From 21ec8864c33a21ab6fedb220e92318c3e9f2c940 Mon Sep 17 00:00:00 2001 From: Louis Stermole Date: Tue, 28 Feb 2017 13:02:04 -0600 Subject: Disable RTT_WR during WR_LEVEL cal step, and set equivalent terminations Change-Id: Ie813c26588d803371e35790ab9b233630c5041b4 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/37203 Tested-by: Jenkins Server Tested-by: Hostboot CI Reviewed-by: Brian R. Silver Reviewed-by: JACOB L. HARVEY Dev-Ready: Louis Stermole Reviewed-by: Matt K. Light Reviewed-by: Christian R. Geddes Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/37702 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell --- .../hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C | 176 +++++++++- .../hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H | 218 ++++++++++++- .../hwp/memory/lib/mss_attribute_accessors.H | 90 ++++++ .../p9/procedures/hwp/memory/lib/phy/ddr_phy.C | 356 +++++++++++++++++++-- .../p9/procedures/hwp/memory/lib/phy/ddr_phy.H | 171 +++++++++- .../chips/p9/procedures/hwp/memory/lib/phy/seq.H | 3 +- .../procedures/hwp/memory/lib/shared/mss_const.H | 1 + .../hwp/memory/p9_mss_draminit_training.C | 36 +-- .../xml/attribute_info/memory_mcs_attributes.xml | 16 + .../error_info/p9_memory_mss_general_errors.xml | 32 ++ .../fapi2/xml/attribute_info/hb_temp_defaults.xml | 4 + .../targeting/common/xmltohb/attribute_types.xml | 19 ++ src/usr/targeting/common/xmltohb/target_types.xml | 1 + 13 files changed, 1056 insertions(+), 67 deletions(-) diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C index 7f42d97d6..850244d4a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,6 +42,7 @@ #include using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_DIMM; using fapi2::FAPI2_RC_SUCCESS; @@ -158,5 +159,178 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Maps RTT_WR setting to equivalent RTT_NOM setting +/// Specialization for TARGET_TYPE_DIMM +/// @param[in] i_target a DIMM target +/// @param[in] i_rtt_wr an RTT_WR setting +/// @param[out] o_rtt_nom equivalent RTT_NOM setting +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template<> +fapi2::ReturnCode rtt_wr_to_rtt_nom_helper(const fapi2::Target& i_target, + const uint8_t i_rtt_wr, + uint8_t& o_rtt_nom) +{ + switch(i_rtt_wr) + { + case RTT_WR_DYNAMIC_ODT_OFF: + case RTT_WR_HIZ: + o_rtt_nom = RTT_NOM_DISABLE; + break; + + case RTT_WR_RZQ_OVER_3: + o_rtt_nom = RTT_NOM_RZQ_OVER_3; + break; + + case RTT_WR_RZQ_OVER_2: + o_rtt_nom = RTT_NOM_RZQ_OVER_2; + break; + + case RTT_WR_RZQ_OVER_1: + o_rtt_nom = RTT_NOM_RZQ_OVER_1; + break; + + default: + FAPI_ASSERT( false, + fapi2::MSS_INVALID_RTT_WR_ENCODING(). + set_RTT_WR(i_rtt_wr). + set_TARGET(i_target), + "Received invalid RTT_WR value: 0x%02x for %s.", + i_rtt_wr, mss::c_str(i_target) ); + break; + } + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes CCS instructions to set RTT_WR value into RTT_NOM +/// Specialization for TARGET_TYPE_DIMM +/// @param[in] i_target a DIMM target +/// @param[in] i_rank selected rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template<> +fapi2::ReturnCode rtt_nom_override(const fapi2::Target& i_target, + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst) +{ + uint8_t l_rtt_nom_override_disable = 0; + uint8_t l_rtt_wr_value[MAX_RANK_PER_DIMM] = {0}; + uint8_t l_rtt_nom_value[MAX_RANK_PER_DIMM] = {0}; + + // eff_dram* attributes use a per-DIMM rank index, so get that + const auto l_rank_idx = mss::index(i_rank); + + FAPI_TRY( mss::rtt_nom_override_disable(i_target, l_rtt_nom_override_disable) ); + + if ( fapi2::ENUM_ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE_YES == l_rtt_nom_override_disable ) + { + return fapi2::FAPI2_RC_SUCCESS; + } + + // Map RTT_WR settings to RTT_NOM + FAPI_TRY( mss::eff_dram_rtt_wr(i_target, &(l_rtt_wr_value[0])) ); + FAPI_TRY( rtt_wr_to_rtt_nom_helper(i_target, l_rtt_wr_value[l_rank_idx], l_rtt_nom_value[l_rank_idx]) ); + + // Write the override values to RTT_NOM + FAPI_DBG("Overriding RTT_NOM value to 0x%01x to match original RTT_WR value 0x%01x on rank %d", + l_rtt_nom_value[l_rank_idx], l_rtt_wr_value[l_rank_idx], i_rank); + FAPI_TRY( rtt_nom_load(i_target, l_rtt_nom_value, i_rank, io_inst) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes CCS instructions to disable RTT_WR +/// Specialization for TARGET_TYPE_DIMM +/// @param[in] i_target a DIMM target +/// @param[in] i_rank selected rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template<> +fapi2::ReturnCode rtt_wr_disable(const fapi2::Target& i_target, + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst) +{ + uint8_t l_rtt_wr_value[MAX_RANK_PER_DIMM] = {0}; + + // eff_dram* attributes use a per-DIMM rank index, so get that + const auto l_rank_idx = mss::index(i_rank); + + // Write RTT_WR setting for the given rank to RTT_WR_DYNAMIC_ODT_OFF + FAPI_TRY( mss::eff_dram_rtt_wr(i_target, &(l_rtt_wr_value[0])) ); + l_rtt_wr_value[l_rank_idx] = RTT_WR_DYNAMIC_ODT_OFF; + + FAPI_TRY( rtt_wr_load(i_target, l_rtt_wr_value, i_rank, io_inst) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes CCS instructions to restore original value of RTT_NOM +/// Specialization for TARGET_TYPE_DIMM +/// @param[in] i_target a DIMM target +/// @param[in] i_rank selected rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template<> +fapi2::ReturnCode rtt_nom_restore(const fapi2::Target& i_target, + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst) +{ + uint8_t l_rtt_nom_override_disable = 0; + uint8_t l_rtt_nom_value[MAX_RANK_PER_DIMM] = {0}; + + FAPI_TRY( mss::rtt_nom_override_disable(i_target, l_rtt_nom_override_disable) ); + + if ( fapi2::ENUM_ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE_YES == l_rtt_nom_override_disable ) + { + return fapi2::FAPI2_RC_SUCCESS; + } + + // Get original RTT_NOM value + FAPI_TRY( mss::eff_dram_rtt_nom(i_target, &(l_rtt_nom_value[0])) ); + + // Write the value to RTT_NOM + FAPI_TRY( rtt_nom_load(i_target, l_rtt_nom_value, i_rank, io_inst) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes CCS instructions to restore original value of RTT_WR +/// Specialization for TARGET_TYPE_DIMM +/// @param[in] i_target a DIMM target +/// @param[in] i_rank selected rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template<> +fapi2::ReturnCode rtt_wr_restore(const fapi2::Target& i_target, + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst) +{ + // Get original RTT_WR value + uint8_t l_rtt_wr_value[MAX_RANK_PER_DIMM] = {0}; + FAPI_TRY( mss::eff_dram_rtt_wr(i_target, &(l_rtt_wr_value[0])) ); + + // Write the value to RTT_WR + FAPI_TRY( rtt_wr_load(i_target, l_rtt_wr_value, i_rank, io_inst) ); + +fapi_try_exit: + return fapi2::current_err; +} + } // ns ddr4 } // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H index 652f2d388..20e3aff35 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H @@ -74,6 +74,29 @@ enum address_bits BG1 = 15, }; +// RTT_WR settings in MR2 from JEDEC DDR4 spec +enum rtt_wr_settings +{ + RTT_WR_DYNAMIC_ODT_OFF = 0b000, + RTT_WR_RZQ_OVER_2 = 0b001, + RTT_WR_RZQ_OVER_1 = 0b010, + RTT_WR_HIZ = 0b011, + RTT_WR_RZQ_OVER_3 = 0b100, +}; + +// RTT_NOM settings in MR1 from JEDEC DDR4 spec +enum rtt_nom_settings +{ + RTT_NOM_DISABLE = 0b000, + RTT_NOM_RZQ_OVER_4 = 0b001, + RTT_NOM_RZQ_OVER_2 = 0b010, + RTT_NOM_RZQ_OVER_6 = 0b011, + RTT_NOM_RZQ_OVER_1 = 0b100, + RTT_NOM_RZQ_OVER_5 = 0b101, + RTT_NOM_RZQ_OVER_3 = 0b110, + RTT_NOM_RZQ_OVER_7 = 0b111, +}; + /// /// @brief Mirror (front to back) the ADR bits of a CCS instruction - implementation /// @tparam T typename of the ccs::instruction_t @@ -1001,7 +1024,7 @@ fapi2::ReturnCode mrs_load( const fapi2::Target& i_targ std::vector< ccs::instruction_t >& io_inst); /// -/// @brief Set MPR Mode +/// @brief Set MPR Mode /// @param[in] i_target a DIMM target /// @param[in] i_mode setting for MPR mode /// @param[in,out] io_data data we are modifying MPR mode to @@ -1025,6 +1048,62 @@ inline fapi2::ReturnCode set_dram_mpr_mode(const fapi2::Target& i_target, + const uint8_t i_value[MAX_RANK_PER_DIMM], + mrs01_data& io_data) +{ + constexpr uint64_t MAX_RTT_NOM = RTT_NOM_RZQ_OVER_7; + + for (size_t l_rank = 0; l_rank < MAX_RANK_PER_DIMM; ++l_rank) + { + if(i_value[l_rank] > MAX_RTT_NOM) + { + FAPI_ERR("Invalid RTT_NOM value recieved: %d. Max encoding allowed: %d.", i_value[l_rank], MAX_RTT_NOM); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + } + + // Update field if input check passes + io_data.iv_rtt_nom[l_rank] = i_value[l_rank]; + } + + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Set RTT_WR values in an mrs02_data object +/// @param[in] i_target a DIMM target +/// @param[in] i_value settings for RTT_WR +/// @param[in,out] io_data data we are modifying RTT_WR to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +inline fapi2::ReturnCode set_dram_rtt_wr(const fapi2::Target& i_target, + const uint8_t i_value[MAX_RANK_PER_DIMM], + mrs02_data& io_data) +{ + constexpr uint64_t MAX_RTT_WR = RTT_WR_RZQ_OVER_3; + + for (size_t l_rank = 0; l_rank < MAX_RANK_PER_DIMM; ++l_rank) + { + if(i_value[l_rank] > MAX_RTT_WR) + { + FAPI_ERR("Invalid RTT_WR value recieved: %d. Max encoding allowed: %d.", i_value[l_rank], MAX_RTT_WR); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + } + + // Update field if input check passes + io_data.iv_dram_rtt_wr[l_rank] = i_value[l_rank]; + } + + return fapi2::FAPI2_RC_SUCCESS; +} + /// /// @brief Set MPR Read /// @param[in] i_target a DIMM target @@ -1151,6 +1230,74 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Makes CCS instruction to set RTT_NOM value +/// @tparam T TargetType of the CCS instruction +/// @param[in] i_target a DIMM target +/// @param[in] i_value values to set to RTT_NOM +/// @param[in] i_rank DIMM rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType T > +fapi2::ReturnCode rtt_nom_load(const fapi2::Target& i_target, + const uint8_t i_value[MAX_RANK_PER_DIMM], + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst ) +{ + // tMRD (clock cycles) must be satisfied after an MRS command + constexpr uint64_t l_delay = mss::tmrd(); + + mrs01_data l_data(i_target, fapi2::current_err); + FAPI_TRY(fapi2::current_err, "%s. Failed to initialize mrs01_data for rtt_nom_load", mss::c_str(i_target) ); + + FAPI_TRY( set_dram_rtt_nom(i_target, i_value, l_data), + "%s. Failed set_dram_rtt_nom()", + mss::c_str(i_target)); + + // Make MRS CCS inst + FAPI_TRY( mrs_engine(i_target, l_data, i_rank, l_delay, io_inst), + "Failed to send MRS01 on %s, rank: %d", + mss::c_str(i_target), i_rank); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Makes CCS instruction to set RTT_WR value +/// @tparam T TargetType of the CCS instruction +/// @param[in] i_target a DIMM target +/// @param[in] i_value values to set to RTT_WR +/// @param[in] i_rank DIMM rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType T > +fapi2::ReturnCode rtt_wr_load(const fapi2::Target& i_target, + const uint8_t i_value[MAX_RANK_PER_DIMM], + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst ) +{ + // tMRD (clock cycles) must be satisfied after an MRS command + constexpr uint64_t l_delay = mss::tmrd(); + + mrs02_data l_data(i_target, fapi2::current_err); + FAPI_TRY(fapi2::current_err, "%s. Failed to initialize mrs02_data for rtt_wr_load", mss::c_str(i_target) ); + + FAPI_TRY( set_dram_rtt_wr(i_target, i_value, l_data), + "%s. Failed set_dram_rtt_wr()", + mss::c_str(i_target)); + + // Make MRS CCS inst + FAPI_TRY( mrs_engine(i_target, l_data, i_rank, l_delay, io_inst), + "Failed to send MRS02 on %s, rank: %d", + mss::c_str(i_target), i_rank); + +fapi_try_exit: + return fapi2::current_err; +} + /// /// @brief Makes CCS instruction for an MPR read /// @tparam T TargetType of the CCS instruction @@ -1234,6 +1381,75 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Maps RTT_WR setting to equivalent RTT_NOM setting +/// @tparam T TargetType of the DIMM +/// @param[in] i_target a DIMM target +/// @param[in] i_rtt_wr an RTT_WR setting +/// @param[out] o_rtt_nom equivalent RTT_NOM setting +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType T > +fapi2::ReturnCode rtt_wr_to_rtt_nom_helper(const fapi2::Target& i_target, + const uint8_t i_rtt_wr, + uint8_t& o_rtt_nom); + +/// +/// @brief Executes CCS instructions to set RTT_WR value into RTT_NOM +/// @tparam T TargetType of the DIMM +/// @tparam CT TargetType of the CCS instruction +/// @param[in] i_target a DIMM target +/// @param[in] i_rank selected rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType T, fapi2::TargetType CT > +fapi2::ReturnCode rtt_nom_override(const fapi2::Target& i_target, + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst); + +/// +/// @brief Executes CCS instructions to disable RTT_WR +/// @tparam T TargetType of the DIMM +/// @tparam CT TargetType of the CCS instruction +/// @param[in] i_target a DIMM target +/// @param[in] i_rank selected rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType T, fapi2::TargetType CT > +fapi2::ReturnCode rtt_wr_disable(const fapi2::Target& i_target, + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst); + +/// +/// @brief Executes CCS instructions to restore original value to RTT_NOM +/// @tparam T TargetType of the DIMM +/// @tparam CT TargetType of the CCS instruction +/// @param[in] i_target a DIMM target +/// @param[in] i_rank selected rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType T, fapi2::TargetType CT > +fapi2::ReturnCode rtt_nom_restore(const fapi2::Target& i_target, + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst); + +/// +/// @brief Executes CCS instructions to restore original value to RTT_WR +/// @tparam T TargetType of the DIMM +/// @tparam CT TargetType of the CCS instruction +/// @param[in] i_target a DIMM target +/// @param[in] i_rank selected rank +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType T, fapi2::TargetType CT > +fapi2::ReturnCode rtt_wr_restore(const fapi2::Target& i_target, + const uint64_t i_rank, + std::vector< ccs::instruction_t >& io_inst); + } // ddr4 } // mss #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H index 5d76833db..002df9591 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 @@ -16989,6 +16989,96 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE getter +/// @param[in] const ref to the fapi2::Target +/// @param[out] ref to the value uint8_t +/// @note Generated by gen_accessors.pl generateParameters (F) +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK +/// @note Set equal to 1 to disable setting of RTT_NOM to use RTT_WR values during +/// WR_LEVEL +/// calibration. +/// +inline fapi2::ReturnCode rtt_nom_override_disable(const fapi2::Target& i_target, + uint8_t& o_value) +{ + uint8_t l_value[2][2]; + auto l_mca = i_target.getParent(); + auto l_mcs = l_mca.getParent(); + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE, l_mcs, l_value) ); + o_value = l_value[mss::index(l_mca)][mss::index(i_target)]; + return fapi2::current_err; + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE: 0x%lx (target: %s)", + uint64_t(fapi2::current_err), mss::c_str(i_target)); + return fapi2::current_err; +} + +/// +/// @brief ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE getter +/// @param[in] const ref to the fapi2::Target +/// @param[out] uint8_t* memory to store the value +/// @note Generated by gen_accessors.pl generateParameters (G) +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK +/// @note Set equal to 1 to disable setting of RTT_NOM to use RTT_WR values during +/// WR_LEVEL +/// calibration. +/// +inline fapi2::ReturnCode rtt_nom_override_disable(const fapi2::Target& i_target, + uint8_t* o_array) +{ + if (o_array == nullptr) + { + FAPI_ERR("nullptr passed to attribute accessor %s", __func__); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + } + + uint8_t l_value[2][2]; + auto l_mcs = i_target.getParent(); + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE, l_mcs, l_value) ); + memcpy(o_array, &(l_value[mss::index(i_target)][0]), 2); + return fapi2::current_err; + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE: 0x%lx (target: %s)", + uint64_t(fapi2::current_err), mss::c_str(i_target)); + return fapi2::current_err; +} + +/// +/// @brief ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE getter +/// @param[in] const ref to the fapi2::Target +/// @param[out] uint8_t* memory to store the value +/// @note Generated by gen_accessors.pl generateParameters (H) +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK +/// @note Set equal to 1 to disable setting of RTT_NOM to use RTT_WR values during +/// WR_LEVEL +/// calibration. +/// +inline fapi2::ReturnCode rtt_nom_override_disable(const fapi2::Target& i_target, + uint8_t* o_array) +{ + if (o_array == nullptr) + { + FAPI_ERR("nullptr passed to attribute accessor %s", __func__); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + } + + uint8_t l_value[2][2]; + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE, i_target, l_value) ); + memcpy(o_array, &l_value, 4); + return fapi2::current_err; + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE: 0x%lx (target: %s)", + uint64_t(fapi2::current_err), mss::c_str(i_target)); + return fapi2::current_err; +} + /// /// @brief ATTR_EFF_DRAM_GEN getter diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C index 029b7a61e..69ceaf8ed 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C @@ -875,10 +875,10 @@ fapi2::ReturnCode setup_cal_config( const fapi2::Target& FAPI_TRY(mss::scom_blastah(i_target, mss::dp16Traits::WR_VREF_CONFIG0_REG, l_vref_config)); } - // Latches in the WR VREF values // loops through all RP's running workarounds and latching the VREF's as need be for(const auto& l_rp : i_rank_pairs) { + // Latches in the WR VREF values // Overrides will be set by mss::workarounds::wr_vref::execute. // If the execute code is skipped, then it will read from the attributes uint8_t l_vrefdq_train_range_override = mss::ddr4::USE_DEFAULT_WR_VREF_SETTINGS; @@ -934,19 +934,155 @@ fapi2::ReturnCode setup_cal_config( const fapi2::Target& } /// -/// @brief Setup odt_wr/rd_config +/// @brief Execute a set of PHY cal steps +/// Specializaton for TARGET_TYPE_MCA +/// @param[in] i_target the target associated with this cal +/// @param[in] i_rp one of the currently configured rank pairs +/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable +/// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// @note This is a helper function. Library users are required to call setup_and_execute_cal +/// +template<> +fapi2::ReturnCode execute_cal_steps_helper( const fapi2::Target& i_target, + const uint64_t i_rp, + const fapi2::buffer i_cal_steps_enabled, + const uint8_t i_abort_on_error) +{ + const auto& l_mcbist = mss::find_target(i_target); + auto l_cal_inst = mss::ccs::initial_cal_command(i_rp); + + mss::ccs::program l_program; + + // Sanity check due to WR_LEVEL termination requirement + if ((i_cal_steps_enabled.getBit()) && + (mss::bit_count(static_cast(i_cal_steps_enabled)) != 1)) + { + FAPI_ERR("WR_LEVEL cal step requires special terminations, so must be run separately from other cal steps"); + fapi2::Assert(false); + } + + FAPI_DBG("executing training CCS instruction: 0x%llx, 0x%llx", l_cal_inst.arr0, l_cal_inst.arr1); + + // Delays in the CCS instruction ARR1 for training are supposed to be 0xFFFF, + // and we're supposed to poll for the done or timeout bit. But we don't want + // to wait 0xFFFF cycles before we start polling - that's too long. So we put + // in a best-guess of how long to wait. This, in a perfect world, would be the + // time it takes one rank to train one training algorithm times the number of + // ranks we're going to train. We fail-safe as worst-case we simply poll the + // register too much - so we can tune this as we learn more. + l_program.iv_poll.iv_initial_sim_delay = 200; + l_program.iv_poll.iv_poll_count = 0xFFFF; + l_program.iv_instructions.push_back(l_cal_inst); + + // We need to figure out how long to wait before we start polling. Each cal step has an expected + // duration, so for each cal step which was enabled, we update the CCS program. + FAPI_TRY( mss::cal_timer_setup(i_target, l_program.iv_poll, i_cal_steps_enabled) ); + FAPI_TRY( mss::setup_cal_config(i_target, i_rp, i_cal_steps_enabled) ); + + // In the event of an init cal hang, CCS_STATQ(2) will assert and CCS_STATQ(3:5) = “001” to indicate a + // timeout. Otherwise, if calibration completes, FW should inspect DDRPHY_FIR_REG bits (50) and (58) + // for signs of a calibration error. If either bit is on, then the DDRPHY_PC_INIT_CAL_ERROR register + // should be polled to determine which calibration step failed. + + // If we got a cal timeout, or another CCS error just leave now. If we got success, check the error + // bits for a cal failure. We'll return the proper ReturnCode so all we need to do is FAPI_TRY. + FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Perform necessary termination setup and execute a set of PHY cal steps +/// Specializaton for TARGET_TYPE_MCA +/// @param[in] i_target the target associated with this cal +/// @param[in] i_rp one of the currently configured rank pairs +/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable +/// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode setup_and_execute_cal( const fapi2::Target& i_target, + const uint64_t i_rp, + const fapi2::buffer i_cal_steps_enabled, + const uint8_t i_abort_on_error) +{ + const auto& l_mcbist = mss::find_target(i_target); + + // We run the cal steps in three chunks: pre-write-leveling, write-leveling, post-wirte-leveling. + // This is because write-leveling requires a special set of termination values. + + // Run cal steps before WR_LEVEL if selected + if (i_cal_steps_enabled.getBit()) + { + FAPI_DBG("%s Running EXT_ZQCAL step on RP%d", mss::c_str(i_target), i_rp); + fapi2::buffer l_steps_to_execute; + l_steps_to_execute.setBit(); + FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) ); + } + + // Run WR_LEVEL step (with overridden termination values) if selected + if (i_cal_steps_enabled.getBit()) + { + mss::ccs::program l_program; + std::vector< ccs::instruction_t > l_rtt_inst; + + FAPI_DBG("%s Running WR_LEVEL step on RP%d", mss::c_str(i_target), i_rp); + fapi2::buffer l_steps_to_execute; + l_steps_to_execute.setBit(); + + // Setup WR_LEVEL specific terminations + // JEDEC spec requires disabling RTT_WR during WR_LEVEL, and enabling equivalent terminations + FAPI_TRY( setup_wr_level_terminations(i_target, i_rp, l_rtt_inst) ); + + if (!l_rtt_inst.empty()) + { + l_program.iv_instructions.insert(l_program.iv_instructions.end(), l_rtt_inst.begin(), l_rtt_inst.end() ); + FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) ); + l_program.iv_instructions.clear(); + } + + // Execute WR_LEVEL + FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) ); + + // Restore normal terminations + l_rtt_inst.clear(); + FAPI_TRY( restore_mainline_terminations(i_target, i_rp, l_rtt_inst) ); + + if (!l_rtt_inst.empty()) + { + l_program.iv_instructions.insert(l_program.iv_instructions.end(), l_rtt_inst.begin(), l_rtt_inst.end() ); + FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) ); + } + } + + // Run cal steps after WR_LEVEL if any are selected + if (i_cal_steps_enabled.getBit()) + { + FAPI_DBG("%s Running remaining cal steps on RP%d", mss::c_str(i_target), i_rp); + fapi2::buffer l_steps_to_execute = i_cal_steps_enabled; + l_steps_to_execute.clearBit().clearBit(); + FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +// TODO RTC:167929 Can ODT VPD processing be shared between RD and WR? +/// +/// @brief Setup odt_rd_config /// @param[in] i_target the MCA target /// @param[in] i_dimm_count the number of DIMM presently on the target /// @param[in] i_odt_rd the RD ODT values from VPD -/// @param[in] i_odt_wr the WR ODT values from VPD /// @return FAPI2_RC_SUCCESS iff setup was successful /// template<> -fapi2::ReturnCode reset_odt_config_helper( +fapi2::ReturnCode reset_odt_rd_config_helper( const fapi2::Target& i_target, const uint64_t i_dimm_count, - const uint8_t i_odt_rd[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM], - const uint8_t i_odt_wr[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]) + const uint8_t i_odt_rd[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]) { // The fields in the ODT VPD are 8 bits wide, but we only use the left-most 2 bits // of each nibble. The encoding for each rank in the VPD is @@ -959,9 +1095,6 @@ fapi2::ReturnCode reset_odt_config_helper +fapi2::ReturnCode reset_odt_wr_config_helper( + const fapi2::Target& i_target, + const uint64_t i_dimm_count, + const uint8_t i_odt_wr[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]) +{ + // The fields in the ODT VPD are 8 bits wide, but we only use the left-most 2 bits + // of each nibble. The encoding for each rank in the VPD is + // [Dimm0 ODT0][Dimm0 ODT1][N/A][N/A][Dimm1 ODT0][Dimm1 ODT1][N/A][N/A] + + constexpr uint64_t BIT_FIELD0_START = 0; + constexpr uint64_t BIT_FIELD1_START = 4; + constexpr uint64_t BIT_FIELD_LENGTH = 2; + + // Nimbus PHY is more or less hard-wired for 2 DIMM/port 4R/DIMM + // So there's not much point in looping over DIMM or ranks. - // - // ODT Write - // { // DPHY01_DDRPHY_SEQ_ODT_WR_CONFIG0_P0 // 48:55, ATTR_VPD_ODT_WR[0][0][0]; # when Read of Rank0 @@ -1080,23 +1236,185 @@ fapi_try_exit: } /// -/// @brief Setup odt_wr/rd_config, reads attributes +/// @brief Setup odt_rd_config, reads attributes /// @param[in] i_target the MCA target associated with this cal setup /// @return FAPI2_RC_SUCCESS iff setup was successful /// template<> -fapi2::ReturnCode reset_odt_config( const fapi2::Target& i_target ) +fapi2::ReturnCode reset_odt_rd_config( const fapi2::Target& i_target ) { uint8_t l_odt_rd[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]; - uint8_t l_odt_wr[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]; - uint64_t l_dimm_count = count_dimm(i_target); + const uint64_t l_dimm_count = count_dimm(i_target); FAPI_TRY( mss::vpd_mt_odt_rd(i_target, &(l_odt_rd[0][0])) ); + + return reset_odt_rd_config_helper( + i_target, l_dimm_count, l_odt_rd); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Setup odt_wr_config, reads attributes +/// @param[in] i_target the MCA target associated with this cal setup +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode reset_odt_wr_config( const fapi2::Target& i_target ) +{ + uint8_t l_odt_wr[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]; + + const uint64_t l_dimm_count = count_dimm(i_target); + + FAPI_TRY( mss::vpd_mt_odt_wr(i_target, &(l_odt_wr[0][0])) ); + + return reset_odt_wr_config_helper( + i_target, l_dimm_count, l_odt_wr); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Override odt_wr_config to enabled for a given rank +/// @param[in] i_target the MCA target associated with this cal setup +/// @param[in] i_rank the rank to override +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode override_odt_wr_config( const fapi2::Target& i_target, + const uint64_t& i_rank) +{ + uint8_t l_odt_wr[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {0}; + fapi2::buffer l_odt_wr_buf; + + const uint64_t l_dimm_count = count_dimm(i_target); + + // read the attributes FAPI_TRY( mss::vpd_mt_odt_wr(i_target, &(l_odt_wr[0][0])) ); - return reset_odt_config_helper( - i_target, l_dimm_count, l_odt_rd, l_odt_wr); + // set the ODTs for the rank selected + // The ODT encoding is (for mranks only) + // [R0 ODT][R1 ODT][N/A][N/A][R4 ODT][R5 ODT][N/A][N/A] + // For WR_LEVEL we only want to set the ODT bit for the selected mrank + l_odt_wr_buf = l_odt_wr[mss::rank::get_dimm_from_rank(i_rank)][mss::index(i_rank)]; + FAPI_TRY( l_odt_wr_buf.setBit(i_rank) ); + l_odt_wr[mss::rank::get_dimm_from_rank(i_rank)][mss::index(i_rank)] = l_odt_wr_buf; + + return reset_odt_wr_config_helper( + i_target, l_dimm_count, l_odt_wr); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Setup terminations for WR_LEVEL cal for a given RP +/// @param[in] i_target the MCA target associated with this cal setup +/// @param[in] i_rp selected rank pair +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode setup_wr_level_terminations( const fapi2::Target& i_target, + const uint64_t i_rp, + std::vector< ccs::instruction_t >& io_inst) +{ + // Danger: Make sure this DIMM target doesn't get used/accessed until it is populated + // by get_dimm_target_from_rank below! + fapi2::Target l_dimm; + std::vector l_ranks; + uint8_t l_rtt_wr_value[MAX_RANK_PER_DIMM] = {0}; + + // mrank will be l_ranks[0] from get_ranks_in_pair + FAPI_TRY( mss::rank::get_ranks_in_pair(i_target, i_rp, l_ranks) ); + FAPI_ASSERT( !l_ranks.empty(), + fapi2::MSS_NO_RANKS_IN_RANK_PAIR() + .set_TARGET(i_target) + .set_RANK_PAIR(i_rp), + "No ranks configured in MCA %s, rank pair %d", mss::c_str(i_target), i_rp ); + + FAPI_INF("%s Setting up terminations for WR_LEVEL, MRANK %d", mss::c_str(i_target), l_ranks[0]); + + // Get DIMM target + FAPI_TRY( mss::rank::get_dimm_target_from_rank(i_target, l_ranks[0], l_dimm) ); + + // Get RTT_WR value + FAPI_TRY( mss::eff_dram_rtt_wr(l_dimm, &(l_rtt_wr_value[0])) ); + + // If RTT_WR is not enabled for pair's mrank, we're done + if (l_rtt_wr_value[mss::index(l_ranks[0])] == RTT_WR_DYNAMIC_ODT_OFF) + { + FAPI_INF("%s RTT_WR not set for MRANK %d, no termination adjustment necessary", mss::c_str(i_target), l_ranks[0]); + return fapi2::FAPI2_RC_SUCCESS; + } + + // Disable RTT_WR for the pair's mrank + FAPI_TRY( mss::ddr4::rtt_wr_disable(l_dimm, l_ranks[0], io_inst) ); + + // Write the RTT_WR value into RTT_NOM + FAPI_TRY( mss::ddr4::rtt_nom_override(l_dimm, l_ranks[0], io_inst) ); + + // Set ODT so we get RTT_NOM for writes + FAPI_TRY( override_odt_wr_config(i_target, l_ranks[0]) ); + FAPI_TRY( mss::workarounds::seq::odt_config(i_target) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Restore normal terminations after WR_LEVEL cal for a given RP +/// @param[in] i_target the MCA target associated with this cal setup +/// @param[in] i_rp selected rank pair +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode restore_mainline_terminations( const fapi2::Target& i_target, + const uint64_t i_rp, + std::vector< ccs::instruction_t >& io_inst) +{ + // Danger: Make sure this DIMM target doesn't get used/accessed until it is populated + // by get_dimm_target_from_rank below! + fapi2::Target l_dimm; + std::vector l_ranks; + uint8_t l_rtt_wr_value[MAX_RANK_PER_DIMM] = {0}; + + // mrank will be l_ranks[0] from get_ranks_in_pair + FAPI_TRY( mss::rank::get_ranks_in_pair(i_target, i_rp, l_ranks) ); + FAPI_ASSERT( !l_ranks.empty(), + fapi2::MSS_NO_RANKS_IN_RANK_PAIR() + .set_TARGET(i_target) + .set_RANK_PAIR(i_rp), + "No ranks configured in MCA %s, rank pair %d", mss::c_str(i_target), i_rp ); + + FAPI_INF("%s Restoring terminations after WR_LEVEL, MRANK %d", mss::c_str(i_target), l_ranks[0]); + + // Get DIMM target + FAPI_TRY( mss::rank::get_dimm_target_from_rank(i_target, l_ranks[0], l_dimm) ); + + // Get RTT_WR value + FAPI_TRY( mss::eff_dram_rtt_wr(l_dimm, &(l_rtt_wr_value[0])) ); + + // If RTT_WR is not enabled for pair's mrank, we're done + if (l_rtt_wr_value[mss::index(l_ranks[0])] == RTT_WR_DYNAMIC_ODT_OFF) + { + FAPI_INF("%s RTT_WR not set for MRANK %d, no termination adjustment necessary", mss::c_str(i_target), l_ranks[0]); + return fapi2::FAPI2_RC_SUCCESS; + } + + // Restore RTT_WR for the pair's mrank + FAPI_TRY( mss::ddr4::rtt_wr_restore(l_dimm, l_ranks[0], io_inst) ); + + // Restore RTT_NOM + FAPI_TRY( mss::ddr4::rtt_nom_restore(l_dimm, l_ranks[0], io_inst) ); + + // Restore ODT + FAPI_TRY( reset_odt_wr_config(i_target) ); + FAPI_TRY( mss::workarounds::seq::odt_config(i_target) ); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H index 7f0d9042f..f3a4cd89d 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H @@ -38,6 +38,7 @@ #include #include +#include namespace mss { @@ -149,55 +150,203 @@ fapi2::ReturnCode setup_cal_config( const fapi2::Target& const uint64_t i_rank, const fapi2::buffer i_cal_steps_enabled); -// TODO RTC: 157753 tparams P and R can be pulled from an MCA trait once we have it /// -/// @brief Setup odt_wr/rd_config +/// @brief Execute a set of PHY cal steps +/// @tparam T, the target type of the MCA/MBA +/// @param[in] i_target the target associated with this cal +/// @param[in] i_rp one of the currently configured rank pairs +/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable +/// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// @note This is a helper function. Library users are required to call setup_and_execute_cal +/// +template< fapi2::TargetType T > +fapi2::ReturnCode execute_cal_steps_helper( const fapi2::Target& i_target, + const uint64_t i_rp, + const fapi2::buffer i_cal_steps_enabled, + const uint8_t i_abort_on_error); + +/// +/// @brief Perform necessary termination setup and execute a set of PHY cal steps +/// @tparam T, the target type of the MCA/MBA +/// @param[in] i_target the target associated with this cal +/// @param[in] i_rp one of the currently configured rank pairs +/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable +/// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template< fapi2::TargetType T > +fapi2::ReturnCode setup_and_execute_cal( const fapi2::Target& i_target, + const uint64_t i_rp, + const fapi2::buffer i_cal_steps_enabled, + const uint8_t i_abort_on_error); + +// TODO RTC:167929 Can ODT VPD processing be shared between RD and WR? +// TODO RTC:157753 tparams P and R can be pulled from an MCA trait once we have it +/// +/// @brief Setup odt_rd_config /// @tparam T the target type of the MCA/MBA /// @tparam P the maximum DIMM per T /// @tparam R the maximum rank per DIMM on T /// @param[in] i_target the target /// @param[in] i_dimm_count the number of DIMM presently on the target /// @param[in] i_odt_rd the RD ODT values from VPD +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template< fapi2::TargetType T, uint64_t P, uint64_t R > +fapi2::ReturnCode reset_odt_rd_config_helper( const fapi2::Target& i_target, + const uint64_t i_dimm_count, + const uint8_t i_odt_rd[P][R] ); + +// TODO RTC:167929 Can ODT VPD processing be shared between RD and WR? +// TODO RTC:157753 tparams P and R can be pulled from an MCA trait once we have it +/// +/// @brief Setup odt_wr_config +/// @tparam T the target type of the MCA/MBA +/// @tparam P the maximum DIMM per T +/// @tparam R the maximum rank per DIMM on T +/// @param[in] i_target the target +/// @param[in] i_dimm_count the number of DIMM presently on the target /// @param[in] i_odt_wr the WR ODT values from VPD /// @return FAPI2_RC_SUCCESS iff setup was successful /// template< fapi2::TargetType T, uint64_t P, uint64_t R > -fapi2::ReturnCode reset_odt_config_helper( const fapi2::Target& i_target, +fapi2::ReturnCode reset_odt_wr_config_helper( const fapi2::Target& i_target, const uint64_t i_dimm_count, - const uint8_t i_odt_rd[P][R], const uint8_t i_odt_wr[P][R] ); /// -/// @brief Setup odt_wr/rd_config +/// @brief Setup odt_rd_config /// @param[in] i_target the MCA target /// @param[in] i_dimm_count the number of DIMM presently on the target /// @param[in] i_odt_rd the RD ODT values from VPD +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode reset_odt_rd_config_helper( + const fapi2::Target& i_target, + const uint64_t i_dimm_count, + const uint8_t i_odt_rd[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]); + +/// +/// @brief Setup odt_wr_config +/// @param[in] i_target the MCA target +/// @param[in] i_dimm_count the number of DIMM presently on the target /// @param[in] i_odt_wr the WR ODT values from VPD /// @return FAPI2_RC_SUCCESS iff setup was successful /// template<> -fapi2::ReturnCode reset_odt_config_helper( +fapi2::ReturnCode reset_odt_wr_config_helper( const fapi2::Target& i_target, const uint64_t i_dimm_count, - const uint8_t i_odt_rd[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM], const uint8_t i_odt_wr[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]); /// -/// @brief Setup odt_wr/rd_config, reads attributes +/// @brief Setup odt_rd_config, reads attributes +/// @tparam T the target type of the MCA/MBA +/// @param[in] i_target the target associated with this cal setup +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template< fapi2::TargetType T > +fapi2::ReturnCode reset_odt_rd_config( const fapi2::Target& i_target ); + +/// +/// @brief Setup odt_rd_config, reads attributes +/// @param[in] i_target the MCA target associated with this cal setup +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode reset_odt_rd_config( const fapi2::Target& i_target ); + +/// +/// @brief Setup odt_wr_config, reads attributes /// @tparam T the target type of the MCA/MBA /// @param[in] i_target the target associated with this cal setup /// @return FAPI2_RC_SUCCESS iff setup was successful /// template< fapi2::TargetType T > -fapi2::ReturnCode reset_odt_config( const fapi2::Target& i_target ); +fapi2::ReturnCode reset_odt_wr_config( const fapi2::Target& i_target ); + +/// +/// @brief Setup odt_wr_config, reads attributes +/// @param[in] i_target the MCA target associated with this cal setup +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode reset_odt_wr_config( const fapi2::Target& i_target ); + +/// +/// @brief Override odt_wr_config to enabled for a given rank +/// @tparam T the target type of the MCA/MBA +/// @param[in] i_target the target associated with this cal setup +/// @param[in] i_rank the rank to override +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template< fapi2::TargetType T > +fapi2::ReturnCode override_odt_wr_config( const fapi2::Target& i_target, + const uint64_t& i_rank); + +/// +/// @brief Override odt_wr_config to enabled for a given rank +/// @param[in] i_target the MCA target associated with this cal setup +/// @param[in] i_rank the rank to override +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode override_odt_wr_config( const fapi2::Target& i_target, + const uint64_t& i_rank); + +/// +/// @brief Setup terminations for WR_LEVEL cal for a given RP +/// @tparam T the target type of the MCA/MBA +/// @tparam CT TargetType of the CCS instruction +/// @param[in] i_target the target associated with this cal setup +/// @param[in] i_rp selected rank pair +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template< fapi2::TargetType T, fapi2::TargetType CT > +fapi2::ReturnCode setup_wr_level_terminations( const fapi2::Target& i_target, + const uint64_t i_rp, + std::vector< ccs::instruction_t >& io_inst); + +/// +/// @brief Setup terminations for WR_LEVEL cal for a given RP +/// @param[in] i_target the MCA target associated with this cal setup +/// @param[in] i_rp selected rank pair +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode setup_wr_level_terminations( const fapi2::Target& i_target, + const uint64_t i_rp, + std::vector< ccs::instruction_t >& io_inst); + +/// +/// @brief Restore terminations after WR_LEVEL cal for a given RP +/// @tparam T the target type of the MCA/MBA +/// @tparam CT TargetType of the CCS instruction +/// @param[in] i_target the target associated with this cal setup +/// @param[in] i_rp selected rank pair +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template< fapi2::TargetType T, fapi2::TargetType CT > +fapi2::ReturnCode restore_mainline_terminations( const fapi2::Target& i_target, + const uint64_t i_rp, + std::vector< ccs::instruction_t >& io_inst); /// -/// @brief Setup odt_wr/rd_config, reads attributes +/// @brief Restore terminations after WR_LEVEL cal for a given RP /// @param[in] i_target the MCA target associated with this cal setup +/// @param[in] i_rp selected rank pair +/// @param[in,out] io_inst a vector of CCS instructions we should add to /// @return FAPI2_RC_SUCCESS iff setup was successful /// template<> -fapi2::ReturnCode reset_odt_config( const fapi2::Target& i_target ); +fapi2::ReturnCode restore_mainline_terminations( const fapi2::Target& i_target, + const uint64_t i_rp, + std::vector< ccs::instruction_t >& io_inst); /// /// @brief Perform the DLL calibration diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.H index 6896b19cb..989e672d9 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.H @@ -396,7 +396,8 @@ inline fapi2::ReturnCode reset( const fapi2::Target& i_target ) FAPI_TRY( reset_timing1(i_target) ); FAPI_TRY( reset_timing2(i_target) ); FAPI_TRY( reset_rd_wr_data(i_target) ); - FAPI_TRY( reset_odt_config(i_target) ); + FAPI_TRY( reset_odt_rd_config(i_target) ); + FAPI_TRY( reset_odt_wr_config(i_target) ); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H index 5eee66a56..4cb69e317 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H @@ -153,6 +153,7 @@ enum cal_steps WRITE_CTR_2D_VREF = 7, COARSE_WR = 8, COARSE_RD = 9, + STEPS_AFTER_WR_LEVEL = 8, // represents the number of bits in cal_step_enable after the WR_LEVEL bit }; // Static consts for DDR4 voltages used in p9_mss_volt diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C index 2b371bad4..a4b1f2f0a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C @@ -101,23 +101,6 @@ extern "C" // Keep track of the last error seen by a rank pair fapi2::ReturnCode l_rank_pair_error = fapi2::FAPI2_RC_SUCCESS; - - mss::ccs::program l_program; - - // Setup a series of register probes which we'll see during the polling loop - // Leaving these probes in here as we need them from time to time, but they - // take up a lot of sim time, so we like to remove them simply - - // Delays in the CCS instruction ARR1 for training are supposed to be 0xFFFF, - // and we're supposed to poll for the done or timeout bit. But we don't want - // to wait 0xFFFF cycles before we start polling - that's too long. So we put - // in a best-guess of how long to wait. This, in a perfect world, would be the - // time it takes one rank to train one training algorithm times the number of - // ranks we're going to train. We fail-safe as worst-case we simply poll the - // register too much - so we can tune this as we learn more. - l_program.iv_poll.iv_initial_sim_delay = 200; - l_program.iv_poll.iv_poll_count = 0xFFFF; - // Returned from set_rank_pairs, it tells us how many rank pairs // we configured on this port. std::vector l_pairs; @@ -167,7 +150,6 @@ extern "C" // THE PROCESSING OF THE ERRORS. (it's hard to figure out which DIMM failed, too) BRS. for (const auto& rp : l_pairs) { - auto l_inst = mss::ccs::initial_cal_command(rp); uint8_t cal_abort_on_error = i_abort_on_error; if (i_abort_on_error == CAL_ABORT_SENTINAL) @@ -175,22 +157,8 @@ extern "C" FAPI_TRY( mss::cal_abort_on_error(cal_abort_on_error) ); } - FAPI_DBG("executing training CCS instruction: 0x%llx, 0x%llx", l_inst.arr0, l_inst.arr1); - l_program.iv_instructions.push_back(l_inst); - - // We need to figure out how long to wait before we start polling. Each cal step has an expected - // duration, so for each cal step which was enabled, we update the CCS program. - FAPI_TRY( mss::cal_timer_setup(p, l_program.iv_poll, l_cal_steps_enabled) ); - FAPI_TRY( mss::setup_cal_config(p, rp, l_cal_steps_enabled) ); - - // In the event of an init cal hang, CCS_STATQ(2) will assert and CCS_STATQ(3:5) = “001” to indicate a - // timeout. Otherwise, if calibration completes, FW should inspect DDRPHY_FIR_REG bits (50) and (58) - // for signs of a calibration error. If either bit is on, then the DDRPHY_PC_INIT_CAL_ERROR register - // should be polled to determine which calibration step failed. - - // If we got a cal timeout, or another CCS error just leave now. If we got success, check the error - // bits for a cal failure. We'll return the proper ReturnCode so all we need to do is FAPI_TRY. - FAPI_TRY( mss::ccs::execute(i_target, l_program, p) ); + // Execute selected cal steps + FAPI_TRY( mss::setup_and_execute_cal(p, rp, l_cal_steps_enabled, i_abort_on_error) ); // Conducts workarounds after training if needed FAPI_TRY( mss::workarounds::dp16::post_training_workarounds( p, l_cal_steps_enabled ) ); diff --git a/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml index a05cf332a..4d5a3a80d 100644 --- a/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml +++ b/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml @@ -3144,4 +3144,20 @@ eff_rank_group_override + + ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE + TARGET_TYPE_MCS + + Set equal to 1 to disable setting of RTT_NOM to use RTT_WR values + during WR_LEVEL calibration. + + + uint8 + + NO = 0, YES = 1 + bool + 2 2 + rtt_nom_override_disable + + diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_general_errors.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_general_errors.xml index 2cde5f46b..28883d6ef 100644 --- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_general_errors.xml +++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_general_errors.xml @@ -84,4 +84,36 @@ + + RC_MSS_INVALID_RTT_WR_ENCODING + + An invalid/unsupported RTT_WR encoding was received, possibly due to VPD error or bad + setting of ATTR_EFF_DRAM_RTT_WR attribute. + + RTT_WR + + TARGET + HIGH + + + TARGET + + + + + RC_MSS_NO_RANKS_IN_RANK_PAIR + + A rank pair was received with no configured ranks when setting up terminations + for write leveling calibration. + + RANK_PAIR + + TARGET + HIGH + + + 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 f88495198..8ca8d58d6 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 @@ -90,6 +90,10 @@ ATTR_MSS_MRW_TEMP_REFRESH_MODE 0x0 + + ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE + 0x0 + ATTR_PERF_24x7_INVOCATION_TIME_MS 0x1 diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index 864c19963..2f0a900b0 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -33135,6 +33135,25 @@ Measured in GB + + MSS_RTT_NOM_OVERRIDE_DISABLE + + Set equal to 1 to disable setting of RTT_NOM to use RTT_WR values + during WR_LEVEL calibration. + + + + 2,2 + + volatile-zeroed + + + + ATTR_MSS_RTT_NOM_OVERRIDE_DISABLE + DIRECT + + + EFF_DRAM_RTT_WR diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml index a1197fc25..03ad06aa6 100755 --- a/src/usr/targeting/common/xmltohb/target_types.xml +++ b/src/usr/targeting/common/xmltohb/target_types.xml @@ -1858,6 +1858,7 @@ MSS_DIMM_THERMAL_LIMIT MSS_VREF_CAL_ENABLE MSS_MRW_UNSUPPORTED_RANK_CONFIG + MSS_RTT_NOM_OVERRIDE_DISABLE EFF_DRAM_RTT_NOM EFF_DRAM_RTT_WR EFF_DRAM_RTT_PARK -- cgit v1.2.1