diff options
author | Alvin Wang <wangat@tw.ibm.com> | 2019-03-14 10:25:31 -0500 |
---|---|---|
committer | Christian R. Geddes <crgeddes@us.ibm.com> | 2019-04-22 11:18:12 -0500 |
commit | 3c3ab2bd4c3cbee67eb518bcce214234d8f071f3 (patch) | |
tree | 6bf46537fd7357489516b93fdcc3d699248818be /src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C | |
parent | e4956ca54c226efdda7639decb8f06a92e586825 (diff) | |
download | talos-hostboot-3c3ab2bd4c3cbee67eb518bcce214234d8f071f3.tar.gz talos-hostboot-3c3ab2bd4c3cbee67eb518bcce214234d8f071f3.zip |
Move MCBIST lib to generic folder
Change-Id: Ib717742707bea6a626131578f5a3b1aeebc76281
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/69677
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Dev-Ready: STEPHEN GLANCY <sglancy@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/69707
Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Tested-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C')
-rw-r--r-- | src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C | 597 |
1 files changed, 70 insertions, 527 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C index f5ef0e24c..c5b43fce7 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C @@ -35,8 +35,8 @@ #include <lib/shared/nimbus_defaults.H> #include <fapi2.H> +#include <lib/mss_attribute_accessors.H> #include <lib/mcbist/mcbist.H> -#include <lib/utils/dump_regs.H> #include <lib/workarounds/mcbist_workarounds.H> #include <generic/memory/lib/utils/pos.H> @@ -47,7 +47,22 @@ using fapi2::TARGET_TYPE_MCS; namespace mss { -const std::pair<uint64_t, uint64_t> mcbistTraits<fapi2::TARGET_TYPE_MCBIST>::address_pairs[] = +/// +/// @brief Gets the attribute for freq +/// @param[in] const ref to the target +/// @param[out] uint64_t& reference to store the value +/// @note Generated by gen_accessors.pl generate_mc_port_params +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK +/// @note Frequency of this memory channel in MT/s (Mega Transfers per second) +/// +template<> +fapi2::ReturnCode freq<mss::mc_type::NIMBUS, fapi2::TARGET_TYPE_MCBIST>(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& + i_target, uint64_t& o_value) +{ + return mss::freq(i_target, o_value); +} + +const std::pair<uint64_t, uint64_t> mcbistTraits<>::address_pairs[] = { { START_ADDRESS_0, END_ADDRESS_0 }, { START_ADDRESS_1, END_ADDRESS_1 }, @@ -55,7 +70,7 @@ const std::pair<uint64_t, uint64_t> mcbistTraits<fapi2::TARGET_TYPE_MCBIST>::add { START_ADDRESS_3, END_ADDRESS_3 }, }; -const std::vector< mss::mcbist::op_type > mcbistTraits<fapi2::TARGET_TYPE_MCBIST>::FIFO_MODE_REQUIRED_OP_TYPES = +const std::vector< mss::mcbist::op_type > mcbistTraits<>::FIFO_MODE_REQUIRED_OP_TYPES = { mss::mcbist::op_type::WRITE , mss::mcbist::op_type::READ , @@ -71,459 +86,16 @@ namespace mcbist { /// -/// @brief Load MCBIST maint pattern given a pattern -/// @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< > -fapi2::ReturnCode load_maint_pattern( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - const pattern& i_pattern, - const bool i_invert ) -{ - // Init the fapi2 return code - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - // Array access control - fapi2::buffer<uint64_t> l_aacr; - // Array access data - fapi2::buffer<uint64_t> l_aadr; - - // first we must setup the access control register - // Setup the array address - // enable the auto increment bit - // set ecc mode bit on - l_aacr - .writeBit<MCA_WREITE_AACR_BUFFER>(mss::states::OFF) - .insertFromRight<MCA_WREITE_AACR_ADDRESS, MCA_WREITE_AACR_ADDRESS_LEN>(mss::mcbist::rmw_address::DW0) - .writeBit<MCA_WREITE_AACR_AUTOINC>(mss::states::ON) - .writeBit<MCA_WREITE_AACR_ECCGEN>(mss::states::ON); - - // This loop will be run twice to write the pattern twice. Once per 64B write. - // When MCBIST maint mode is in 64B mode it will only use the first 64B when in 128B mode - // MCBIST maint will use all 128B (it will perform two consecutive writes) - const auto l_ports = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target); - // Init the port map - - for (const auto& p : l_ports) - { - l_aacr.insertFromRight<MCA_WREITE_AACR_ADDRESS, MCA_WREITE_AACR_ADDRESS_LEN>(mss::mcbist::rmw_address::DW0); - - for (auto l_num_reads = 0; l_num_reads < 2; ++l_num_reads) - { - FAPI_INF("Setting the array access control register."); - FAPI_TRY( mss::putScom(p, MCA_WREITE_AACR, l_aacr) ); - - for (const auto& l_cache_line : i_pattern) - { - fapi2::buffer<uint64_t> l_value_first = i_invert ? ~l_cache_line.first : l_cache_line.first; - fapi2::buffer<uint64_t> l_value_second = i_invert ? ~l_cache_line.second : l_cache_line.second; - FAPI_INF("Loading cache line pattern 0x%016lx 0x%016lx", l_value_first, l_value_second); - FAPI_TRY( mss::putScom(p, MCA_AADR, l_value_first) ); - - // In order for the data to actually be written into the RMW buffer, we must issue a putscom to the MCA_AAER register - // This register is used for the ECC, we will just write all zero to this register. The ECC will be auto generated - // when the aacr MCA_WREITE_AACR_ECCGEN bit is set - FAPI_TRY( mss::putScom(p, MCA_AAER, 0) ); - - // No need to increment the address because the logic does it automatically when MCA_WREITE_AACR_AUTOINC is set - FAPI_TRY( mss::putScom(p, MCA_AADR, l_value_second) ); - - // In order for the data to actually be written into the RMW buffer, we must issue a putscom to the MCA_AAER register - // This register is used for the ECC, we will just write all zero to this register. The ECC will be auto generated - // when the aacr MCA_WREITE_AACR_ECCGEN bit is set - FAPI_TRY( mss::putScom(p, MCA_AAER, 0) ); - } - - l_aacr.insertFromRight<MCA_WREITE_AACR_ADDRESS, MCA_WREITE_AACR_ADDRESS_LEN>(mss::mcbist::rmw_address::DW8); - } - } - - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Load MCBIST data compare mask registers -/// @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_program the mcbist::program -/// @return FAPI2_RC_SUCCSS iff ok -/// -template< > -fapi2::ReturnCode load_data_compare_mask( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - const mcbist::program<TARGET_TYPE_MCBIST>& i_program ) -{ - typedef mcbistTraits<TARGET_TYPE_MCBIST> TT; - - // Init the fapi2 return code - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - // Load the MCBCM Data compare masks - - const auto l_ports = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target); - FAPI_INF("Loading the MCBIST data compare mask registers!"); - - for (const auto& p : l_ports) - { - FAPI_TRY( mss::putScom(p, TT::COMPARE_MASK, i_program.iv_compare_mask) ); - } - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Load MCBIST 24b random data seeds given a pattern index -/// @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_random24_data_seed mcbist::random24_data_seed -/// @param[in] i_random24_map mcbist::random24_seed_map -/// @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< > -fapi2::ReturnCode load_random24b_seeds( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - const random24_data_seed& i_random24_data_seed, - const random24_seed_map& i_random24_map, - const bool i_invert ) -{ - // Init the fapi2 return code - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - const uint64_t l_random_addr0 = MCBIST_MCBRDS0Q; - const uint64_t l_random_addr1 = MCBIST_MCBRDS1Q; - uint64_t l_index = 0; - uint64_t l_map_index = 0; - uint64_t l_map_offset = 0; - - fapi2::buffer<uint64_t> l_mcbrsd0q; - fapi2::buffer<uint64_t> l_mcbrsd1q; - - - // We are going to loop through the random seeds and load them into the random seed registers - // Because the 24b random data seeds share the same registers as the 24b random data byte LFSR maps - // we will load those as well - - for (const auto& l_seed : i_random24_data_seed) - { - FAPI_INF("Loading 24b random seed index %ld ", l_index); - fapi2::buffer<uint64_t> l_value = i_invert ? ~l_seed : l_seed; - - // Print an informational message to indicate if a random seed is 0 - // TK Do we want an error here? 0 may be used on purpose to hold a byte at all 0 on purpose - if ( l_value == 0 ) - { - FAPI_INF("Warning: Random 24b data seed is set to 0 for seed index %d", l_index); - } - - // If we are processing the first 24b random data seed we will add it to the fapi buffer - // we won't load it yet because the second 24b seed will be loaded into the same register - if ( l_index == 0 ) - { - l_mcbrsd0q.insertFromRight<MCBIST_MCBRDS0Q_DGEN_RNDD_SEED0, MCBIST_MCBRDS0Q_DGEN_RNDD_SEED0_LEN>(l_value); - } - // The second 24b random data seed is loaded into the same register as the first seed - // therefore we will add the second seed tothe fapi buffer and then issue the putscom - else if (l_index == 1 ) - { - l_mcbrsd0q.insertFromRight<MCBIST_MCBRDS0Q_DGEN_RNDD_SEED1, MCBIST_MCBRDS0Q_DGEN_RNDD_SEED1_LEN>(l_value); - FAPI_INF("Loading 24b random seeds 0 and 1 0x%016lx ", l_mcbrsd0q); - FAPI_TRY( mss::putScom(i_target, l_random_addr0, l_mcbrsd0q) ); - } - // The third 24b random data seed occupies the same register as the random data byte maps. Therefore we first - // add the third random 24b data seed to the register and then loop through all of the byte mappings a total of - // 9. ach of the byte mappings associates a byte of the random data to a byte in the 24b random data LFSRs - // Each byte map is offset by 4 bits in the register. - else - { - l_mcbrsd1q.insertFromRight<MCBIST_MCBRDS1Q_DGEN_RNDD_SEED2, MCBIST_MCBRDS1Q_DGEN_RNDD_SEED2_LEN>(l_value); - - for (const auto& l_map : i_random24_map) - { - l_map_offset = MCBIST_MCBRDS1Q_DGEN_RNDD_DATA_MAPPING + (l_map_index * RANDOM24_SEED_MAP_FIELD_LEN); - l_mcbrsd1q.insertFromRight(l_map, l_map_offset, RANDOM24_SEED_MAP_FIELD_LEN); - FAPI_INF("Loading 24b random seed map index %ld ", l_map_index); - FAPI_ASSERT( l_map_index < mss::mcbist::MAX_NUM_RANDOM24_MAPS, - fapi2::MSS_MEMDIAGS_INVALID_PATTERN_INDEX().set_INDEX(l_map_index), - "Attempting to load a 24b random data seed map which does not exist %d", l_map_index ); - ++l_map_index; - } - - FAPI_TRY( mss::putScom(i_target, l_random_addr1, l_mcbrsd1q) ); - } - - FAPI_ASSERT( l_index < MAX_NUM_RANDOM24_SEEDS, - fapi2::MSS_MEMDIAGS_INVALID_PATTERN_INDEX().set_INDEX(l_index), - "Attempting to load a 24b random data seed which does not exist %d", l_index ); - ++l_index; - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Load a set of MCBIST subtests in to the MCBIST registers -/// @tparam T, the fapi2::TargetType - derived -/// @tparam TT, the mcbistTraits associated with T - derived -/// @param[in] the target to effect -/// @param[in] the mcbist::program -/// @return FAPI2_RC_SUCCSS iff ok -/// @note assumes the MCBIST engine has been configured. -/// -template<> -fapi2::ReturnCode load_mcbmr( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - const mcbist::program<TARGET_TYPE_MCBIST>& i_program ) -{ - - // Leave if there are no subtests. - if (0 == i_program.iv_subtests.size()) - { - FAPI_INF("no subtests, nothing to do"); - return fapi2::current_err; - } - - // List of the 8 MCBIST registers - each holds 4 subtests. - static const std::vector< uint64_t > l_memory_registers = - { - MCBIST_MCBMR0Q, MCBIST_MCBMR1Q, MCBIST_MCBMR2Q, MCBIST_MCBMR3Q, - MCBIST_MCBMR4Q, MCBIST_MCBMR5Q, MCBIST_MCBMR6Q, MCBIST_MCBMR7Q, - }; - - std::vector< uint64_t > l_memory_register_buffers = - { - 0, 0, 0, 0, 0, 0, 0, 0, - }; - - static const size_t SUBTEST_PER_REG = 4; - static const size_t SUBTEST_PER_PROGRAM = 32; - - static const auto BITS_IN_SUBTEST = sizeof(mcbist::subtest_t<TARGET_TYPE_MCBIST>().iv_mcbmr) * 8; - static const auto LEFT_SHIFT = (sizeof(uint64_t) * 8) - BITS_IN_SUBTEST; - - ssize_t l_bin = -1; - size_t l_register_shift = 0; - - // We'll shift this in to position to indicate which subtest is the last - static const uint64_t l_done_bit( 0x8000000000000000 >> MCBIST_MCBMR0Q_MCBIST_CFG_TEST00_DONE ); - - // TK: For now limit MCBIST programs to 32 subtests. - const auto l_program_size = i_program.iv_subtests.size(); - FAPI_ASSERT( l_program_size <= SUBTEST_PER_PROGRAM, - fapi2::MSS_MCBIST_PROGRAM_TOO_BIG().set_PROGRAM_LENGTH(l_program_size), - "mcbist program of length %d exceeds arbitrary maximum of %d", l_program_size, SUBTEST_PER_PROGRAM ); - - // Distribute the program over the 8 MCBIST subtest registers - // We need the index, so increment thru i_program.iv_subtests.size() - for (size_t l_index = 0; l_index < l_program_size; ++l_index) - { - l_bin = (l_index % SUBTEST_PER_REG) == 0 ? l_bin + 1 : l_bin; - l_register_shift = (l_index % SUBTEST_PER_REG) * BITS_IN_SUBTEST; - - l_memory_register_buffers[l_bin] |= - (uint64_t(i_program.iv_subtests[l_index].iv_mcbmr) << LEFT_SHIFT) >> l_register_shift; - - FAPI_DBG("putting subtest %d (0x%x) in MCBMR%dQ shifted %d 0x%016llx", - l_index, i_program.iv_subtests[l_index].iv_mcbmr, l_bin, - l_register_shift, l_memory_register_buffers[l_bin]); - } - - // l_bin and l_register_shift are the values for the last subtest we'll tell the MCBIST about. - // We need to set that subtest's done-bit so the MCBIST knows it's the end of the line - l_memory_register_buffers[l_bin] |= l_done_bit >> l_register_shift; - FAPI_DBG("setting MCBMR%dQ subtest %llu as the last subtest 0x%016llx", - l_bin, l_register_shift, l_memory_register_buffers[l_bin]); - - // ... and slam the values in to the registers. - // Could just decrement l_bin, but that scoms the subtests in backwards and is confusing - for (auto l_index = 0; l_index <= l_bin; ++l_index) - { - FAPI_TRY( mss::putScom(i_target, l_memory_registers[l_index], l_memory_register_buffers[l_index]) ); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Poll the mcbist engine and check for errors -/// @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_program, the mcbist program which is executing -/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK -/// -template< fapi2::TargetType T, typename TT = mcbistTraits<T> > -fapi2::ReturnCode poll( const fapi2::Target<T>& i_target, const program<T>& i_program ) -{ - fapi2::buffer<uint64_t> l_status; - - static const uint64_t l_done = fapi2::buffer<uint64_t>().setBit<TT::MCBIST_DONE>(); - static const uint64_t l_fail = fapi2::buffer<uint64_t>().setBit<TT::MCBIST_FAIL>(); - static const uint64_t l_in_progress = fapi2::buffer<uint64_t>().setBit<TT::MCBIST_IN_PROGRESS>(); - - // A small vector of addresses to poll during the polling loop - const std::vector<mss::poll_probe<fapi2::TARGET_TYPE_MCBIST>> l_probes = - { - {i_target, "mcbist current address", MCBIST_MCBMCATQ}, - }; - - mss::poll(i_target, TT::STATQ_REG, i_program.iv_poll, - [&l_status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool - { - FAPI_DBG("mcbist statq 0x%llx, remaining: %d", stat_reg, poll_remaining); - l_status = stat_reg; - return l_status.getBit<TT::MCBIST_IN_PROGRESS>() != 1; - }, - l_probes); - - // Check to see if we're still in progress - meaning we timed out. - FAPI_ASSERT((l_status & l_in_progress) != l_in_progress, - fapi2::MSS_MCBIST_TIMEOUT().set_MCBIST_TARGET(i_target), - "MCBIST timed out %s", mss::c_str(i_target)); - - // The control register has a bit for done-and-happy and a bit for done-and-unhappy - if ( ((l_status & l_done) == l_done) || ((l_status & l_fail) == l_fail) ) - { - FAPI_INF("MCBIST completed, processing errors"); - - // We're done. It doesn't mean that there were no errors. - FAPI_TRY( i_program.process_errors(i_target) ); - - // If we're here there were no errors, but lets report if the fail bit was set anyway. - FAPI_ASSERT( (l_status & l_fail) != l_fail, - fapi2::MSS_MCBIST_UNKNOWN_FAILURE() - .set_MCBIST_TARGET(i_target) - .set_STATUS_REGISTER(l_status), - "%s MCBIST reported a fail, but process_errors didn't find it 0x%016llx", - mss::c_str(i_target), l_status ); - - // And if we're here all is good with the world. - return fapi2::current_err; - } - - FAPI_ASSERT(false, - fapi2::MSS_MCBIST_DATA_FAIL() - .set_MCBIST_TARGET(i_target) - .set_STATUS_REGISTER(l_status), - "%s MCBIST executed but we got corrupted data in the control register 0x%016llx", - mss::c_str(i_target), l_status ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Execute the mcbist program -/// @param[in] i_target the target to effect -/// @param[in] i_program, the mcbist program to execute -/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK -/// -template<> -fapi2::ReturnCode execute( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - const program<TARGET_TYPE_MCBIST>& i_program ) -{ - typedef mcbistTraits<TARGET_TYPE_MCBIST> TT; - - fapi2::buffer<uint64_t> l_status; - bool l_poll_result = false; - poll_parameters l_poll_parameters; - - // Before we go off into the bushes, lets see if there are any instructions in the - // program. If not, we can save everyone the hassle - FAPI_ASSERT(0 != i_program.iv_subtests.size(), - fapi2::MSS_MEMDIAGS_NO_MCBIST_SUBTESTS().set_MCBIST_TARGET(i_target), - "Attempt to run an MCBIST program with no subtests on %s", mss::c_str(i_target)); - - // Implement any mcbist work-arounds. - // I'm going to do the unthinkable here - and cast away the const of the mcbist program input. - // The work arounds need to change this, and so it needs to not be const. However, I don't want - // to risk general const-correctness by changing the input parameter to non-const. So, I use - // const_cast<> (ducks out of the way of the flying adjectives.) These are work-arounds ... - FAPI_TRY( workarounds::mcbist::end_of_rank(i_target, const_cast<program<TARGET_TYPE_MCBIST>&>(i_program)) ); - - FAPI_TRY( clear_errors(i_target) ); - - // Configures the write/read FIFO bit - FAPI_TRY( load_fifo_mode( i_target, i_program) ); - - // Slam the address generator config - FAPI_TRY( load_addr_gen(i_target, i_program) ); - - // Slam the parameters in to the mcbist parameter register - FAPI_TRY( load_mcbparm(i_target, i_program) ); - - // Slam the configured address maps down - FAPI_TRY( load_mcbamr( i_target, i_program) ); - - // Slam the config register down - FAPI_TRY( load_config( i_target, i_program) ); - - // Slam the control register down - FAPI_TRY( load_control( i_target, i_program) ); - - // Load the patterns and any associated bits for random, etc - FAPI_TRY( load_data_config( i_target, i_program) ); - - // Load the thresholds - FAPI_TRY( load_thresholds( i_target, i_program) ); - - // Slam the subtests in to the mcbist registers - // Always do this last so the action file triggers see the other bits set - FAPI_TRY( load_mcbmr(i_target, i_program) ); - - // Start the engine, and then poll for completion - FAPI_TRY(start_stop(i_target, mss::START)); - - // Verify that the in-progress bit has been set, so we know we started - // Don't use the program's poll as it could be a very long time. Use the default poll. - l_poll_result = mss::poll(i_target, TT::STATQ_REG, l_poll_parameters, - [&l_status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool - { - FAPI_DBG("looking for mcbist start, mcbist statq 0x%llx, remaining: %d", stat_reg, poll_remaining); - l_status = stat_reg; - // We're done polling when either we see we're in progress or we see we're done. - return (l_status.getBit<TT::MCBIST_IN_PROGRESS>() == true) || (l_status.getBit<TT::MCBIST_DONE>() == true); - }); - - // So we've either run/are running or we timed out waiting for the start. - FAPI_ASSERT( l_poll_result == true, - fapi2::MSS_MEMDIAGS_MCBIST_FAILED_TO_START().set_MCBIST_TARGET(i_target), - "The MCBIST engine failed to start its program" ); - - // If the user asked for async mode, we can leave. Otherwise, poll and check for errors - if (!i_program.iv_async) - { - return mcbist::poll(i_target, i_program); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// /// @brief Get a list of ports involved in the program -/// Specialization for program<fapi2::TARGET_TYPE_MCBIST> +/// Specialization for program<> /// @param[in] i_target the target for this program /// @return vector of port targets /// template<> -template<> std::vector<fapi2::Target<fapi2::TARGET_TYPE_MCA>> - program<fapi2::TARGET_TYPE_MCBIST>::get_port_list<fapi2::TARGET_TYPE_MCA>( const - fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target ) const + program<>::get_port_list( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target ) const { - typedef mss::mcbistTraits<TARGET_TYPE_MCBIST> TT; + using TT = mss::mcbistTraits<>; std::vector<fapi2::Target<fapi2::TARGET_TYPE_MCA>> l_list; @@ -542,81 +114,6 @@ std::vector<fapi2::Target<fapi2::TARGET_TYPE_MCA>> return l_list; } -/// -/// @brief Read entries from MCBIST Read Modify Write (RMW) array -/// Specialization for fapi2::TARGET_TYPE_MCA -/// @param[in] i_target the target to effect -/// @param[in] i_start_addr the array address to read first -/// @param[in] i_num_entries the number of array entries to read -/// @param[in] i_roll_over_for_compare_mode set to true if only using first -/// NUM_COMPARE_INFO_ENTRIES of array, so array address rolls over at correct value -/// @param[out] o_data vector of output data -/// @param[out] o_ecc_data vector of ecc data -/// @return FAPI2_RC_SUCCSS iff ok -/// @note The number of entries in the array depends on i_roll_over_for_compare_mode parameter: -/// (NUM_COMPARE_LOG_ENTRIES for false, NUM_COMPARE_INFO_ENTRIES for true) but user may read more than -/// that since reads work in a circular buffer fashion -/// -template<> -fapi2::ReturnCode read_rmw_array(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, - const uint64_t i_start_addr, - const uint64_t i_num_entries, - const bool i_roll_over_for_compare_mode, - std::vector< fapi2::buffer<uint64_t> >& o_data, - std::vector< fapi2::buffer<uint64_t> >& o_ecc_data) -{ - typedef mcbistTraits<fapi2::TARGET_TYPE_MCA> TT; - - fapi2::buffer<uint64_t> l_control_value; - fapi2::buffer<uint64_t> l_data; - uint64_t l_array_addr = i_start_addr; - - // Clear out any stale values from output vectors - o_data.clear(); - o_ecc_data.clear(); - - // Set the control register for the RMW array - l_control_value.writeBit<TT::RMW_WRT_BUFFER_SEL>(TT::SELECT_RMW_BUFFER) - // set start address - .insertFromRight<TT::RMW_WRT_ADDRESS, TT::RMW_WRT_ADDRESS_LEN>(l_array_addr) - // enable the auto increment bit - .setBit<TT::RMW_WRT_AUTOINC>() - // set ecc mode bit off - .clearBit<TT::RMW_WRT_ECCGEN>(); - - FAPI_INF("Setting the RMW array access control register."); - FAPI_TRY( mss::putScom(i_target, TT::RMW_WRT_BUF_CTL_REG, l_control_value) ); - - for (uint8_t l_index = 0; l_index < i_num_entries; ++l_index) - { - // Read info out of RMW array and put into output vector - // Note that since we enabled AUTOINC above, reading ECC_REG will increment - // the array pointer so the next DATA_REG read will read the next array entry - FAPI_TRY( mss::getScom(i_target, TT::RMW_WRT_BUF_DATA_REG, l_data) ); - - FAPI_INF("RMW data index %d is: %016lx", l_array_addr, l_data); - o_data.push_back(l_data); - - // Need to read ecc register to increment array index - FAPI_TRY( mss::getScom(i_target, TT::RMW_WRT_BUF_ECC_REG, l_data) ); - o_ecc_data.push_back(l_data); - ++l_array_addr; - - // Need to manually roll over address if we go beyond NUM_COMPARE_INFO_ENTRIES - // Since actual array is bigger than what is used for compare mode - if (i_roll_over_for_compare_mode && - (l_array_addr >= TT::NUM_COMPARE_INFO_ENTRIES)) - { - FAPI_INF("Rolling over the RMW array access control register address from %d to %d.", (i_start_addr + l_index), 0); - l_control_value.clearBit<TT::RMW_WRT_ADDRESS, TT::RMW_WRT_ADDRESS_LEN>(); - FAPI_TRY( mss::putScom(i_target, TT::RMW_WRT_BUF_CTL_REG, l_control_value) ); - l_array_addr = 0; - } - } - -fapi_try_exit: - return fapi2::current_err; -} /// /// @brief Read entries from MCBIST Read Buffer (RB) array @@ -635,7 +132,7 @@ fapi2::ReturnCode read_rb_array(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_t std::vector< fapi2::buffer<uint64_t> >& o_data, std::vector< fapi2::buffer<uint64_t> >& o_ecc_data) { - typedef mcbistTraits<fapi2::TARGET_TYPE_MCS> TT; + using TT = mcbistTraits<DEFAULT_MC_TYPE, fapi2::TARGET_TYPE_MCS>; fapi2::buffer<uint64_t> l_control_value; fapi2::buffer<uint64_t> l_data; @@ -687,7 +184,7 @@ fapi_try_exit: /// @param[in] i_targets the vector of targets to analyze - specialization for MCA target type /// @return l_capable - yes iff these vector of targets are broadcast capable /// -template< > +template<> const mss::states is_broadcast_capable(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_MCA>>& i_targets) { // If we don't have MCA's exit out @@ -911,7 +408,7 @@ fapi_try_exit: /// template< > fapi2::ReturnCode enable_broadcast_mode(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - mcbist::program<fapi2::TARGET_TYPE_MCBIST>& io_program) + mcbist::program<>& io_program) { // constexpr's for beautification constexpr bool ENABLE = true; @@ -934,6 +431,52 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Configures broadcast mode, if it is needed +/// @param[in] i_target the target to effect +/// @param[in,out] io_program the mcbist::program +/// @return FAPI2_RC_SUCCSS iff ok +/// +template<> +fapi2::ReturnCode configure_broadcast_mode(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, + mcbist::program<>& io_program) +{ + // If we're not capable to do broadcast mode on this target, exit out + const auto l_broadcast_capable = is_broadcast_capable(i_target); + + if(l_broadcast_capable == mss::states::NO) + { + FAPI_INF("%s is not broadcast capable, skipping enablement of broadcast mode", mss::c_str(i_target)); + return fapi2::FAPI2_RC_SUCCESS; + } + + // Enable broadcast mode + FAPI_INF("%s is broadcast capable, enabling broadcast mode", mss::c_str(i_target)); + return enable_broadcast_mode(i_target, io_program); +} + +/// +/// @brief Clear the errors helper. Chip can specialise this +/// function to put any necessary workaround in it. +/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK +/// +template< > +fapi2::ReturnCode clear_error_helper( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, + const program<>& i_program ) +{ + // Implement any mcbist work-arounds. + // I'm going to do the unthinkable here - and cast away the const of the mcbist program input. + // The work arounds need to change this, and so it needs to not be const. However, I don't want + // to risk general const-correctness by changing the input parameter to non-const. So, I use + // const_cast<> (ducks out of the way of the flying adjectives.) These are work-arounds ... + FAPI_TRY( workarounds::mcbist::end_of_rank(i_target, const_cast<program<>&>(i_program)) ); + + FAPI_TRY( clear_errors(i_target) ); + +fapi_try_exit: + return fapi2::current_err; +} + } // namespace MCBIST // Note: outside of the mcbist namespace |