diff options
Diffstat (limited to 'src/import/chips/p9')
22 files changed, 1134 insertions, 87 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/docs/FIR.md b/src/import/chips/p9/procedures/hwp/memory/docs/FIR.md new file mode 100644 index 000000000..1ae411713 --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/docs/FIR.md @@ -0,0 +1,79 @@ + +# How the memory subsystem handles FIR bits + +In order to make handling of FIR bits a bit more straight forward, we have +created a small data structure mss::fir::reg. Given the FIR register which +reports FIR errors, a fir::reg will encapsulate the 2 action registers and +the mask register as well as the reporting register. + +FIR actions, and when FIR are unmasked are defined by the team as a whole, +and are documented outside of the ekb. + +## FIR actions + +FIR actions are configured in 3 parallel registers: action0, action1 and +mask. Bit patterns assigned across these three registers define a response +the system is to take when a FIR bit is asserted. Because they span three +parallel registers, the actions are defined as tripples: + +``` + Action 0 Action 1 Mask + +---+ +---+ +---+ + | 0 | | 0 | | 0 | + +---+ +---+ +---+ +``` + +So, for any bit postion representing a FIR, that corresponding bit in the +three registers defines the system response. Consider "bit 12," to define +a response, we must set the three bits in position 12 in the three +egisters: + +``` + bit 0, ..., bit 12 + + Action 0 Action 1 Mask Action 0 Action 1 Mask + +---+ +---+ +---+ +---+ +---+ +---+ + | 0 | | 0 | | 1 | | 0 | | 0 | | 0 | + +---+ +---+ +---+ ..., +---+ +---+ +---+ ..., +``` + +This represents that the FIR "bit 0" is masked (1 in the mask register bit +position 0) and the FIR "bit 12" should respond with a check-stop (0 in +the action 0 and action 1 registers in bit position 12, and a 0 to represent +the FIR is unmasked. + +## Action Tripples + +The actions are defined as: + +``` + Action 0 Action 1 Mask + +---+ +---+ +---+ + | 0 | | 0 | | 0 | System Checkstop + +---+ +---+ +---+ + + +---+ +---+ +---+ + | 0 | | 1 | | 0 | Recoverable Error + +---+ +---+ +---+ + + +---+ +---+ +---+ + | 1 | | 0 | | 0 | Attention + +---+ +---+ +---+ + + +---+ +---+ +---+ + | 1 | | 1 | | 0 | Local Checkstop + +---+ +---+ +---+ + + +---+ +---+ +---+ + | X | | X | | 1 | Masked + +---+ +---+ +---+ +``` + +## The fir::reg class + +Given this information, the fir::reg class provides a read-modify-write +interface for specific actions, keyed off of the FIR register. For example +fir::reg::checkstop() configures the appropriate action0, action1 and mask bits. +fir::reg::write() ensures all of the configuration is written to the proper +register. Refer to the fir.H documentation for further explanation on using +the fir::reg class. diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/fir/check.C b/src/import/chips/p9/procedures/hwp/memory/lib/fir/check.C new file mode 100644 index 000000000..91416c5ea --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/fir/check.C @@ -0,0 +1,185 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/fir/check.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] 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 check.C +/// @brief Subroutines for checking MSS FIR +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> +#include <p9_mc_scom_addresses.H> +#include <p9_mc_scom_addresses_fld.H> + +#include <lib/utils/scom.H> +#include <lib/fir/fir.H> +#include <lib/fir/check.H> +#include <lib/utils/assert_noexit.H> +#include <lib/utils/find.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_MCA; + +namespace mss +{ + +namespace check +{ + +/// +/// @brief A small, local, class to hold some of the FFDC information we need from the ports +/// +struct fir_ffdc +{ + /// + /// @brief fir_ffdc ctor + /// @param[in] the MCA target the FFDC was collected from + /// @param[in] the cal FIR information + /// @param[in] the phy FIR information + /// + fir_ffdc( const fapi2::Target<TARGET_TYPE_MCA>& i_target, const uint64_t i_calfir, const uint64_t i_phyfir ): + iv_target(i_target), + iv_calfir(i_calfir), + iv_phyfir(i_phyfir) + {} + + ~fir_ffdc() = default; + fir_ffdc() = delete; + + fapi2::Target<TARGET_TYPE_MCA> iv_target; + uint64_t iv_calfir; + uint64_t iv_phyfir; +}; + +/// +/// @brief Check FIR bits during PHY reset +/// @note For DDRPHYFIR and some MBACALFIR errors, up to and including phy reset, need to +/// handle within the phy reset procedure, since we may get errors from a 'non-functional' +/// magic port, which PRD can't analyze. +/// @param[in] i_target the fapi2::Target MCBIST +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode during_phy_reset( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target ) +{ + // Save off the current current_err + fapi2::ReturnCode l_current_err(fapi2::current_err); + + // Error path: if we hit error before FIR check (we can see that in current_err), and FIR check also + // finds something, commit first error and exit phy reset with new error from FIR check + // If bit on, call out MCA with deconfig and gard, including DDRPHYFIR and MBACALFIR in FFDC + // Do FIR check on all ports, so we can log errors from multiple ports that happen to have FIR bits on + + // Create a mask from the bits Marc wants us to check + fapi2::buffer<uint64_t> l_calfir_mask; + l_calfir_mask.setBit<MCA_MBACALFIRQ_MBA_RECOVERABLE_ERROR>() + .setBit<MCA_MBACALFIRQ_MBA_NONRECOVERABLE_ERROR>() + .setBit<MCA_MBACALFIRQ_SM_1HOT_ERR>(); + + fapi2::buffer<uint64_t> l_phyfir_mask; + l_phyfir_mask.setBit<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_0>() + .setBit<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_1>() + .setBit<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_3>() + .setBit<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_4>() + .setBit<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_5>() + .setBit<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_6>() + .setBit<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_7>(); + + + // Go grab the MCA_MBACALFIRQ for each port. We only save off some of the FFDC information for the ports which + // have FIR set. This allows us to 1) see if we have any thing to do (empty vector means we don't) and 2) gives us + // all the information we need to log all the proper errors. + std::vector< fir_ffdc> l_fir_ffdc; + + for (const auto& p : mss::find_targets_with_magic<TARGET_TYPE_MCA>(i_target)) + { + fapi2::buffer<uint64_t> l_calfir_data; + fapi2::buffer<uint64_t> l_phyfir_data; + fapi2::buffer<uint64_t> l_calfir_masked; + fapi2::buffer<uint64_t> l_phyfir_masked; + + FAPI_TRY( mss::getScom(p, MCA_MBACALFIRQ, l_calfir_data) ); + FAPI_TRY( mss::getScom(p, MCA_IOM_PHY0_DDRPHY_FIR_REG, l_phyfir_data) ); + + l_calfir_masked = l_calfir_data & l_calfir_mask; + l_phyfir_masked = l_phyfir_data & l_phyfir_mask; + + // If either has set bits we make a little record in the vector + if ((l_calfir_masked != 0) || (l_phyfir_masked != 0)) + { + l_fir_ffdc.push_back( fir_ffdc(p, l_calfir_data, l_phyfir_data) ); + } + + // Clear the FIR + FAPI_TRY( mss::putScom(p, MCA_MBACALFIRQ_AND, l_calfir_masked.invert()) ); + FAPI_TRY( mss::putScom(p, MCA_IOM_PHY0_DDRPHY_FIR_REG_AND, l_phyfir_masked.invert()) ); + } + + FAPI_INF("seeing FIRs set on %d ports", l_fir_ffdc.size()); + + // Ok, we know if l_fir_ffdc is empty that we had no FIR bits set. In this case we just return fapi2::current_err + // as it represents the error state of our caller. If there were no errors seen by the caller, this will be + // SUCCESS, and our caller will return SUCCESS. If there was an error, we don't disturb it, we just return + // is so the caller can pass it back to it's caller (if there are FIR we'll disrupt current_err ...) + if (l_fir_ffdc.size() == 0) + { + return l_current_err; + } + + // Ok so if we're here we have FIR bits set. Not sure it matters what they are, we're returning them in the FFDC + // and calling out/deconfig the port. First thing we do is commit whatever was in fapi2::current_err, if it's not + // success. + if (l_current_err != fapi2::FAPI2_RC_SUCCESS) + { + fapi2::logError(l_current_err); + } + + // Now log all the errors which represent all the errors found from the ports. + for (const fir_ffdc& f : l_fir_ffdc) + { + MSS_ASSERT_NOEXIT(false, + fapi2::MSS_DDR_PHY_RESET_PORT_FIR() + .set_CAL_FIR(f.iv_calfir) + .set_PHY_FIR(f.iv_phyfir) + .set_MCA_TARGET(f.iv_target), + "Reporting FIR bits set for %s (cal: 0x%016lx phy: 0x%016lx", + mss::c_str(f.iv_target), f.iv_calfir, f.iv_phyfir); + } + + // The last thing we want to do is to create a new error code noting there were FIR set for any of the ports + // during PHY reset and pass that back so it goes upstream. This will jump right to the label ... + FAPI_ASSERT(false, fapi2::MSS_DDR_PHY_RESET_PORT_FIRS_REPORTED().set_MCBIST_TARGET(i_target)); + +fapi_try_exit: + return fapi2::current_err; +} + + +} +} diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/fir/training_fir.H b/src/import/chips/p9/procedures/hwp/memory/lib/fir/check.H index 086eb24e2..27f884940 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/fir/training_fir.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/fir/check.H @@ -1,7 +1,7 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/fir/training_fir.H $ */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/fir/check.H $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ @@ -24,8 +24,8 @@ /* IBM_PROLOG_END_TAG */ /// -/// @file training_fir.H -/// @brief Subroutines for training FIR +/// @file check.H +/// @brief Subroutines for checking MSS FIR /// // *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> // *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com> @@ -33,22 +33,29 @@ // *HWP Level: 2 // *HWP Consumed by: FSP:HB -#ifndef _MSS_TRAINING_FIR_H_ -#define _MSS_TRAINING_FIR_H_ +#ifndef _MSS_CHECK_FIR_H_ +#define _MSS_CHECK_FIR_H_ #include <fapi2.H> namespace mss { +namespace check +{ + /// -/// @brief Unmask and setup actions for training related FIR +/// @brief Check FIR bits during PHY reset +/// @note For DDRPHYFIR and some MBACALFIR errors, up to and including phy reset, need to +/// handle within the phy reset procedure, since we may get errors from a 'non-functional' +/// magic port, which PRD can't analyze. /// @tparam T the fapi2::TargetType which hold the FIR bits /// @param[in] i_target the fapi2::Target /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// template< fapi2::TargetType T > -fapi2::ReturnCode unmask_training_errors( const fapi2::Target<T>& i_target ); +fapi2::ReturnCode during_phy_reset( const fapi2::Target<T>& i_target ); } +} #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/fir/fir.H b/src/import/chips/p9/procedures/hwp/memory/lib/fir/fir.H new file mode 100644 index 000000000..b25ab105f --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/fir/fir.H @@ -0,0 +1,314 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/fir/fir.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] 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 fir.H +/// @brief Memory subsystem FIR support +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#ifndef _MSS_FIR_H_ +#define _MSS_FIR_H_ + +#include <fapi2.H> +#include <p9_mc_scom_addresses.H> +#include <p9_mc_scom_addresses_fld.H> +#include <lib/utils/scom.H> + +namespace mss +{ + +// +// Each FIR bit is contained in a register (set or unset) and is mapped to action and mask registers (defines +// their behavior). Likewise, each unit (MCBIST, MCS, MCA) has control bits defining whether the attentions +// from this unit represent special or host attentions. + +/// +/// @brief FIR Register Traits +/// @tparam R the FIR register +/// +template <uint64_t R > +struct firTraits; + +/// +/// @brief FIR Register Traits for MCBISTFIR +/// +template <> +struct firTraits<MCBIST_MCBISTFIRQ> +{ + static constexpr uint64_t REG = MCBIST_MCBISTFIRQ; + static constexpr uint64_t ACT0 = MCBIST_MCBISTFIRACT0; + static constexpr uint64_t ACT1 = MCBIST_MCBISTFIRACT1; + static constexpr uint64_t MASK = MCBIST_MCBISTFIRMASK; + static constexpr uint64_t MASK_AND = MCBIST_MCBISTFIRMASK_AND; + static constexpr uint64_t MASK_OR = MCBIST_MCBISTFIRMASK_OR; + + // Target type of this register + static constexpr fapi2::TargetType T = fapi2::TARGET_TYPE_MCBIST; +}; + +/// +/// @brief FIR Register Traits for PHYFIR +/// +template <> +struct firTraits<MCA_IOM_PHY0_DDRPHY_FIR_REG> +{ + static constexpr uint64_t REG = MCA_IOM_PHY0_DDRPHY_FIR_REG; + static constexpr uint64_t ACT0 = MCA_IOM_PHY0_DDRPHY_FIR_ACTION0_REG; + static constexpr uint64_t ACT1 = MCA_IOM_PHY0_DDRPHY_FIR_ACTION1_REG; + static constexpr uint64_t MASK = MCA_IOM_PHY0_DDRPHY_FIR_MASK_REG; + static constexpr uint64_t MASK_AND = MCA_IOM_PHY0_DDRPHY_FIR_MASK_REG_AND; + static constexpr uint64_t MASK_OR = MCA_IOM_PHY0_DDRPHY_FIR_MASK_REG_OR; + + // Target type of this register + static constexpr fapi2::TargetType T = fapi2::TARGET_TYPE_MCA; +}; + +/// +/// @brief FIR Register Traits for MCFIR +/// +template <> +struct firTraits<MCS_MCFIR> +{ + static constexpr uint64_t REG = MCS_MCFIR; + static constexpr uint64_t ACT0 = MCS_MCFIRACT0; + static constexpr uint64_t ACT1 = MCS_MCFIRACT1; + static constexpr uint64_t MASK = MCS_MCFIRMASK; + static constexpr uint64_t MASK_AND = MCS_MCFIRMASK_AND; + static constexpr uint64_t MASK_OR = MCS_MCFIRMASK_OR; + + // Target type of this register + static constexpr fapi2::TargetType T = fapi2::TARGET_TYPE_MCS; +}; + +/// +/// @brief FIR Register Traits for MCA_FIR (ECC64.SCOM.FIR) +/// +template <> +struct firTraits<MCA_FIR> +{ + static constexpr uint64_t REG = MCA_FIR; + static constexpr uint64_t ACT0 = MCA_ACTION0; + static constexpr uint64_t ACT1 = MCA_ACTION1; + static constexpr uint64_t MASK = MCA_MASK; + static constexpr uint64_t MASK_AND = MCA_MASK_AND; + static constexpr uint64_t MASK_OR = MCA_MASK_OR; + + // Target type of this register + static constexpr fapi2::TargetType T = fapi2::TARGET_TYPE_MCA; +}; + +/// +/// @brief FIR Register Traits for MBACALFIR +/// +template <> +struct firTraits<MCA_MBACALFIRQ> +{ + static constexpr uint64_t REG = MCA_MBACALFIRQ; + static constexpr uint64_t ACT0 = MCA_MBACALFIR_ACTION0; + static constexpr uint64_t ACT1 = MCA_MBACALFIR_ACTION1; + static constexpr uint64_t MASK = MCA_MBACALFIR_MASK; + static constexpr uint64_t MASK_AND = MCA_MBACALFIR_MASK_AND; + static constexpr uint64_t MASK_OR = MCA_MBACALFIR_MASK_OR; + + // Target type of this register + static constexpr fapi2::TargetType T = fapi2::TARGET_TYPE_MCA; +}; + +namespace fir +{ + + +/// +/// @brief Small class to hold a FIR register +/// @tparam R the FIR register +/// @tparam RT the type traits for this register (derived) +/// +template< uint64_t R, typename RT = firTraits<R> > +class reg +{ + + private: + fapi2::Target<RT::T> iv_target; + + public: + + /// + /// @brief fir::reg constructor + /// @param[in] i_target representing the fapi2::Target used to scom register R + /// @param[out] a fapi2::ReturnCode indicating if the internal constructor opererations were a success + /// + reg( const fapi2::Target<RT::T>& i_target, fapi2::ReturnCode& o_rc ): + iv_target(i_target), + + // Fill our buffer with F's as we're going to clear the bits we want to + // unmask and then drop the result in to the _AND register. + iv_mask(~0) + { + // Priming Read + FAPI_TRY( mss::getScom(iv_target, RT::ACT0, iv_action0) ); + FAPI_TRY( mss::getScom(iv_target, RT::ACT1, iv_action1) ); + + fapi_try_exit: + o_rc = fapi2::current_err; + } + + /// + /// @brief Clear FIR bits + /// @tparam B the ordinial number of the bit in question + /// @return FAPI2_RC_SUCCESS iff ok + /// + template< uint64_t B > + inline fapi2::ReturnCode clear() const + { + fapi2::buffer<uint64_t> l_read; + FAPI_TRY( mss::getScom(iv_target, RT::REG, l_read) ); + l_read.clearBit<B>(); + FAPI_TRY( mss::putScom(iv_target, RT::REG, l_read) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Clear the entire register of FIR bits + /// @return FAPI2_RC_SUCCESS iff ok + /// + inline fapi2::ReturnCode clear() const + { + return mss::putScom(iv_target, RT::REG, 0); + } + + // Magic patterns in these functions are (Action0, Action1, Mask) + + /// + /// @brief Setup Checkstop (0,0,0) + /// @tparam B the ordinial number of the bit in question + /// @tparam C the bit count, defaults to 1 + /// @return fir::reg reference suitable for chaining + /// + template< uint64_t B, uint64_t C = 1 > + inline fir::reg<R>& checkstop() + { + return action_helper<B, C>(0, 0, 0); + } + + /// + /// @brief Setup Recoverable Error (0,1,0) + /// @tparam B the ordinial number of the bit in question + /// @tparam C the bit count, defaults to 1 + /// @return fir::reg reference sutable for chaining + /// + template< uint64_t B, uint64_t C = 1 > + inline fir::reg<R>& recoverable_error() + { + return action_helper<B, C>(0, 1, 0); + } + + /// + /// @brief Setup Attention (1,0,0) + /// @tparam B the ordinial number of the bit in question + /// @tparam C the bit count, defaults to 1 + /// @return fir::reg reference sutable for chaining + /// + template< uint64_t B, uint64_t C = 1 > + inline fir::reg<R>& attention() + { + return action_helper<B, C>(1, 0, 0); + // TK do we need to setup special attention or host attention here? + } + + /// + /// @brief Setup Local checkstop (1,1,0) + /// @tparam B the ordinial number of the bit in question + /// @tparam C the bit count, defaults to 1 + /// @return fir::reg reference sutable for chaining + /// + template< uint64_t B, uint64_t C = 1 > + inline fir::reg<R>& local_checkstop() + { + return action_helper<B, C>(1, 1, 0); + } + + /// + /// @brief Setup Masked (x,x,1) + /// @tparam B the ordinial number of the bit in question + /// @tparam C the bit count, defaults to 1 + /// @return fir::reg reference sutable for chaining + /// + template< uint64_t B, uint64_t C = 1 > + inline fir::reg<R>& masked() + { + return action_helper<B, C>(1, 1, 1); + } + + /// + /// @brief Write action0, action1 and mask for this register + /// @return fapi2::FAPI2_RC_SUCCESS iff ok + /// + inline fapi2::ReturnCode write() const + { + // Set action registers before unmasking to prevent unintended actions when you unmask. + FAPI_TRY( mss::putScom(iv_target, RT::ACT0, iv_action0) ); + FAPI_TRY( mss::putScom(iv_target, RT::ACT1, iv_action1) ); + FAPI_TRY( mss::putScom(iv_target, RT::MASK_AND, iv_mask) ); + + fapi_try_exit: + return fapi2::current_err; + } + + private: + + fapi2::buffer<uint64_t> iv_mask; + fapi2::buffer<uint64_t> iv_action0; + fapi2::buffer<uint64_t> iv_action1; + + /// + /// @brief Register helper takes a setting of bits for action0, action1 and mask and sets our internal state + /// @tparam B the fir bit ordinal number + /// @tparam C the bit count, defaults to 1 + /// @param[in] i_act0 the setting for action0 + /// @param[in] i_act1 the setting for action1 + /// @param[in] i_mask the setting for mask + /// @return reference to fir::reg, to be used for chaining + /// + template< uint64_t B, uint64_t C = 1 > + inline fir::reg<R>& action_helper(const uint64_t i_act0, const uint64_t i_act1, const uint64_t i_mask) + { + iv_mask.writeBit<B, C>(i_mask); + iv_action0.writeBit<B, C>(i_act0); + iv_action1.writeBit<B, C>(i_act1); + + return *this; + } +}; + +} +} +#endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.C b/src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.C index 9cba6d76b..1c970538e 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.C @@ -38,51 +38,92 @@ #include <p9_mc_scom_addresses_fld.H> #include <lib/utils/scom.H> +#include <lib/utils/find.H> +#include <lib/fir/fir.H> #include <lib/fir/memdiags_fir.H> +#include <lib/mc/port.H> using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_MCA; namespace mss { +namespace unmask +{ + /// /// @brief Unmask and setup actions for memdiags related FIR -/// @param[in] i_target the fapi2::Target +/// @param[in] i_target the fapi2::Target MCBIST /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// template<> -fapi2::ReturnCode unmask_memdiags_errors( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target ) +fapi2::ReturnCode after_memdiags( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target ) { - FAPI_INF("unmask_memdiags_errors"); + fapi2::ReturnCode l_rc; + + for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target)) + { + fir::reg<MCA_FIR> l_ecc64_fir_reg(p, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_FIR); + + fir::reg<MCA_MBACALFIRQ> l_cal_fir_reg(p, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_MBACALFIRQ); + + l_ecc64_fir_reg.checkstop<MCA_FIR_MAINLINE_AUE>() + .recoverable_error<MCA_FIR_MAINLINE_UE>() + .checkstop<MCA_FIR_MAINLINE_IAUE>() + .recoverable_error<MCA_FIR_MAINLINE_IUE>(); + + // TODO RTC:165157 check for manufacturing flags and don't unmask this if + // thresholds policy is enabled. + l_ecc64_fir_reg.recoverable_error<MCA_FIR_MAINTENANCE_IUE>(); + + l_cal_fir_reg.recoverable_error<MCA_MBACALFIRQ_PORT_FAIL>(); + + FAPI_TRY(l_ecc64_fir_reg.write(), "unable to write fir::reg %d", MCA_FIR); + FAPI_TRY(l_cal_fir_reg.write(), "unable to write fir::reg %d", MCA_MBACALFIRQ); + + // Note: We also want to include the following setup RCD recovery and port fail + FAPI_TRY( mss::change_port_fail_disable(p, mss::LOW) ); + FAPI_TRY( mss::change_rcd_recovery_disable(p, mss::LOW) ); + } - // Fill our buffer with F's as we're going to clear the bits we want to - // unmask and then drop the result in to the _AND register. - fapi2::buffer<uint64_t> l_mcbistfir_mask(~0); - fapi2::buffer<uint64_t> l_mcbistfir_action0; - fapi2::buffer<uint64_t> l_mcbistfir_action1; + return fapi2::FAPI2_RC_SUCCESS; - FAPI_TRY( mss::getScom(i_target, MCBIST_MCBISTFIRACT0, l_mcbistfir_action0) ); - FAPI_TRY( mss::getScom(i_target, MCBIST_MCBISTFIRACT1, l_mcbistfir_action1) ); +fapi_try_exit: + return fapi2::current_err; +} - // There's not much to do here right now as Marc needs to work out the new FIR - // and whatnot for Nimbus. Lets make sure we setup everything as PRD needs it - // for sim, and we'll circle back to add the other FIR as the design completes. +/// +/// @brief Unmask and setup actions for scrub related FIR +/// @param[in] i_target the fapi2::Target MCBIST +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode after_background_scrub( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target ) +{ + for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target)) + { + fapi2::ReturnCode l_rc; + fir::reg<MCA_FIR> l_ecc64_fir_reg(p, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_FIR); - // Don't unmask the main address skipped FIR. First, we rely on the skipping so - // we probably don't want any one to see it and second it's broken per Shelton 5/16. + l_ecc64_fir_reg.recoverable_error<MCA_FIR_MAINLINE_MPE_RANK_0_TO_7, + MCA_FIR_MAINLINE_MPE_RANK_0_TO_7_LEN>() + .recoverable_error<MCA_FIR_MAINLINE_NCE>() + .recoverable_error<MCA_FIR_MAINLINE_TCE>() + .recoverable_error<MCA_FIR_MAINLINE_IMPE>() + .recoverable_error<MCA_FIR_MAINTENANCE_IMPE>(); - // Unmask the program complete bit and setup the actions for an attention - l_mcbistfir_action0.setBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>(); - l_mcbistfir_action1.clearBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>(); - l_mcbistfir_mask.clearBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>(); + FAPI_TRY(l_ecc64_fir_reg.write(), "unable to write fir::reg %d", MCA_FIR); + } - // Hit the and register of the fir mask - FAPI_TRY( mss::putScom(i_target, MCBIST_MCBISTFIRACT0, l_mcbistfir_action0) ); - FAPI_TRY( mss::putScom(i_target, MCBIST_MCBISTFIRACT1, l_mcbistfir_action1) ); - FAPI_TRY( mss::putScom(i_target, MCBIST_MCBISTFIRMASK_AND, l_mcbistfir_mask) ); + return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: return fapi2::current_err; } } +} diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.H b/src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.H index 2c6cdc49d..552b5bdcd 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.H @@ -37,10 +37,14 @@ #define _MSS_MEMDIAGS_FIR_H_ #include <fapi2.H> +#include <lib/fir/fir.H> namespace mss { +namespace unmask +{ + /// /// @brief Unmask and setup actions for memdiags related FIR /// @tparam T the fapi2::TargetType which hold the FIR bits @@ -48,7 +52,17 @@ namespace mss /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// template< fapi2::TargetType T > -fapi2::ReturnCode unmask_memdiags_errors( const fapi2::Target<T>& i_target ); +fapi2::ReturnCode after_memdiags( const fapi2::Target<T>& i_target ); + +/// +/// @brief Unmask and setup actions for scrub related FIR +/// @tparam T the fapi2::TargetType which hold the FIR bits +/// @param[in] i_target the fapi2::Target +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template< fapi2::TargetType T > +fapi2::ReturnCode after_background_scrub( const fapi2::Target<T>& i_target ); } +} #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/fir/unmask.C b/src/import/chips/p9/procedures/hwp/memory/lib/fir/unmask.C new file mode 100644 index 000000000..f03e65e37 --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/fir/unmask.C @@ -0,0 +1,252 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/fir/unmask.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] 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 unmask.C +/// @brief Subroutines for unmasking and setting up MSS FIR +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> +#include <p9_mc_scom_addresses.H> +#include <p9_mc_scom_addresses_fld.H> + +#include <lib/utils/scom.H> +#include <lib/fir/fir.H> +#include <lib/fir/unmask.H> +#include <lib/workarounds/mcbist_workarounds.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_MCA; + +namespace mss +{ + +namespace unmask +{ + +/// +/// @brief Unmask and setup actions performed after draminit_mc +/// @param[in] i_target the fapi2::Target of the MCBIST +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode after_draminit_mc( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target ) +{ + FAPI_INF("unmask mss fir after draminit_mc"); + + fapi2::ReturnCode l_rc; + + // TK - unclear right now if these can become generic per MCBIST or whether these are specific + // to Nimbus. If they can be generic,this whole thing can go back in the H file and the specifics + // of the registers and bits can be handled generically. + + fir::reg<MCBIST_MCBISTFIRQ> l_mcbist_fir_reg(i_target, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCBIST_MCBISTFIRQ); + + // Setup mcbist fir. All mcbist attentions are already special attentions + // Write this out before the work-around as it will read and write. + l_mcbist_fir_reg.attention<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>() + .checkstop<MCBIST_MCBISTFIRQ_MCBIST_BRODCAST_OUT_OF_SYNC>(); + + FAPI_TRY(l_mcbist_fir_reg.write(), "unable to write fir::reg %d", MCBIST_MCBISTFIRQ); + + FAPI_TRY(mss::workarounds::mcbist::wat_debug_attention(i_target)); + + for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target)) + { + fir::reg<MCA_FIR> l_mca_fir_reg(p, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_FIR); + + l_mca_fir_reg.checkstop<MCA_FIR_MAINTENANCE_AUE>() + .checkstop<MCA_FIR_MAINTENANCE_IAUE>() + .recoverable_error<MCA_FIR_SCOM_PARITY_CLASS_STATUS>() + .recoverable_error<MCA_FIR_SCOM_PARITY_CLASS_RECOVERABLE>() + .checkstop<MCA_FIR_SCOM_PARITY_CLASS_UNRECOVERABLE>() + .checkstop<MCA_FIR_ECC_CORRECTOR_INTERNAL_PARITY_ERROR>() + .recoverable_error<MCA_FIR_WRITE_RMW_CE>() + .checkstop<MCA_FIR_WRITE_RMW_UE>() + .checkstop<MCA_FIR_WDF_OVERRUN_ERROR_0>() + .checkstop<MCA_FIR_WDF_OVERRUN_ERROR_1>() + .checkstop<MCA_FIR_WDF_SCOM_SEQUENCE_ERROR>() + .checkstop<MCA_FIR_WDF_STATE_MACHINE_ERROR>() + .checkstop<MCA_FIR_WRT_MISC_REGISTER_PARITY_ERROR>() + .checkstop<MCA_FIR_WRT_SCOM_SEQUENCE_ERROR>() + .checkstop<MCA_FIR_WRT_MISC_REGISTER_PARITY_ERROR>() + .checkstop<MCA_FIR_ECC_CORRECTOR_INTERNAL_PARITY_ERROR>() + .checkstop<MCA_FIR_READ_BUFFER_OVERFLOW_ERROR>() + .checkstop<MCA_FIR_WDF_ASYNC_INTERFACE_ERROR>() + .checkstop<MCA_FIR_READ_ASYNC_INTERFACE_PARITY_ERROR>() + .checkstop<MCA_FIR_READ_ASYNC_INTERFACE_SEQUENCE_ERROR>(); + + FAPI_TRY(l_mca_fir_reg.write(), "unable to write fir::reg %d", MCA_FIR); + + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Unmask and setup actions performed after draminit_training +/// @param[in] i_target the fapi2::Target of the MCBIST +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode after_draminit_training( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target ) +{ + FAPI_INF("unmask mss fir after draminit_training"); + + fapi2::ReturnCode l_rc; + + // TK - unclear right now if these can become generic per MCBIST or whether these are specific + // to Nimbus. If they can be generic,this whole thing can go back in the H file and the specifics + // of the registers and bits can be handled generically. + + fir::reg<MCBIST_MCBISTFIRQ> l_mcbist_fir_reg(i_target, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCBIST_MCBISTFIRQ); + + // Setup mcbist fir. All mcbist attentions are already special attentions + FAPI_TRY(l_mcbist_fir_reg.recoverable_error<MCBIST_MCBISTFIRQ_COMMAND_ADDRESS_TIMEOUT>().write(), + "unable to write fir::reg %d", MCBIST_MCBISTFIRQ); + + for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target)) + { + fir::reg<MCA_MBACALFIRQ> l_mca_fir_reg(p, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_MBACALFIRQ); + + l_mca_fir_reg.recoverable_error<MCA_MBACALFIRQ_REFRESH_OVERRUN>() + .recoverable_error<MCA_MBACALFIRQ_DDR_CAL_TIMEOUT_ERR>() + .recoverable_error<MCA_MBACALFIRQ_DDR_CAL_RESET_TIMEOUT>() + .recoverable_error<MCA_MBACALFIRQ_WRQ_RRQ_HANG_ERR>() + .checkstop<MCA_MBACALFIRQ_ASYNC_IF_ERROR>() + .checkstop<MCA_MBACALFIRQ_CMD_PARITY_ERROR>() + .recoverable_error<MCA_MBACALFIRQ_RCD_CAL_PARITY_ERROR>(); + + FAPI_TRY(l_mca_fir_reg.write(), "unable to write fir::reg %d", MCA_MBACALFIRQ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Unmask and setup actions performed after mss_scominit +/// (yeah, it's clearing bits - it's ok) +/// @param[in] i_target the fapi2::Target of the MCBIST +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode after_scominit( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target ) +{ + FAPI_INF("unmask (and clear) mss fir after scominit"); + + fapi2::ReturnCode l_rc; + + // TK - unclear right now if these can become generic per MCBIST or whether these are specific + // to Nimbus. If they can be generic,this whole thing can go back in the H file and the specifics + // of the registers and bits can be handled generically. + + for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target)) + { + fir::reg<MCA_IOM_PHY0_DDRPHY_FIR_REG> l_mca_fir_reg(p, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_IOM_PHY0_DDRPHY_FIR_REG); + + fir::reg<MCA_MBACALFIRQ> l_cal_fir_reg(p, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_MBACALFIRQ); + + FAPI_TRY(l_mca_fir_reg.clear<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_2>()); + FAPI_TRY(l_mca_fir_reg.clear<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_4>()); + + FAPI_TRY(l_cal_fir_reg.clear<MCA_MBACALFIRQ_RCD_PARITY_ERROR>()); + + // No need to write after clearing - the clear does the read/modify/write. + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Unmask and setup actions performed after mss_ddr_phy_reset +/// @param[in] i_target the fapi2::Target of the MCBIST +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode after_phy_reset( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target ) +{ + FAPI_INF("unmask mss fir after phy reset"); + + fapi2::ReturnCode l_rc; + + // TK - unclear right now if these can become generic per MCBIST or whether these are specific + // to Nimbus. If they can be generic,this whole thing can go back in the H file and the specifics + // of the registers and bits can be handled generically. + + fir::reg<MCBIST_MCBISTFIRQ> l_mcbist_fir_reg(i_target, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCBIST_MCBISTFIRQ); + + l_mcbist_fir_reg.checkstop<MCBIST_MCBISTFIRQ_INTERNAL_FSM_ERROR>() + .recoverable_error<MCBIST_MCBISTFIRQ_SCOM_RECOVERABLE_REG_PE>() + .checkstop<MCBIST_MCBISTFIRQ_SCOM_FATAL_REG_PE>(); + + FAPI_TRY(l_mcbist_fir_reg.write(), "unable to write fir::reg %d", MCBIST_MCBISTFIRQ); + + for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target)) + { + fir::reg<MCA_IOM_PHY0_DDRPHY_FIR_REG> l_mca_fir_reg(p, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_IOM_PHY0_DDRPHY_FIR_REG); + + fir::reg<MCA_MBACALFIRQ> l_cal_fir_reg(p, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_MBACALFIRQ); + + l_cal_fir_reg.recoverable_error<MCA_MBACALFIRQ_MBA_RECOVERABLE_ERROR>() + .checkstop<MCA_MBACALFIRQ_MBA_NONRECOVERABLE_ERROR>() + .recoverable_error<MCA_MBACALFIRQ_RCD_PARITY_ERROR>() + .checkstop<MCA_MBACALFIRQ_SM_1HOT_ERR>(); + + l_mca_fir_reg.recoverable_error<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_0>() + .recoverable_error<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_1>() + .recoverable_error<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_3>() + .recoverable_error<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_4>() + .recoverable_error<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_5>() + .recoverable_error<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_6>() + .recoverable_error<MCA_IOM_PHY0_DDRPHY_FIR_REG_ERROR_7>(); + + FAPI_TRY(l_mca_fir_reg.write(), "unable to write fir::reg %d", MCA_IOM_PHY0_DDRPHY_FIR_REG); + FAPI_TRY(l_cal_fir_reg.write(), "unable to write fir::reg %d", MCA_MBACALFIRQ); + } + +fapi_try_exit: + return fapi2::current_err; + +} + +} +} diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/fir/training_fir.C b/src/import/chips/p9/procedures/hwp/memory/lib/fir/unmask.H index a94aa7454..fceb24ab8 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/fir/training_fir.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/fir/unmask.H @@ -1,7 +1,7 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/fir/training_fir.C $ */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/fir/unmask.H $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ @@ -24,8 +24,8 @@ /* IBM_PROLOG_END_TAG */ /// -/// @file training_fir.C -/// @brief Subroutines for training FIR +/// @file unmask.H +/// @brief Subroutines for unmasking and setting up MSS FIR /// // *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> // *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com> @@ -33,47 +33,54 @@ // *HWP Level: 2 // *HWP Consumed by: FSP:HB -#include <fapi2.H> -#include <p9_mc_scom_addresses.H> -#include <p9_mc_scom_addresses_fld.H> - -#include <lib/utils/scom.H> -#include <lib/utils/find.H> -#include <lib/fir/training_fir.H> +#ifndef _MSS_UNMASK_FIR_H_ +#define _MSS_UNMASK_FIR_H_ -using fapi2::TARGET_TYPE_MCBIST; -using fapi2::TARGET_TYPE_MCA; +#include <fapi2.H> namespace mss { +namespace unmask +{ + /// -/// @brief Unmask and setup actions for training related FIR +/// @brief Unmask and setup actions performed after draminit_mc +/// @tparam T the fapi2::TargetType which hold the FIR bits /// @param[in] i_target the fapi2::Target /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// -template<> -fapi2::ReturnCode unmask_training_errors( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target ) -{ - // TK complete with all the actions and other FIR when we get there. - FAPI_INF("unmask_training_errors"); +template< fapi2::TargetType T > +fapi2::ReturnCode after_draminit_mc( const fapi2::Target<T>& i_target ); - // All we presently do here is clear the ALERT_N FIR as it's not - // reliable until after the RCD has been configured (so before training) +/// +/// @brief Unmask and setup actions performed after draminit_training +/// @tparam T the fapi2::TargetType which hold the FIR bits +/// @param[in] i_target the fapi2::Target +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template< fapi2::TargetType T > +fapi2::ReturnCode after_draminit_training( const fapi2::Target<T>& i_target ); - // Fill our buffer with F's as we're going to clear the bits we want to - // unmask and then drop the result in to the _AND register. - fapi2::buffer<uint64_t> l_trainingfir_mask(~0); +/// +/// @brief Unmask and setup actions performed after mss_scominit +/// @tparam T the fapi2::TargetType which hold the FIR bits +/// @param[in] i_target the fapi2::Target of the MCBIST +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template< fapi2::TargetType T > +fapi2::ReturnCode after_scominit( const fapi2::Target<T>& i_target ); - l_trainingfir_mask.clearBit<MCA_MBACALFIRQ_RCD_PARITY_ERROR>(); +/// +/// @brief Unmask and setup actions performed after mss_ddr_phy_reset +/// @tparam T the fapi2::TargetType which hold the FIR bits +/// @param[in] i_target the fapi2::Target of the MCBIST +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +template< fapi2::TargetType T > +fapi2::ReturnCode after_phy_reset( const fapi2::Target<T>& i_target ); - for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target)) - { - FAPI_TRY( mss::putScom(p, MCA_MBACALFIRQ_AND, l_trainingfir_mask) ); - } -fapi_try_exit: - return fapi2::current_err; } - } +#endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H b/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H index bfc6e503c..c5edddf9f 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H @@ -109,6 +109,7 @@ class portTraits<fapi2::TARGET_TYPE_MCA> PORT_FAIL_DISABLE = MCA_MBA_FARB0Q_CFG_PORT_FAIL_DISABLE, OE_ALWAYS_ON = MCA_MBA_FARB0Q_CFG_OE_ALWAYS_ON, + RCD_RECOVERY_DISABLE = MCA_MBA_FARB0Q_CFG_DISABLE_RCD_RECOVERY, CAL0Q_CAL_INTERVAL_TMR0_ENABLE = MCA_MBA_CAL0Q_CFG_CAL_INTERVAL_TMR0_ENABLE, CAL0Q_TIME_BASE_TMR0 = MCA_MBA_CAL0Q_CFG_TIME_BASE_TMR0, @@ -270,6 +271,28 @@ fapi_try_exit: } /// +/// @brief Change the state of the RCD recovery bit +/// @tparam T, the fapi2 target type of the target +/// @tparam TT, the class traits for the port +/// @param[in] i_target the target +/// @param[in] i_state the state +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType T, typename TT = portTraits<T> > +fapi2::ReturnCode change_rcd_recovery_disable( const fapi2::Target<T>& i_target, states i_state ) +{ + fapi2::buffer<uint64_t> l_data; + + FAPI_DBG("Change rcd recovery disable to %s %s", (i_state == HIGH ? "high" : "low"), mss::c_str(i_target)); + FAPI_TRY( mss::getScom(i_target, TT::FARB0Q_REG, l_data) ); + l_data.writeBit<TT::RCD_RECOVERY_DISABLE>(i_state); + FAPI_TRY( mss::putScom(i_target, TT::FARB0Q_REG, l_data) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// /// @brief Change the state of the output enable always-on bit /// @tparam T, the fapi2 target type of the target /// @tparam TT, the class traits for the port diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H index 9ce68f581..8c840d4d7 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H @@ -214,6 +214,30 @@ fapi_try_exit: } /// +/// @brief ATTR_CHIP_EC_FEATURE_MSS_WAT_DEBUG_ATTN getter +/// @tparam T the fapi2 target type of the target +/// @param[in] const ref to the target +/// @param[out] uint8_t& reference to store the value +/// @return bool true iff feature is enabled +/// +template< fapi2::TargetType T > +inline bool chip_ec_feature_mss_wat_debug_attn(const fapi2::Target<T>& i_target) +{ + const auto l_chip = mss::find_target<fapi2::TARGET_TYPE_PROC_CHIP>(i_target); + uint8_t l_value = 0; + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_MSS_WAT_DEBUG_ATTN, l_chip, l_value) ); + + return l_value != 0; + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_CHIP_EC_FEATURE_MSS_WAT_DEBUG_ATTN: 0x%lx (target: %s)", + uint64_t(fapi2::current_err), mss::c_str(i_target)); + fapi2::Assert(false); + return false; +} + +/// /// @brief ATTR_CHIP_EC_FEATURE_MSS_TRAINING_BAD_BITS getter /// @tparam T the fapi2 target type of the target /// @param[in] const ref to the target @@ -238,7 +262,6 @@ fapi_try_exit: return false; } - } // close mss namespace #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H index 366bdded7..cb3be6cfa 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H @@ -91,6 +91,10 @@ fapi2::ReturnCode dqsclk_offset( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_ inline uint64_t vreg_control0( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, const uint64_t i_original_value ) { + +// Anuwat has asked that we don't enforce this right now. +#ifdef ANUWAT_SAYS_DONT_DO_THIS_NOW + fapi2::buffer<uint64_t> l_value(i_original_value); uint8_t l_vccd_override = 0; @@ -120,6 +124,11 @@ fapi_try_exit: // Not reached return 0; +#else + + return i_original_value; + +#endif } /// @@ -177,6 +186,10 @@ fapi_try_exit: /// inline uint64_t vreg_coarse( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, const uint64_t i_original_value ) { + +// Anuwat has asked that we don't enforce this right now. +#ifdef ANUWAT_SAYS_DONT_DO_THIS_NOW + fapi2::buffer<uint64_t> l_value(i_original_value); uint8_t l_vccd_override = 0; @@ -204,6 +217,13 @@ fapi_try_exit: // Not reached return 0; + +#else + + return i_original_value; + +#endif + } /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C index b700aeacd..ff8277d45 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C @@ -45,6 +45,7 @@ #include <lib/dimm/kind.H> #include <lib/workarounds/mcbist_workarounds.H> #include <lib/mcbist/mcbist.H> +#include <lib/fir/fir.H> using fapi2::TARGET_TYPE_MCBIST; using fapi2::TARGET_TYPE_DIMM; @@ -135,6 +136,30 @@ fapi2::ReturnCode end_of_rank( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target return fapi2::FAPI2_RC_SUCCESS; } +/// +/// @brief WAT debug attention +/// For Nimbus DD1 the MCBIST engine uses the WAT debug bit as a workaround +/// @param[in] i_target the fapi2 target of the mcbist +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode wat_debug_attention( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target ) +{ + // MCBIST attentions are already special attention + if (mss::chip_ec_feature_mss_wat_debug_attn(i_target)) + { + fapi2::ReturnCode l_rc; + fir::reg<MCBIST_MCBISTFIRQ> mcbist_fir_register(i_target, l_rc); + FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCBIST_MCBISTFIRQ); + + FAPI_TRY(mcbist_fir_register.attention<MCBIST_MCBISTFIRQ_WAT_DEBUG_ATTN>().write()); + } + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + } // close namespace mcbist } // close namespace workarounds } // close namespace mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H index 0f8e9c978..c10868907 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H @@ -71,6 +71,14 @@ void replace_read_helper(mss::mcbist::program<fapi2::TARGET_TYPE_MCBIST>& i_prog fapi2::ReturnCode end_of_rank( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, mss::mcbist::program<fapi2::TARGET_TYPE_MCBIST>& i_program ); +/// +/// @brief WAT debug attention +/// For Nimbus DD1 the MCBIST engine uses the WAT debug bit as a workaround +/// @param[in] i_target the fapi2 target of the mcbist +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode wat_debug_attention( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target ); + } // close namespace mcbist } // close namespace workarounds } // close namespace mss diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C index d450c4ad1..05b3c64fe 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C @@ -43,6 +43,8 @@ #include <lib/utils/count_dimm.H> #include <lib/phy/adr32s.H> #include <lib/workarounds/dp16_workarounds.H> +#include <lib/fir/check.H> +#include <lib/fir/unmask.H> using fapi2::TARGET_TYPE_MCBIST; @@ -77,7 +79,7 @@ extern "C" FAPI_TRY( mss::dp16::reset_sysclk(i_target) ); // (Note: The chip should already be in this state.) - FAPI_DBG("All control signals to the PHYs should already be set to their inactive state, idle state, or inactive values"); + FAPI_DBG("All control signals to the PHYs should be set to their inactive state, idle state, or inactive values"); // 2. Assert reset to PHY for 32 memory clocks FAPI_TRY( mss::change_resetn(i_target, mss::HIGH), "change_resetn for %s failed", mss::c_str(i_target) ); @@ -159,14 +161,17 @@ extern "C" // Workarounds FAPI_TRY( mss::workarounds::dp16::after_phy_reset(i_target) ); - // If mss_unmask_ddrphy_errors gets it's own bad rc, - // it will commit the passed in rc (if non-zero), and return it's own bad rc. - // Else if mss_unmask_ddrphy_errors runs clean, - // it will just return the passed in rc. - // TODO RTC:159727 Need to code.. FAPI_TRY(mss_unmask_ddrphy_errors(i_target, rc)); + // Unmask the FIR we want unmasked after phy reset is complete. Note this is the "good path." + // The algorithm is 'good path do after_phy_reset, all paths (error or not) perform the checks + // which are defined in during_phy_reset'. We won't run after_phy_reset (unmask of FIR) unless + // we're done with a success. + FAPI_TRY( mss::unmask::after_phy_reset(i_target) ); fapi_try_exit: - return fapi2::current_err; + + // mss::check::during_phy_reset handles the error/no error case internally. All we need to do is + // return the ReturnCode it hands us - it's taken care of commiting anything it needed to. + return mss::check::during_phy_reset(i_target); } diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C index 079bb8e46..cac69b4d2 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C @@ -38,7 +38,6 @@ #include <p9_mss_draminit.H> #include <lib/utils/count_dimm.H> -#include <lib/fir/training_fir.H> #include <lib/utils/conversions.H> #include <lib/dimm/bcw_load.H> @@ -131,10 +130,10 @@ extern "C" // Clocks (CK_t,CK_c) need to be started and stable for 10ns or 5tCK // (whichever is greater) before CKE goes active. constexpr uint64_t DELAY_5TCK = 5; - uint64_t l_delay_in_ns = std::max( static_cast<uint64_t>(mss::DELAY_10NS), - mss::cycles_to_ns(i_target, DELAY_5TCK) ); + const uint64_t l_delay_in_ns = std::max( static_cast<uint64_t>(mss::DELAY_10NS), + mss::cycles_to_ns(i_target, DELAY_5TCK) ); - uint64_t l_delay_in_cycles = mss::ns_to_cycles(i_target, l_delay_in_ns); + const uint64_t l_delay_in_cycles = mss::ns_to_cycles(i_target, l_delay_in_ns); // Set our delay (for HW and SIM) FAPI_TRY( fapi2::delay(l_delay_in_ns, mss::cycles_to_simcycles(l_delay_in_cycles)) ); @@ -161,10 +160,6 @@ extern "C" // Load data buffer control words (BCW) FAPI_TRY( mss::bcw_load(i_target) ); - // Register has been configured, so we can unmask 'training' errors which includes parity - // which we want to see during MRS load - FAPI_TRY( mss::unmask_training_errors(i_target) ); - // Load MRS FAPI_TRY( mss::mrs_load(i_target) ); diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C index 09ee36669..c0995bed0 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C @@ -37,7 +37,7 @@ #include <mss.H> #include <p9_mss_draminit_mc.H> -#include <lib/fir/memdiags_fir.H> +#include <lib/fir/unmask.H> #include <lib/utils/find.H> #include <lib/utils/count_dimm.H> @@ -141,7 +141,7 @@ extern "C" } // At this point the DDR interface must be monitored for memory errors. Memory related FIRs should be unmasked. - FAPI_TRY( mss::unmask_memdiags_errors(i_target) ); + FAPI_TRY( mss::unmask::after_draminit_mc(i_target) ); fapi_try_exit: FAPI_INF("End draminit MC"); 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 0c1035d2f..28ad2f29f 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 @@ -38,6 +38,7 @@ #include <p9_mss_draminit_training.H> #include <lib/utils/count_dimm.H> +#include <lib/fir/unmask.H> using fapi2::TARGET_TYPE_MCBIST; using fapi2::TARGET_TYPE_MCA; @@ -218,7 +219,11 @@ extern "C" // So we're calibrated the entire port. If we're here either we didn't have any errors or the last error // seen on a port is the error for this entire controller. - fapi2::current_err = l_port_error; + FAPI_TRY(l_port_error, "Seeing port error, exiting training"); + + // Unmask FIR + FAPI_TRY( mss::unmask::after_draminit_training(i_target) ); + fapi_try_exit: FAPI_INF("End draminit training"); diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_scominit.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_scominit.C index 254221684..6a9eba234 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_scominit.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_scominit.C @@ -42,6 +42,7 @@ #include <lib/utils/find.H> #include <lib/phy/ddr_phy.H> #include <lib/mc/mc.H> +#include <lib/fir/unmask.H> using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_MCBIST; @@ -115,6 +116,9 @@ fapi2::ReturnCode p9_mss_scominit( const fapi2::Target<TARGET_TYPE_MCBIST>& i_ta // Initialize via scoms for non-static PHY items. FAPI_TRY( mss::phy_scominit(i_target) ); + // Do FIRry things + FAPI_TRY( mss::unmask::after_scominit(i_target) ); + fapi_try_exit: FAPI_INF("End MSS SCOM init"); return fapi2::current_err; diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_mss_eff_grouping.mk b/src/import/chips/p9/procedures/hwp/nest/p9_mss_eff_grouping.mk index 86e28ed1c..8bbfe2866 100644 --- a/src/import/chips/p9/procedures/hwp/nest/p9_mss_eff_grouping.mk +++ b/src/import/chips/p9/procedures/hwp/nest/p9_mss_eff_grouping.mk @@ -25,5 +25,4 @@ PROCEDURE=p9_mss_eff_grouping OBJS+=p9_fbc_utils.o $(call ADD_MODULE_INCDIR,$(PROCEDURE),$(ROOTPATH)/chips/p9/procedures/hwp/memory/) -$(call ADD_MODULE_INDDIR,$(PROCEDURE),$(ROOTPATH)/chips/p9/procedures/hwp/memory/lib) $(call BUILD_PROCEDURE) diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_revert_sbe_mcs_setup.C b/src/import/chips/p9/procedures/hwp/nest/p9_revert_sbe_mcs_setup.C index f153b6dd2..ac58ac5ef 100644 --- a/src/import/chips/p9/procedures/hwp/nest/p9_revert_sbe_mcs_setup.C +++ b/src/import/chips/p9/procedures/hwp/nest/p9_revert_sbe_mcs_setup.C @@ -134,10 +134,7 @@ revert_mcs_hb_dcbz_config(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_t FAPI_TRY(fapi2::putScom(i_target, MCS_MCMODE1_ARR[i_mcs], l_mcmode1), "Error from putScom (MCS%d_MCMODE1)", i_mcs); - // MCFIRMASK -- mask all errors - l_mcfirmask.flush<1>(); - FAPI_TRY(fapi2::putScom(i_target, MCS_MCFIRMASK_OR_ARR[i_mcs], l_mcfirmask), - "Error from putScom (MCS%d_MCFIRMASK_OR)", i_mcs); + // MCFIRMASK -- don't remask FIR (per Joe, Marc) } fapi_try_exit: diff --git a/src/import/chips/p9/procedures/xml/attribute_info/chip_ec_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/chip_ec_attributes.xml index 679201b8b..a7279fbe9 100644 --- a/src/import/chips/p9/procedures/xml/attribute_info/chip_ec_attributes.xml +++ b/src/import/chips/p9/procedures/xml/attribute_info/chip_ec_attributes.xml @@ -430,6 +430,23 @@ </attribute> <attribute> + <id>ATTR_CHIP_EC_FEATURE_MSS_WAT_DEBUG_ATTN</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description> + WAT Debug Attention work-around for Nimbus DD1.0 + </description> + <chipEcFeature> + <chip> + <name>ENUM_ATTR_NAME_NIMBUS</name> + <ec> + <value>0x20</value> + <test>LESS_THAN</test> + </ec> + </chip> + </chipEcFeature> + </attribute> + + <attribute> <id>ATTR_CHIP_EC_FEATURE_MSS_HW392781_RDARRAY_CLKGATE</id> <targetType>TARGET_TYPE_PROC_CHIP</targetType> <description> diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_ddr_phy_reset.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_ddr_phy_reset.xml index 30eebbba0..bf6775426 100644 --- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_ddr_phy_reset.xml +++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_ddr_phy_reset.xml @@ -376,7 +376,7 @@ <target>TARGET</target> </deconfigure> </hwpError> - + <hwpError> <rc>RC_MSS_INVALID_VPD_VALUE_MC_DRV_IMP_DQ_DQS</rc> <description> @@ -487,4 +487,31 @@ </deconfigure> </hwpError> +<hwpError> + <rc>RC_MSS_DDR_PHY_RESET_PORT_FIR</rc> + <description> + The port noted has set an error bit during PHY reset + </description> + <ffdc>CAL_FIR</ffdc> + <ffdc>PHY_FIR</ffdc> + <callout> + <target>MCA_TARGET</target> + <priority>HIGH</priority> + </callout> + <deconfigure> + <target>MCA_TARGET</target> + </deconfigure> +</hwpError> + +<hwpError> + <rc>RC_MSS_DDR_PHY_RESET_PORT_FIRS_REPORTED</rc> + <description> + One or more ports noted a set error bit during PHY reset + </description> + <callout> + <target>MCBIST_TARGET</target> + <priority>HIGH</priority> + </callout> +</hwpError> + </hwpErrors> |