Skip to content

Commit

Permalink
Fixes MCBIST ecc/spare data pattern bug
Browse files Browse the repository at this point in the history
MCBIST wasn't setting up the ecc/spare DRAM's
data pattern registers. This commit fixes that bug
by taking the first byte of data and putting it into the
ecc/spare data registers

Change-Id: I5cdda1de8d123ff5f3bb991a2182c5027abb4f29
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/80769
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Reviewed-by: Mark Pizzutillo <mark.pizzutillo@ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/80790
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R Geddes <crgeddes@us.ibm.com>
  • Loading branch information
sglancy6 authored and crgeddes committed Jul 24, 2019
1 parent f2281d4 commit de35db8
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
Expand Up @@ -52,6 +52,36 @@
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H>
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist.H>

// This file is still necessary to put traits and generic code together
namespace mss
{

namespace mcbist
{

///
/// @brief Load MCBIST ECC (and?) spare data pattern given a pattern - explorer specialization
/// @param[in] i_target the target to effect
/// @param[in] i_pattern an mcbist::patterns
/// @param[in] i_invert whether to invert the pattern or not
/// @return FAPI2_RC_SUCCSS iff ok
///
template< >
inline fapi2::ReturnCode load_eccspare_pattern<mss::mc_type::EXPLORER>(
const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
const pattern& i_pattern,
const bool i_invert )
{
// First up assemble the pattern
const auto l_pattern = generate_eccspare_pattern(i_pattern, i_invert);

FAPI_TRY(fapi2::putScom(i_target, EXPLR_MCBIST_MCBFDQ, l_pattern));
FAPI_TRY(fapi2::putScom(i_target, EXPLR_MCBIST_MCBFDSPQ, l_pattern));

fapi_try_exit:
return fapi2::current_err;
}

} // ns mss

} // ns mcbist
#endif
22 changes: 22 additions & 0 deletions src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H
Expand Up @@ -126,6 +126,28 @@ fapi2::ReturnCode setup_broadcast_port_select(const fapi2::Target<T>& i_target,
template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
fapi2::ReturnCode enable_broadcast_mode(const fapi2::Target<T>& i_target, mcbist::program<>& io_program);

///
/// @brief Load MCBIST ECC (and?) spare data pattern given a pattern - explorer specialization
/// @param[in] i_target the target to effect
/// @param[in] i_pattern an mcbist::patterns
/// @param[in] i_invert whether to invert the pattern or not
/// @note this overload disappears when we have real patterns.
/// @return FAPI2_RC_SUCCSS iff ok
///
template< >
inline fapi2::ReturnCode load_eccspare_pattern<mss::mc_type::NIMBUS>(
const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
const pattern& i_pattern,
const bool i_invert )
{
// First up assemble the pattern
const auto l_pattern = generate_eccspare_pattern(i_pattern, i_invert);

FAPI_TRY(fapi2::putScom(i_target, MCBIST_MCBFDQ, l_pattern));

fapi_try_exit:
return fapi2::current_err;
}
} // namespace MCBIST

} // namespace mss
Expand Down
74 changes: 74 additions & 0 deletions src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H
Expand Up @@ -2779,6 +2779,78 @@ fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Helper for assembling the ecc/spare pattern
/// @param[in] i_data the data pattern for a single beat
/// @param[in] i_invert true if the data should be inverted
/// @return The data pattern for this beat (a single byte of dataa)
///
inline uint8_t generate_eccspare_pattern_helper(const uint64_t& i_data, const bool i_invert )
{
fapi2::buffer<uint64_t> l_data(i_invert ? ~i_data : i_data);
uint8_t l_byte = 0;
l_data.extractToRight<0, BITS_PER_BYTE>(l_byte);
return l_byte;
}

///
/// @brief Generates the pattern for the ECC and/or spare data
/// @param[in] i_pattern the pattern on which to operate
/// @param[in] i_invert true if the pattern should be inverted
/// @return ECC/spare pattern as needing to be put into the ECC/spare registers
///
inline fapi2::buffer<uint64_t> generate_eccspare_pattern(const pattern& i_pattern, const bool i_invert )
{
constexpr uint64_t BYTE0 = BITS_PER_BYTE * 0;
constexpr uint64_t BYTE1 = BITS_PER_BYTE * 1;
constexpr uint64_t BYTE2 = BITS_PER_BYTE * 2;
constexpr uint64_t BYTE3 = BITS_PER_BYTE * 3;
constexpr uint64_t BYTE4 = BITS_PER_BYTE * 4;
constexpr uint64_t BYTE5 = BITS_PER_BYTE * 5;
constexpr uint64_t BYTE6 = BITS_PER_BYTE * 6;
constexpr uint64_t BYTE7 = BITS_PER_BYTE * 7;

fapi2::buffer<uint64_t> l_pattern;

// Pattern assembly is a tad weird for ECC/spare
// The pattern is stored in the same register by byte
// So we want to keep the same data as the rest of the data
// As such, we want to grab each piece of data on a byte by byte basis, flip as needed, and append it to the pattern

// Beat 0/1
l_pattern.insertFromRight<BYTE0, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[0].first, i_invert));
l_pattern.insertFromRight<BYTE1, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[0].second, i_invert));

// Beat 2/3
l_pattern.insertFromRight<BYTE2, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[1].first, i_invert));
l_pattern.insertFromRight<BYTE3, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[1].second, i_invert));

// Beat 4/5
l_pattern.insertFromRight<BYTE4, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[2].first, i_invert));
l_pattern.insertFromRight<BYTE5, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[2].second, i_invert));

// Beat 6/7
l_pattern.insertFromRight<BYTE6, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[3].first, i_invert));
l_pattern.insertFromRight<BYTE7, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[3].second, i_invert));

return l_pattern;
}

///
/// @brief Load MCBIST ECC (and?) spare data pattern given a pattern
/// @tparam MC the mc type of the T
/// @tparam T, the fapi2::TargetType - derived
/// @tparam TT, the mcbistTraits associated with T - derived
/// @param[in] i_target the target to effect
/// @param[in] i_pattern an mcbist::patterns
/// @param[in] i_invert whether to invert the pattern or not
/// @note this overload disappears when we have real patterns.
/// @return FAPI2_RC_SUCCSS iff ok
///
template< mss::mc_type MC, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
inline fapi2::ReturnCode load_eccspare_pattern( const fapi2::Target<T>& i_target, const pattern& i_pattern,
const bool i_invert );

///
/// @brief Load MCBIST pattern given a pattern
/// @tparam MC the mc type of the T
Expand Down Expand Up @@ -2810,6 +2882,8 @@ inline fapi2::ReturnCode load_pattern( const fapi2::Target<T>& i_target, const p
++l_address;
}

FAPI_TRY(load_eccspare_pattern<MC>( i_target, i_pattern, i_invert ));

fapi_try_exit:
return fapi2::current_err;
}
Expand Down

0 comments on commit de35db8

Please sign in to comment.