summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib/ccs
diff options
context:
space:
mode:
authorBrian Silver <bsilver@us.ibm.com>2015-12-28 11:26:59 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-04-01 21:20:07 -0400
commit2dbce731a9de46f7f30df1eaa88b0b35a7797bc6 (patch)
treef5756a02b9bc91d33589dedd18117e9190951cff /src/import/chips/p9/procedures/hwp/memory/lib/ccs
parent3ab41df3a6aabf47bcae6bf5b50dca05616929d6 (diff)
downloadtalos-hostboot-2dbce731a9de46f7f30df1eaa88b0b35a7797bc6.tar.gz
talos-hostboot-2dbce731a9de46f7f30df1eaa88b0b35a7797bc6.zip
Initial commit of memory subsystem
Change-Id: Ia6375304adaa7e04dfa642e144341d7a5776673a Original-Change-Id: I6b63d2c4eec5d77585c91d905a464962a6153a0a Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/22978 Tested-by: Jenkins Server Reviewed-by: Craig C. Hamilton <cchamilt@us.ibm.com> Reviewed-by: Brian Silver <bsilver@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22759 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/ccs')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C254
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H648
2 files changed, 902 insertions, 0 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C
new file mode 100644
index 000000000..5753fd577
--- /dev/null
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C
@@ -0,0 +1,254 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: chips/p9/procedures/hwp/memory/lib/ccs/ccs.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* EKB Project */
+/* */
+/* COPYRIGHT 2015 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file ccs.C
+/// @brief Run and manage the CCS engine
+///
+// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Craig Hamilton <cchamilt@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: FSP:HB
+
+#include <fapi2.H>
+
+#include "../mss.H"
+#include "ccs.H"
+
+using fapi2::TARGET_TYPE_MCBIST;
+using fapi2::TARGET_TYPE_MCA;
+
+using fapi2::FAPI2_RC_SUCCESS;
+
+namespace mss
+{
+namespace ccs
+{
+
+///
+/// @brief Start or stop the CCS engine
+/// @param[in] i_target The MCBIST containing the CCS engine
+/// @param[in] i_start_stop bool MSS_CCS_START for starting, MSS_CCS_STOP otherwise
+/// @return FAPI2_RC_SUCCESS iff success
+///
+template<>
+fapi2::ReturnCode start_stop( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, bool i_start_stop )
+{
+ typedef ccsTraits<TARGET_TYPE_MCBIST> TT;
+
+ fapi2::buffer<uint64_t> l_buf;
+
+ // Do we need to read this? We are setting the only bit defined in the scomdef? BRS
+ FAPI_TRY(fapi2::getScom(i_target, TT::CNTLQ_REG, l_buf));
+
+ FAPI_TRY( fapi2::putScom(i_target, TT::CNTLQ_REG,
+ i_start_stop ? l_buf.setBit<TT::CCS_START>() : l_buf.setBit<TT::CCS_STOP>()) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Determine the CCS failure type
+/// @tparam T the fapi2 target type of the target for this error
+/// @param[in] the failure type
+/// @return ReturnCode associated with the fail.
+/// @note FFDC is handled here, caller doesn't need to do it
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode fail_type( const fapi2::Target<T>& i_target, const uint64_t& i_type )
+{
+ FAPI_ASSERT(STAT_READ_MISCOMPARE != i_type,
+ fapi2::MSS_CCS_READ_MISCOMPARE().set_TARGET_IN_ERROR(i_target),
+ "CCS FAIL Read Miscompare");
+
+ FAPI_ASSERT(STAT_UE_SUE != i_type,
+ fapi2::MSS_CCS_UE_SUE().set_TARGET_IN_ERROR(i_target),
+ "CCS FAIL UE or SUE Error");
+
+ FAPI_ASSERT(STAT_CAL_TIMEOUT != i_type,
+ fapi2::MSS_CCS_CAL_TIMEOUT().set_TARGET_IN_ERROR(i_target),
+ "CCS FAIL Calibration Operation Time Out");
+
+ FAPI_ASSERT(STAT_HUNG != i_type,
+ fapi2::MSS_CCS_HUNG().set_TARGET_IN_ERROR(i_target),
+ "CCS appears hung");
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Execute the contents of the CCS array
+/// @param[in] i_target The MCBIST containing the array
+/// @param[in] the MCBIST ccs program - to get the polling parameters
+/// @return FAPI2_RC_SUCCESS iff success
+///
+template<>
+fapi2::ReturnCode execute_inst_array(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
+ ccs::program<TARGET_TYPE_MCBIST>& i_program)
+{
+ typedef ccsTraits<TARGET_TYPE_MCBIST> TT;
+
+ fapi2::buffer<uint64_t> status;
+
+ FAPI_TRY(start_stop(i_target, mss::START));
+
+ mss::poll(i_target, TT::STATQ_REG, i_program.iv_poll,
+ [&status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_DBG("ccs statq 0x%llx, remaining: %d", stat_reg, poll_remaining);
+ status = stat_reg;
+ return status.getBit<TT::CCS_IN_PROGRESS>() != 1;
+ });
+
+ // Check for done and success. DONE being the only bit set.
+ if (status == STAT_QUERY_SUCCESS)
+ {
+ FAPI_DBG("CCS Executed Successfully.");
+ goto fapi_try_exit;
+ }
+
+ // So we failed or we're still in progress. Mask off the fail bits
+ // and run this through the FFDC generator.
+ FAPI_TRY( fail_type(i_target, status & 0x1C00000000000000) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Execute a set of CCS instructions
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the vector of instructions
+/// @param[in] the vector of ports
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note assumes the CCS engine has been configured.
+///
+template<>
+fapi2::ReturnCode execute( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
+ ccs::program<TARGET_TYPE_MCBIST>& i_program,
+ const std::vector< fapi2::Target<TARGET_TYPE_MCA> >& i_ports)
+{
+ // Subtract one for the idle we insert at the end
+ static const size_t CCS_INSTRUCTION_DEPTH = 32 - 1;
+ static const uint64_t CCS_ARR0_ZERO = MCBIST_CCS_INST_ARR0_00;
+ static const uint64_t CCS_ARR1_ZERO = MCBIST_CCS_INST_ARR1_00;
+
+ ccs::instruction_t<TARGET_TYPE_MCBIST> l_des = ccs::des_command<TARGET_TYPE_MCBIST>();
+
+ FAPI_DBG("loading ccs instructions (%d) for %s", i_program.iv_instructions.size(), mss::c_str(i_target));
+
+ auto l_inst_iter = i_program.iv_instructions.begin();
+
+ while (l_inst_iter != i_program.iv_instructions.end())
+ {
+ size_t l_inst_count = 0;
+
+ uint64_t l_total_delay = 0;
+ uint64_t l_delay = 0;
+ uint64_t l_repeat = 0;
+
+ // Shove the instructions into the CCS engine, in 32 instruction chunks, and execute them
+ for (; l_inst_iter != i_program.iv_instructions.end()
+ && l_inst_count < CCS_INSTRUCTION_DEPTH; ++l_inst_count, ++l_inst_iter)
+ {
+ // Make sure this instruction leads to the next. Notice this limits this mechanism to pretty
+ // simple (straight line) CCS programs. Anything with a loop or such will need another mechanism.
+ l_inst_iter->arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_GOTO_CMD,
+ MCBIST_CCS_INST_ARR1_00_GOTO_CMD_LEN>(l_inst_count + 1);
+ FAPI_TRY( fapi2::putScom(i_target, CCS_ARR0_ZERO + l_inst_count, l_inst_iter->arr0) );
+ FAPI_TRY( fapi2::putScom(i_target, CCS_ARR1_ZERO + l_inst_count, l_inst_iter->arr1) );
+
+ // arr1 contains a specification of the delay and repeat after this instruction, as well
+ // as a repeat. Total up the delays as we go so we know how long to wait before polling
+ // the CCS engine for completion
+ l_inst_iter->arr1.extractToRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(l_delay);
+ l_inst_iter->arr1.extractToRight<MCBIST_CCS_INST_ARR1_00_REPEAT_CMD_CNT,
+ MCBIST_CCS_INST_ARR1_00_REPEAT_CMD_CNT>(l_repeat);
+
+ l_total_delay += l_delay * (l_repeat + 1);
+
+ FAPI_DBG("css inst %d: 0x%016lX 0x%016lX (0x%lx, 0x%lx) delay: 0x%x (0x%x) %s",
+ l_inst_count, l_inst_iter->arr0, l_inst_iter->arr1,
+ CCS_ARR0_ZERO + l_inst_count, CCS_ARR1_ZERO + l_inst_count,
+ l_delay, l_total_delay, mss::c_str(i_target));
+ }
+
+ // Check our program for any delays. If there isn't a iv_initial_delay configured, then
+ // we use the delay we just summed from the instructions.
+ if (i_program.iv_poll.iv_initial_delay == 0)
+ {
+ i_program.iv_poll.iv_initial_delay = cycles_to_ns(i_target, l_total_delay);
+ }
+
+ if (i_program.iv_poll.iv_initial_sim_delay == 0)
+ {
+ i_program.iv_poll.iv_initial_sim_delay = cycles_to_simcycles(l_total_delay);
+ }
+
+ FAPI_DBG("executing ccs instructions (%d:%d, %d) for %s",
+ i_program.iv_instructions.size(), l_inst_count, i_program.iv_poll.iv_initial_delay, mss::c_str(i_target));
+
+ // Insert a DES as our last instruction. DES is idle state anyway and having this
+ // here as an instruction forces the CCS engine to wait the delay specified in
+ // the last instruction in this array (which it otherwise doesn't do.)
+ l_des.arr1.setBit<MCBIST_CCS_INST_ARR1_00_END>();
+ FAPI_TRY( fapi2::putScom(i_target, CCS_ARR0_ZERO + l_inst_count, l_des.arr0) );
+ FAPI_TRY( fapi2::putScom(i_target, CCS_ARR1_ZERO + l_inst_count, l_des.arr1) );
+
+ FAPI_DBG("css inst %d fixup: 0x%016lX 0x%016lX (0x%lx, 0x%lx) %s",
+ l_inst_count, l_des.arr0, l_des.arr1,
+ CCS_ARR0_ZERO + l_inst_count, CCS_ARR1_ZERO + l_inst_count, mss::c_str(i_target));
+
+ // Kick off the CCS engine - per port. No broadcast mode for CCS (per Shelton 9/23/15)
+ for (auto p : i_ports)
+ {
+ FAPI_DBG("executing CCS array for port %d (%s)", mss::pos(p), mss::c_str(p));
+ FAPI_TRY( select_ports( i_target, mss::pos(p)) );
+ FAPI_TRY( execute_inst_array(i_target, i_program) );
+ }
+ }
+
+fapi_try_exit:
+ i_program.iv_instructions.clear();
+ return fapi2::current_err;
+}
+
+///
+/// @brief Nimbus specialization for modeq_copy_cke_to_spare_cke
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the buffer representing the mode register
+/// @param[in] bool, true iff Copy CKE signals to CKE Spare on both ports
+/// @return void
+/// @note no-op for p9n
+///
+template<>
+void copy_cke_to_spare_cke<TARGET_TYPE_MCBIST>( const fapi2::Target<TARGET_TYPE_MCBIST>&, fapi2::buffer<uint64_t>&,
+ bool )
+{
+ return;
+}
+
+} // namespace
+} // namespace
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H
new file mode 100644
index 000000000..d5008f660
--- /dev/null
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H
@@ -0,0 +1,648 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: chips/p9/procedures/hwp/memory/lib/ccs/ccs.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* EKB Project */
+/* */
+/* COPYRIGHT 2015 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file ccs.H
+/// @brief Run and manage the CCS engine
+///
+// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Craig Hamilton <cchamilt@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 1
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_CCS_H_
+#define _MSS_CCS_H_
+
+#include <fapi2.H>
+
+#include <p9_mc_scom_addresses.H>
+
+#include "../utils/poll.H"
+#include "../port/port.H"
+#include "../shared/mss_const.H"
+
+// I have a dream that the CCS engine code can be shared among controllers. So, I drive the
+// engine from a set of traits. This might be folly. Allow me to dream. BRS
+
+template< fapi2::TargetType T >
+class ccsTraits;
+
+// Centaur CCS Engine traits
+template<>
+class ccsTraits<fapi2::TARGET_TYPE_MEMBUF_CHIP>
+{
+ public:
+};
+
+// Nimbus CCS Engine traits
+template<>
+class ccsTraits<fapi2::TARGET_TYPE_MCBIST>
+{
+ public:
+ static const uint64_t MODEQ_REG = MCBIST_CCS_MODEQ;
+ static const uint64_t MCB_CNTL_REG = MCBIST_MCB_CNTLQ;
+ static const uint64_t CNTLQ_REG = MCBIST_CCS_CNTLQ;
+ static const uint64_t STATQ_REG = MCBIST_CCS_STATQ;
+
+ enum
+ {
+ // CCS MODEQ
+ STOP_ON_ERR = MCBIST_CCS_MODEQ_STOP_ON_ERR,
+ UE_DISABLE = MCBIST_CCS_MODEQ_UE_DISABLE,
+ DATA_COMPARE_BURST_SEL = MCBIST_CCS_MODEQ_DATA_COMPARE_BURST_SEL,
+ DATA_COMPARE_BURST_SEL_LEN = MCBIST_CCS_MODEQ_DATA_COMPARE_BURST_SEL_LEN,
+ DDR_CAL_TIMEOUT_CNT = MCBIST_CCS_MODEQ_DDR_CAL_TIMEOUT_CNT,
+ DDR_CAL_TIMEOUT_CNT_LEN = MCBIST_CCS_MODEQ_DDR_CAL_TIMEOUT_CNT_LEN,
+ CFG_PARITY_AFTER_CMD = MCBIST_CCS_MODEQ_CFG_PARITY_AFTER_CMD,
+ COPY_CKE_TO_SPARE_CKE = MCBIST_CCS_MODEQ_COPY_CKE_TO_SPARE_CKE,
+ DISABLE_ECC_ARRAY_CHK = MCBIST_CCS_MODEQ_DISABLE_ECC_ARRAY_CHK,
+ DISABLE_ECC_ARRAY_CORRECTION = MCBIST_CCS_MODEQ_DISABLE_ECC_ARRAY_CORRECTION,
+ CFG_DGEN_FIXED_MODE = MCBIST_CCS_MODEQ_CFG_DGEN_FIXED_MODE,
+ DDR_CAL_TIMEOUT_CNT_MULT = MCBIST_CCS_MODEQ_DDR_CAL_TIMEOUT_CNT_MULT,
+ DDR_CAL_TIMEOUT_CNT_MULT_LEN = MCBIST_CCS_MODEQ_DDR_CAL_TIMEOUT_CNT_MULT_LEN,
+ IDLE_PAT_ADDRESS_0_13 = MCBIST_CCS_MODEQ_IDLE_PAT_ADDRESS_0_13,
+ IDLE_PAT_ADDRESS_0_13_LEN = MCBIST_CCS_MODEQ_IDLE_PAT_ADDRESS_0_13_LEN,
+ IDLE_PAT_ADDRESS_17 = MCBIST_CCS_MODEQ_IDLE_PAT_ADDRESS_17,
+ IDLE_PAT_BANK_GROUP_1 = MCBIST_CCS_MODEQ_IDLE_PAT_BANK_GROUP_1,
+ IDLE_PAT_BANK_0_1 = MCBIST_CCS_MODEQ_IDLE_PAT_BANK_0_1,
+ IDLE_PAT_BANK_0_1_LEN = MCBIST_CCS_MODEQ_IDLE_PAT_BANK_0_1_LEN,
+ IDLE_PAT_BANK_GROUP_0 = MCBIST_CCS_MODEQ_IDLE_PAT_BANK_GROUP_0,
+ IDLE_PAT_ACTN = MCBIST_CCS_MODEQ_IDLE_PAT_ACTN,
+ IDLE_PAT_ADDRESS_16 = MCBIST_CCS_MODEQ_IDLE_PAT_ADDRESS_16,
+ IDLE_PAT_ADDRESS_15 = MCBIST_CCS_MODEQ_IDLE_PAT_ADDRESS_15,
+ IDLE_PAT_ADDRESS_14 = MCBIST_CCS_MODEQ_IDLE_PAT_ADDRESS_14,
+ NTTM_MODE = MCBIST_CCS_MODEQ_NTTM_MODE,
+ NTTM_RW_DATA_DLY = MCBIST_CCS_MODEQ_NTTM_RW_DATA_DLY,
+ NTTM_RW_DATA_DLY_LEN = MCBIST_CCS_MODEQ_NTTM_RW_DATA_DLY_LEN,
+ IDLE_PAT_BANK_2 = MCBIST_CCS_MODEQ_IDLE_PAT_BANK_2,
+ DDR_PARITY_ENABLE = MCBIST_CCS_MODEQ_DDR_PARITY_ENABLE,
+ IDLE_PAT_PARITY = MCBIST_CCS_MODEQ_IDLE_PAT_PARITY,
+
+ // MCB_CNTRL
+ MCB_CNTL_PORT_SEL = MCBIST_MCB_CNTLQ_MCBCNTL_PORT_SEL,
+ MCB_CNTL_PORT_SEL_LEN = MCBIST_MCB_CNTLQ_MCBCNTL_PORT_SEL_LEN,
+
+ // CCS CNTL
+ CCS_START = MCBIST_CCS_CNTLQ_START,
+ CCS_STOP = MCBIST_CCS_CNTLQ_STOP,
+
+ // CCS STATQ
+ CCS_IN_PROGRESS = MCBIST_CCS_STATQ_IP,
+
+ // ARR0
+ ARR0_DDR_ADDRESS_0_13 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13,
+ ARR0_DDR_ADDRESS_0_13_LEN = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13_LEN,
+ ARR0_DDR_ADDRESS_17 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_17,
+ ARR0_DDR_BANK_GROUP_1 = MCBIST_CCS_INST_ARR0_00_DDR_BANK_GROUP_1,
+ ARR0_DDR_RESETN = MCBIST_CCS_INST_ARR0_00_DDR_RESETN,
+ ARR0_DDR_BANK_0_1 = MCBIST_CCS_INST_ARR0_00_DDR_BANK_0_1,
+ ARR0_DDR_BANK_0_1_LEN = MCBIST_CCS_INST_ARR0_00_DDR_BANK_0_1_LEN,
+ ARR0_DDR_BANK_GROUP_0 = MCBIST_CCS_INST_ARR0_00_DDR_BANK_GROUP_0,
+ ARR0_DDR_ACTN = MCBIST_CCS_INST_ARR0_00_DDR_ACTN,
+ ARR0_DDR_ADDRESS_16 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_16,
+ ARR0_DDR_ADDRESS_15 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_15,
+ ARR0_DDR_ADDRESS_14 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_14,
+ ARR0_DDR_CKE = MCBIST_CCS_INST_ARR0_00_DDR_CKE,
+ ARR0_DDR_CKE_LEN = MCBIST_CCS_INST_ARR0_00_DDR_CKE_LEN,
+ ARR0_DDR_CSN_0_1 = MCBIST_CCS_INST_ARR0_00_DDR_CSN_0_1,
+ ARR0_DDR_CSN_0_1_LEN = MCBIST_CCS_INST_ARR0_00_DDR_CSN_0_1_LEN,
+ ARR0_DDR_CID_0_1 = MCBIST_CCS_INST_ARR0_00_DDR_CID_0_1,
+ ARR0_DDR_CID_0_1_LEN = MCBIST_CCS_INST_ARR0_00_DDR_CID_0_1_LEN,
+ ARR0_DDR_CSN_2_3 = MCBIST_CCS_INST_ARR0_00_DDR_CSN_2_3,
+ ARR0_DDR_CSN_2_3_LEN = MCBIST_CCS_INST_ARR0_00_DDR_CSN_2_3_LEN,
+ ARR0_DDR_CID_2 = MCBIST_CCS_INST_ARR0_00_DDR_CID_2,
+ ARR0_DDR_ODT = MCBIST_CCS_INST_ARR0_00_DDR_ODT,
+ ARR0_DDR_ODT_LEN = MCBIST_CCS_INST_ARR0_00_DDR_ODT_LEN,
+ ARR0_DDR_CAL_TYPE = MCBIST_CCS_INST_ARR0_00_DDR_CAL_TYPE,
+ ARR0_DDR_CAL_TYPE_LEN = MCBIST_CCS_INST_ARR0_00_DDR_CAL_TYPE_LEN,
+ ARR0_DDR_PARITY = MCBIST_CCS_INST_ARR0_00_DDR_PARITY,
+ ARR0_DDR_BANK_2 = MCBIST_CCS_INST_ARR0_00_DDR_BANK_2,
+ ARR0_LOOP_BREAK_MODE = MCBIST_CCS_INST_ARR0_00_LOOP_BREAK_MODE,
+ ARR0_LOOP_BREAK_MODE_LEN = MCBIST_CCS_INST_ARR0_00_LOOP_BREAK_MODE_LEN,
+
+ // ARR1
+ ARR1_IDLES = MCBIST_CCS_INST_ARR1_00_IDLES,
+ ARR1_IDLES_LEN = MCBIST_CCS_INST_ARR1_00_IDLES_LEN,
+ ARR1_REPEAT_CMD_CNT = MCBIST_CCS_INST_ARR1_00_REPEAT_CMD_CNT,
+ ARR1_REPEAT_CMD_CNT_LEN = MCBIST_CCS_INST_ARR1_00_REPEAT_CMD_CNT_LEN,
+ ARR1_READ_OR_WRITE_DATA = MCBIST_CCS_INST_ARR1_00_READ_OR_WRITE_DATA,
+ ARR1_READ_OR_WRITE_DATA_LEN = MCBIST_CCS_INST_ARR1_00_READ_OR_WRITE_DATA_LEN,
+ ARR1_READ_COMPARE_REQUIRED = MCBIST_CCS_INST_ARR1_00_READ_COMPARE_REQUIRED,
+ ARR1_DDR_CAL_RANK = MCBIST_CCS_INST_ARR1_00_DDR_CAL_RANK,
+ ARR1_DDR_CAL_RANK_LEN = MCBIST_CCS_INST_ARR1_00_DDR_CAL_RANK_LEN,
+ ARR1_DDR_CALIBRATION_ENABLE = MCBIST_CCS_INST_ARR1_00_DDR_CALIBRATION_ENABLE,
+ ARR1_END = MCBIST_CCS_INST_ARR1_00_END,
+ ARR1_GOTO_CMD = MCBIST_CCS_INST_ARR1_00_GOTO_CMD,
+ ARR1_GOTO_CMD_LEN = MCBIST_CCS_INST_ARR1_00_GOTO_CMD_LEN,
+
+ };
+};
+
+namespace mss
+{
+namespace ccs
+{
+
+enum
+{
+ // Success is defined as done-bit set, no others.
+ STAT_QUERY_SUCCESS = 0x4000000000000000,
+
+ // Bit positions 3:5
+ STAT_READ_MISCOMPARE = 0x1000000000000000,
+ STAT_UE_SUE = 0x0800000000000000,
+ STAT_CAL_TIMEOUT = 0x0400000000000000,
+
+ // If the fail type isn't one of these, we're hung
+ STAT_HUNG = 0x0ull,
+};
+
+// A ccs instruction is data (array 0) and some control information (array 1)
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+class instruction_t
+{
+ public:
+ fapi2::buffer<uint64_t> arr0;
+ fapi2::buffer<uint64_t> arr1;
+
+ ///
+ /// @brief intstruction_t ctor
+ /// @param[in] the DIMM this instruction is headed for
+ /// @param[in] the rank this instruction is headed for
+ /// @param[in] the initial value for arr0, defaults to 0
+ /// @param[in] the initial value for arr1, defaults to 0
+ ///
+ instruction_t( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target = fapi2::Target<fapi2::TARGET_TYPE_DIMM>(),
+ uint64_t i_rank = 0xFF,
+ const fapi2::buffer<uint64_t> i_arr0 = 0,
+ const fapi2::buffer<uint64_t> i_arr1 = 0):
+ arr0(i_arr0),
+ arr1(i_arr1)
+ {
+
+ static const uint64_t CS_N[mss::MAX_RANK_PER_DIMM] =
+ {
+ // DCS0 L DCS1 H => Rank 0
+ 0b01,
+ // DCS0 H DCS1 L => Rank 1
+ 0b10,
+ };
+
+ // Start be deselcting everything and we'll clear the bits we want.
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_0_1, TT::ARR0_DDR_CSN_0_1_LEN>(0b11);
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_2_3, TT::ARR0_DDR_CSN_2_3_LEN>(0b11);
+
+ // If the rank indicates nothing selected (active low) then we're done.
+ if (i_rank == 0xFF)
+ {
+ return;
+ }
+
+ //
+ // Note: This needs to be able to handle all DIMM, stacked, encoded CS_n, etc. This
+ // ain't gonna cut it. Turn this in to a dispatched funtion like c_str() and rcd_load() BRS
+ //
+
+ // Direct CS mode - just clear the CS_N you're interested in.
+ // Setup the chip select based on which dimm in the slot and the rank
+ if (mss::index(i_target) == 0)
+ {
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_0_1,
+ TT::ARR0_DDR_CSN_0_1_LEN>(CS_N[i_rank]);
+ }
+ else
+ {
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_2_3,
+ TT::ARR0_DDR_CSN_2_3_LEN>(CS_N[i_rank]);
+ }
+
+#ifdef QUAD_ENCODED_CS
+ // Implement the Encoded QuadCS Mode DCS, DC mapping and stuff the resulting
+ // bits in to the proper location for the CCS instruction (perhaps we need
+ // to be a template - p9n CCS is different from Centaur ... make initializing
+ // the instruction a policy of the ccsTraits ... BRS)
+
+ // Lookup table for CS_N and CID indexed by rank for Quad encoded CS modee
+ // First bits 0:1 is DCS1_n:DCS2_n. Second bits 0:1 are CID 0:1 bit 2 is CID 2
+ static const std::pair< uint8_t, uint8_t > CS_CID[mss::MAX_RANK_PER_DIMM] =
+ {
+ // DCS0 L DCS1 H CID L:L => Rank 0
+ { 0b01000000, 0b00000000 },
+ // DCS0 L DCS1 H CID H:H => Rank 1
+ { 0b01000000, 0b11000000 },
+ // DCS0 H DCS1 L CID L:L => Rank 2
+ { 0b10000000, 0b00000000 },
+ // DCS0 H DCS1 L CID H:H => Rank 3
+ { 0b10000000, 0b11000000 },
+ };
+
+ // Setup the chip select based on which dimm in the slot and the rank
+ if (mss::index(i_target) == 0)
+ {
+ arr0.insert<TT::ARR0_DDR_CSN_0_1,
+ TT::ARR0_DDR_CSN_0_1_LEN>(CS_CID[i_rank].first);
+ }
+ else
+ {
+ arr0.insert<TT::ARR0_DDR_CSN_2_3,
+ TT::ARR0_DDR_CSN_2_3_LEN>(CS_CID[i_rank].first);
+ }
+
+ arr0.insert<TT::ARR0_DDR_CID_0_1,
+ TT::ARR0_DDR_CID_0_1_LEN>(CS_CID[i_rank].second);
+ arr0.writeBit<TT::ARR0_DDR_CID_2>(
+ fapi2::buffer<uint8_t>(CS_CID[i_rank].second).getBit<2>());
+#endif
+ }
+};
+
+///
+/// @brief A class representing a series of CCS instructions, and the
+/// CCS engine parameters associated with running the instructions
+/// @tparam fapi2::TargetType T representing the fapi2 target which
+/// contains the CCS engine (e.g., fapi2::TARGET_TYPE_MCBIST)
+template< fapi2::TargetType T >
+class program
+{
+ public:
+ // Setup our poll parameters so the CCS executer can see
+ // whether to use the delays in the instruction stream or not
+ program(): iv_poll(0, 0)
+ {}
+
+ // Vector of instructions
+ std::vector< instruction_t<T> > iv_instructions;
+ poll_parameters iv_poll;
+};
+
+///
+/// @brief Common setup for all MRS/RCD instructions
+/// @param[in,out] fapi2::buffer<uint64_t> representing the ARR0 of the instruction
+/// @return void
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+static void mrs_rcd_helper( fapi2::buffer<uint64_t>& i_arr0 )
+{
+ //
+ // Generic DDR4 MRS setup (RCD is an MRS)
+ //
+ // CKE is high Note: P8 set all 4 of these high - not sure if that's correct. BRS
+ i_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(0b1111);
+
+ // ACT is high
+ i_arr0.setBit<TT::ARR0_DDR_ACTN>();
+
+ // RAS, CAS, WE low
+ i_arr0.clearBit<TT::ARR0_DDR_ADDRESS_16>();
+ i_arr0.clearBit<TT::ARR0_DDR_ADDRESS_15>();
+ i_arr0.clearBit<TT::ARR0_DDR_ADDRESS_14>();
+}
+
+///
+/// @brief Create, initialize an RCD (RCW - JEDEC) CCS command
+/// @tparam T, the fapi2 type of the unit which contains the CCS engine
+/// @param[in] the DIMM this instruction is headed for
+/// @return the RCD CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline instruction_t<T> rcd_command( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target )
+{
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr0;
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr1;
+
+ //
+ // Generic DDR4 MRS setup (RCD is an MRS)
+ //
+ mrs_rcd_helper<fapi2::TARGET_TYPE_MCBIST>(rcd_boilerplate_arr0);
+
+ //
+ // RCD setup
+ //
+ // DDR4: Set BG1 to 0. BG0, BA1:BA0 to 0b111
+ rcd_boilerplate_arr0.clearBit<TT::ARR0_DDR_BANK_GROUP_1>();
+ rcd_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_BANK_0_1, TT::ARR0_DDR_BANK_0_1_LEN>(0b11);
+ rcd_boilerplate_arr0.setBit<TT::ARR0_DDR_BANK_GROUP_0>();
+
+ // RCD always goes to rank 0. All we need to know is which DIMM we are on the port
+ return instruction_t<T>(i_target, 0, rcd_boilerplate_arr0, rcd_boilerplate_arr1);
+}
+
+///
+/// @brief Create, initialize an MRS CCS command
+/// @tparam T, the fapi2 type of the unit which contains the CCS engine
+/// @param[in] the DIMM this instruction is headed for
+/// @param[in] the rank on this dimm
+/// @param[in] the specific MRS
+/// @return the MRS CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline instruction_t<T> mrs_command( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, const uint64_t i_rank,
+ const uint64_t i_mrs )
+{
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr0;
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr1;
+ fapi2::buffer<uint8_t> mrs(i_mrs);
+
+ //
+ // Generic DDR4 MRS setup (RCD is an MRS)
+ //
+ mrs_rcd_helper<fapi2::TARGET_TYPE_MCBIST>(rcd_boilerplate_arr0);
+
+ //
+ // MRS setup
+ //
+ // DDR4: Set BG1 to 0. BG0, BA1:BA0 to i_mrs
+ rcd_boilerplate_arr0.clearBit<TT::ARR0_DDR_BANK_GROUP_1>();
+ mss::swizzle<TT::ARR0_DDR_BANK_0_1, 3, 7>(mrs, rcd_boilerplate_arr0);
+ FAPI_DBG("mrs rcd boiler 0x%llx 0x%llx", uint8_t(mrs), uint64_t(rcd_boilerplate_arr0));
+ return instruction_t<T>(i_target, i_rank, rcd_boilerplate_arr0, rcd_boilerplate_arr1);
+}
+
+///
+/// @brief Create, initialize a JEDEC Device Deselect CCS command
+/// @tparam T, the fapi2 type of the unit containing the CCS engine
+/// @return the Device Deselect CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline instruction_t<T> des_command()
+{
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr0;
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr1;
+
+ // ACT is high. It's a no-care in the spec but it seems to raise questions when
+ // people look at the trace, so lets set it high.
+ rcd_boilerplate_arr0.setBit<TT::ARR0_DDR_ACTN>();
+
+ // CKE is high Note: P8 set all 4 of these high - not sure if that's correct. BRS
+ rcd_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(0b1111);
+
+ // ACT is high no-care
+ // RAS, CAS, WE no-care
+
+ // Device Deslect wants CS_n always high (select nothing using rank 0xFF)
+ return instruction_t<T>(fapi2::Target<fapi2::TARGET_TYPE_DIMM>(), 0xFF, rcd_boilerplate_arr0, rcd_boilerplate_arr1);
+}
+
+///
+/// @brief Create, initialize an instruction which indicates an initial cal
+/// @param[in] the rank-pair (rank) to cal
+/// @return the initial cal instruction
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline instruction_t<T> initial_cal_command(const uint64_t i_rp)
+{
+ // An initial cal arr0 looks just like a DES, but we set the initial cal bits
+ instruction_t<T> l_inst = des_command<T>();
+
+ // ACT is low - per Centaur spec (Shelton to confirm for Nimbus) BRS
+ l_inst.arr0.template clearBit<TT::ARR0_DDR_ACTN>();
+
+ l_inst.arr0.template insertFromRight<TT::ARR0_DDR_CAL_TYPE, TT::ARR0_DDR_CAL_TYPE_LEN>(0b1100);
+ l_inst.arr1.template setBit<TT::ARR1_DDR_CALIBRATION_ENABLE>();
+
+#ifdef USE_LOTS_OF_IDLES
+ // Idles is 0xFFFF - per Centaur spec (Shelton to confirm for Nimbus) BRS
+ l_inst.arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>(0xFFFF);
+#else
+ l_inst.arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>(0x0);
+#endif
+
+ // The rank we're calibrating is enacoded - it's an int. So rank 3 is 0011 not 0001
+ l_inst.arr1.template insertFromRight<TT::ARR1_DDR_CAL_RANK, TT::ARR1_DDR_CAL_RANK_LEN>(i_rp);
+
+ return l_inst;
+}
+
+//
+// These functions are a little sugar to keep callers from doing the traits-dance to get the
+// appropriate bit field
+//
+
+///
+/// @brief Select the port(s) to be used by the CCS
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the buffer representing the ports
+/// @return void
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline fapi2::ReturnCode select_ports( const fapi2::Target<T>& i_target, uint64_t i_ports)
+{
+ fapi2::buffer<uint64_t> l_data;
+ fapi2::buffer<uint64_t> l_ports;
+
+ // Not handling multiple ports here, can't do that for CCS. BRS
+ FAPI_TRY( l_ports.setBit(i_ports) );
+
+ FAPI_TRY( fapi2::getScom(i_target, TT::MCB_CNTL_REG, l_data) );
+ l_data.insert<TT::MCB_CNTL_PORT_SEL, TT::MCB_CNTL_PORT_SEL_LEN>(l_ports);
+ FAPI_TRY( fapi2::putScom(i_target, TT::MCB_CNTL_REG, l_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief User sets to a '1'b to tell the Hdw to stop CCS whenever failure occurs. When a
+/// '0'b, Hdw will continue CCS even if a failure occurs.
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the buffer representing the mode register
+/// @param[in] i_value, true iff stop whenever failure occurs.
+/// @return void
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline void stop_on_err( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& i_buffer, bool i_value)
+{
+ i_buffer.writeBit<TT::STOP_ON_ERR>(i_value);
+}
+
+///
+/// @brief Disable ECC checking on the CCS arrays
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the buffer representing the mode register
+/// @return void
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline void disable_ecc( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& i_buffer)
+{
+ i_buffer.setBit<TT::DISABLE_ECC_ARRAY_CHK>();
+ i_buffer.setBit<TT::DISABLE_ECC_ARRAY_CORRECTION>();
+}
+
+///
+/// @brief User sets to a '1'b to force the Hdw to ignore any array ue or sue errors
+/// during CCS command fetching.
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the buffer representing the mode register
+/// @param[in] i_value, true iff ignore any array ue or sue errors.
+/// @return void
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline void ue_disable( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& i_buffer, bool i_value)
+{
+ i_buffer.writeBit<TT::UE_DISABLE>(i_value);
+}
+
+///
+/// @brief DDr calibration counter
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the buffer representing the mode register
+/// @param[in] i_count, the count to wait for DDR cal to complete.
+/// @param[in] i_mult, the DDR calibration time multiplaction factor
+/// @return void
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline void cal_count( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& i_buffer,
+ const uint64_t i_count, const uint64_t i_mult)
+{
+ i_buffer.insertFromRight<TT::DDR_CAL_TIMEOUT_CNT, TT::DDR_CAL_TIMEOUT_CNT_LEN>(i_count);
+ i_buffer.insertFromRight<TT::DDR_CAL_TIMEOUT_CNT_MULT, TT::DDR_CAL_TIMEOUT_CNT_MULT_LEN>(i_mult);
+}
+
+///
+/// @brief Copy CKE signals to CKE Spare on both ports NOTE: DOESN'T APPLY FOR NIMBUS. NO
+/// SPARE CHIPS TO COPY TO. 0 - Spare CKEs not copied with values from CKE(0:1) and
+/// CKE(4:5) 1 - Port A CKE(0:1) copied to Port A CKE(2:3), Port A CKE(4:5) copied
+/// to Port A CKE(6:7), Port B CKE(0:1) copied to Port B CKE(2:3) and Port B CKE(4:5)
+/// copied to Port B CKE(6:7)
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the buffer representing the mode register
+/// @param[in] bool, true iff Copy CKE signals to CKE Spare on both ports
+/// @note no-op for p9n
+/// @return void
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+void copy_cke_to_spare_cke( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& i_buffer, bool i_value);
+
+///
+/// @brief Read the modeq register appropriate for this target
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the buffer representing the mode register
+/// @erturn FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline fapi2::ReturnCode read_mode( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& i_buffer)
+{
+ FAPI_DBG("read mode 0x%llx", TT::MODEQ_REG);
+ return fapi2::getScom(i_target, TT::MODEQ_REG, i_buffer);
+}
+
+///
+/// @brief Write the modeq register appropriate for this target
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the buffer representing the mode register
+/// @erturn FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+inline fapi2::ReturnCode write_mode( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_buffer)
+{
+ return fapi2::putScom(i_target, TT::MODEQ_REG, i_buffer);
+}
+
+///
+/// @brief Execute a set of CCS instructions - multiple ports
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the vector of instructions
+/// @param[in] the vector of ports
+/// @erturn FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, fapi2::TargetType P, typename TT = ccsTraits<T> >
+fapi2::ReturnCode execute( const fapi2::Target<T>& i_target,
+ ccs::program<T>& i_program,
+ const std::vector< fapi2::Target<P> >& i_ports );
+
+///
+/// @brief Execute a set of CCS instructions - single port
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the vector of instructions
+/// @param[in] the port
+/// @erturn FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, fapi2::TargetType P, typename TT = ccsTraits<T> >
+fapi2::ReturnCode execute( const fapi2::Target<T>& i_target,
+ ccs::program<T>& i_program,
+ const fapi2::Target<P>& i_port )
+{
+ // Mmm. Might want to find a better way to do this - seems expensive. BRS
+ std::vector< fapi2::Target<P> > l_ports{ i_port };
+ return execute(i_target, i_program, l_ports);
+}
+
+///
+/// @brief Execute a CCS array already loaded in to the engine
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the ccsTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the MCBIST ccs program - to get the polling parameters
+/// @erturn FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+fapi2::ReturnCode execute_inst_array(const fapi2::Target<T>& i_target, ccs::program<T>& i_program);
+///
+/// @brief Start or stop the CCS engine
+/// @param[in] i_target The MCBIST containing the CCS engine
+/// @param[in] i_start_stop bool MSS_CCS_START for starting,
+/// MSS_CCS_STOP otherwise
+/// @return FAPI2_RC_SUCCESS iff success
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+fapi2::ReturnCode start_stop( const fapi2::Target<T>& i_target, bool i_start_stop );
+
+///
+/// @brief Query the status of the CCS engine
+/// @param[in] i_target The MCBIST containing the CCS engine
+/// @param[out] The query result, first being the result, second the type
+/// @return FAPI2_RC_SUCCESS iff success
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<T> >
+fapi2::ReturnCode status_query( const fapi2::Target<T>& i_target, std::pair<uint64_t, uint64_t>& io_status );
+
+} // ends namespace ccs
+}
+
+#endif
OpenPOWER on IntegriCloud