/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist.C $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2019 */ /* [+] 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 exp_mcbist.C /// @brief Run and manage the MCBIST engine /// // *HWP HWP Owner: Stephen Glancy // *HWP HWP Backup: Andre Marin // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: FSP:HB #include #include #include #include #include #include #include namespace mss { /// /// @brief Gets the attribute for freq /// @param[in] const ref to the target /// @param[out] uint64_t& reference to store the value /// @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( const fapi2::Target& i_target, uint64_t& o_value) { // Each OCMB only has one MEM_PORT for (const auto l_port : mss::find_targets(i_target)) { return attr::get_freq(l_port, o_value); } o_value = 0; return ~fapi2::FAPI2_RC_SUCCESS; } const std::pair mcbistTraits::address_pairs[] = { { START_ADDRESS_0, END_ADDRESS_0 }, { START_ADDRESS_1, END_ADDRESS_1 }, { START_ADDRESS_2, END_ADDRESS_2 }, { START_ADDRESS_3, END_ADDRESS_3 }, }; const std::vector< mss::mcbist::op_type > mcbistTraits::FIFO_MODE_REQUIRED_OP_TYPES = { mss::mcbist::op_type::WRITE , mss::mcbist::op_type::READ , mss::mcbist::op_type::READ_WRITE , mss::mcbist::op_type::WRITE_READ , mss::mcbist::op_type::READ_WRITE_READ , mss::mcbist::op_type::READ_WRITE_WRITE , mss::mcbist::op_type::RAND_SEQ , mss::mcbist::op_type::READ_READ_WRITE , }; namespace mcbist { /// /// @brief Get a list of ports involved in the program /// Specialization for program<> /// @param[in] i_target the target for this program /// @return vector of port targets /// template<> std::vector> program<>::get_port_list( const fapi2::Target& i_target ) const { return mss::find_targets(i_target); } /// /// @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& i_target, mcbist::program& io_program) { // No broadcast mode for explorer return fapi2::FAPI2_RC_SUCCESS; } /// /// @brief Read entries from MCBIST Read Buffer (RB) array /// Specialization for fapi2::TARGET_TYPE_MEM_PORT /// @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[out] o_data vector of output data /// @param[out] o_ecc_data vector of ecc data /// @return FAPI2_RC_SUCCSS iff ok /// template<> fapi2::ReturnCode read_rb_array(const fapi2::Target& i_target, const uint64_t i_start_addr, const uint64_t i_num_entries, std::vector< fapi2::buffer >& o_data, std::vector< fapi2::buffer >& o_ecc_data) { using TT = mcbistTraits; fapi2::buffer l_data; uint64_t l_array_addr = i_start_addr; const auto& l_ocmb = mss::find_target(i_target); // Clear out any stale values from output vectors o_data.clear(); o_ecc_data.clear(); for (uint8_t l_index = 0; l_index < i_num_entries; ++l_index) { fapi2::buffer l_control_value; // set start address l_control_value.insertFromRight(l_array_addr); FAPI_INF("Setting the RB array access control register."); FAPI_TRY( mss::putScom(l_ocmb, TT::RD_BUF_CTL_REG, l_control_value) ); // We setup the address to what we need it to be, so let's continue FAPI_TRY( mss::getScom(i_target, TT::RD_BUF_DATA_REG, l_data) ); FAPI_INF("RB data index %d is: 0x%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::RD_BUF_ECC_REG, l_data) ); o_ecc_data.push_back(l_data); ++l_array_addr; // Array address automatically rolls over if we go beyond NUM_COMPARE_LOG_ENTRIES if (l_array_addr >= TT::NUM_COMPARE_LOG_ENTRIES) { l_array_addr = 0; } } fapi_try_exit: return fapi2::current_err; } } // namespace mcbist } // namespace mss