summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2016-11-24 11:01:12 -0600
committerChristian R. Geddes <crgeddes@us.ibm.com>2016-12-06 10:34:28 -0500
commitff34b02d569f9c45bcb5a3832fdcd7f12ef07519 (patch)
treeae1a5e5daa1d0e54c3591a61166ac9a34a921d56
parent01eb02a8ba7730945d5eb785ef7cf1ff2b59def9 (diff)
downloadtalos-hostboot-ff34b02d569f9c45bcb5a3832fdcd7f12ef07519.tar.gz
talos-hostboot-ff34b02d569f9c45bcb5a3832fdcd7f12ef07519.zip
Add a common MRS engine to set up CCS instructions and UTs.
Cascade MRS engine to common copy-pasted code to mrs_load, latch_wr_vref and mrs_one_shot. Change-Id: Iabd7848816a43d012bed4f403504985488fe332c Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33010 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: Brian R. Silver <bsilver@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33026 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C86
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H14
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C55
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H456
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H1
5 files changed, 390 insertions, 222 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C
index 59e21d3ca..a97a9d073 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C
@@ -69,43 +69,19 @@ fapi2::ReturnCode add_latch_wr_vref_commands( const fapi2::Target<fapi2::TARGET_
// Adds both VREFDQ train enables
// Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
- ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_a_side;
- ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_b_side;
-
auto l_mr_override = i_mrs06;
- enable_vref_train_enable(l_mr_override);
-
- FAPI_TRY(setup_ab_side_vref_train_enable(
- i_target,
- l_mr_override,
- i_rank,
- l_inst_a_side,
- l_inst_b_side)
- );
-
// Add both to the CCS program - JEDEC step 1
- io_inst.push_back(l_inst_a_side);
- io_inst.push_back(l_inst_b_side);
+ enable_vref_train_enable(l_mr_override);
+ FAPI_TRY( mrs_engine(i_target, l_mr_override, i_rank, mss::tvrefdqe(i_target), io_inst) );
// Add both to the CCS program - JEDEC step 2
- io_inst.push_back(l_inst_a_side);
- io_inst.push_back(l_inst_b_side);
-
- disable_vref_train_enable(l_mr_override);
+ FAPI_TRY( mrs_engine(i_target, l_mr_override, i_rank, mss::tvrefdqe(i_target), io_inst) );
// Hits VREFDQ train disable - putting the DRAM's back in mainline mode
- FAPI_TRY(setup_ab_side_vref_train_enable(
- i_target,
- l_mr_override,
- i_rank,
- l_inst_a_side,
- l_inst_b_side)
- );
-
// Add both to the CCS program - JEDEC step 3
- io_inst.push_back(l_inst_a_side);
- io_inst.push_back(l_inst_b_side);
+ disable_vref_train_enable(l_mr_override);
+ FAPI_TRY( mrs_engine(i_target, l_mr_override, i_rank, mss::tvrefdqe(i_target), io_inst) );
fapi_try_exit:
return fapi2::current_err;
@@ -216,57 +192,5 @@ fapi_try_exit:
return fapi2::current_err;
}
-///
-/// @brief helper function to setup a/b side MR06 commands for the latching function based upon TRAIN_ENABLE
-/// @param[in] i_mrs06, base MRS 06 allows the user to setup custom values and pass it in
-/// @param[in] i_rank, rank on which to latch MRS 06
-/// @param[out] o_a_side, a-side MR06 command
-/// @param[out] o_b_side, b-side MR06 command
-/// @return FAPI2_RC_SUCCESS if and only if ok
-///
-fapi2::ReturnCode setup_ab_side_vref_train_enable(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const mrs06_data& i_mrs06,
- const uint64_t& i_rank,
- ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_a_side,
- ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_b_side)
-{
- // commands to be latched are MR06
- constexpr uint8_t WR_VREF_MRS = 6;
-
- // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
- o_a_side = ccs::mrs_command<fapi2::TARGET_TYPE_MCBIST>(i_target, i_rank, WR_VREF_MRS);
-
- // Sets up variables
- const auto l_delay_enter = mss::tvrefdqe(i_target);
-
- // Thou shalt send 2 MRS, one for the a-side and the other inverted for the b-side.
- // If we're on an odd-rank then we need to mirror
- // So configure the A-side, mirror if necessary and invert for the B-side
- // Gets the actual MR data to pass into CCS
- FAPI_TRY( mrs06(i_target, i_mrs06, o_a_side, i_rank) );
-
- FAPI_TRY( mss::address_mirror(i_target, i_rank, o_a_side) );
- o_b_side = mss::address_invert(o_a_side);
-
- // Not sure if we can get tricky here and only delay after the b-side MR. The question is whether the delay
- // is needed/assumed by the register or is purely a DRAM mandated delay. We know we can't go wrong having
- // both delays but if we can ever confirm that we only need one we can fix this. BRS
- o_a_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
- MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(l_delay_enter);
- o_b_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
- MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(l_delay_enter);
-
- // Dump out the 'decoded' MRS and trace the CCS instructions.
- FAPI_TRY( mrs06_decode(o_a_side, i_rank) );
-
- FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d a-side", WR_VREF_MRS, l_delay_enter,
- o_a_side.arr0, o_a_side.arr1, mss::c_str(i_target), i_rank);
- FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d b-side", WR_VREF_MRS, l_delay_enter,
- o_b_side.arr0, o_b_side.arr1, mss::c_str(i_target), i_rank);
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
} // close namespace DDR4
} // close namespace mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H
index b6b521c04..7853b5b12 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H
@@ -108,20 +108,6 @@ inline void disable_vref_train_enable(mrs06_data& io_mrs06)
}
///
-/// @brief helper function to setup a/b side MR06 commands for the latching function based upon TRAIN_ENABLE
-/// @param[in] i_mrs06, base MRS 06 allows the user to setup custom values and pass it in
-/// @param[in] i_rank, rank on which to latch MRS 06
-/// @param[out] o_a_side, a-side MR06 command
-/// @param[out] o_b_side, b-side MR06 command
-/// @return FAPI2_RC_SUCCESS if and only if ok
-///
-fapi2::ReturnCode setup_ab_side_vref_train_enable(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const mrs06_data& i_mrs06,
- const uint64_t& i_rank,
- ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_a_side,
- ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_b_side);
-
-///
/// @brief Add latching commands for WR VREF to the instruction array by a given rank
/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_MCA>
/// @param[in] i_rank, rank on which to latch MRS 06 - hits all ranks in the rank pair
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C
index 2017cc1d5..67349352a 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C
@@ -48,13 +48,33 @@ using fapi2::FAPI2_RC_SUCCESS;
namespace mss
{
+///
+/// @brief Sets up MRS CCS instructions
+/// @param[in] i_target a fapi2::Target DIMM
+/// @param[in] i_data the completed MRS data to send
+/// @param[in] i_rank the rank to send to
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< >
+fapi2::ReturnCode mrs_engine( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const mrs_data<fapi2::TARGET_TYPE_MCBIST>& i_data,
+ const uint64_t i_rank,
+ std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst )
+{
+ FAPI_TRY( mrs_engine(i_target, i_data, i_rank, i_data.iv_delay, io_inst) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
namespace ddr4
{
///
/// @brief Perform the mrs_load DDR4 operations - TARGET_TYPE_DIMM specialization
/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM>
-/// @param[in] io_inst a vector of CCS instructions we should add to
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode mrs_load( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
@@ -89,38 +109,7 @@ fapi2::ReturnCode mrs_load( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
{
for (const auto& r : l_ranks)
{
- // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
- ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_a_side =
- ccs::mrs_command<TARGET_TYPE_MCBIST>(i_target, r, d.iv_mrs);
- ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_b_side;
-
- // Thou shalt send 2 MRS, one for the a-side and the other inverted for the b-side.
- // If we're on an odd-rank then we need to mirror
- // So configure the A-side, mirror if necessary and invert for the B-side
- FAPI_TRY( d.iv_func(i_target, l_inst_a_side, r) );
-
- FAPI_TRY( mss::address_mirror(i_target, r, l_inst_a_side) );
- l_inst_b_side = mss::address_invert(l_inst_a_side);
-
- // Not sure if we can get tricky here and only delay after the b-side MR. The question is whether the delay
- // is needed/assumed by the register or is purely a DRAM mandated delay. We know we can't go wrong having
- // both delays but if we can ever confirm that we only need one we can fix this. BRS
- l_inst_a_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
- MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(d.iv_delay);
- l_inst_b_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
- MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(d.iv_delay);
-
- // Dump out the 'decoded' MRS and trace the CCS instructions.
- FAPI_TRY( d.iv_dumper(l_inst_a_side, r) );
-
- FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d a-side", uint8_t(d.iv_mrs), d.iv_delay,
- l_inst_a_side.arr0, l_inst_a_side.arr1, mss::c_str(i_target), r);
- FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d b-side", uint8_t(d.iv_mrs), d.iv_delay,
- l_inst_b_side.arr0, l_inst_b_side.arr1, mss::c_str(i_target), r);
-
- // Add both to the CCS program
- io_inst.push_back(l_inst_a_side);
- io_inst.push_back(l_inst_b_side);
+ FAPI_TRY( mrs_engine(i_target, d, r, io_inst) );
}
}
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H
index 219b6f81a..d2620e084 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H
@@ -40,10 +40,286 @@
#include <fapi2.H>
#include <lib/utils/c_str.H>
#include <lib/dimm/mrs_load.H>
+#include <lib/eff_config/timing.H>
namespace mss
{
+// Map bits in the ARR0 register(s) to MRS address bits. Should be traits related to ARR0. BRS
+enum address_bits
+{
+ A0 = 0,
+ A1 = 1,
+ A2 = 2,
+ A3 = 3,
+ A4 = 4,
+ A5 = 5,
+ A6 = 6,
+ A7 = 7,
+ A8 = 8,
+ A9 = 9,
+ A10 = 10,
+ A11 = 11,
+ A12 = 12,
+ A13 = 13,
+ A14 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_14,
+ A15 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_15,
+ A16 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_16,
+ A17 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_17,
+
+ // Only kind of address bits ... <shrug>
+ BA0 = 17,
+ BA1 = 18,
+ BG0 = 19,
+ BG1 = 15,
+};
+
+///
+/// @brief Mirror (front to back) the ADR bits of a CCS instruction - implementation
+/// @tparam T typename of the ccs::instruction_t
+/// @param[in, out] io_inst reference to a CCS instruction to be mirrored
+/// @return FAPI2_RC_SUCESS iff ok
+/// @note written this way so this is easier to test
+///
+template<fapi2::TargetType T>
+void address_mirror_impl(ccs::instruction_t<T>& io_inst)
+{
+ // Nothing fancy here, just mirror the bits we're told to mirror in Table 14 — Address Mirroring and Inversion
+ mss::template swap<A3, A4>(io_inst.arr0);
+ mss::template swap<A5, A6>(io_inst.arr0);
+ mss::template swap<A7, A8>(io_inst.arr0);
+ mss::template swap<A11, A13>(io_inst.arr0);
+ mss::template swap<BA0, BA1>(io_inst.arr0);
+ mss::template swap<BG0, BG1>(io_inst.arr0);
+}
+
+///
+/// @brief Mirror (front to back) the ADR bits of a CCS instruction
+/// @tparam T typename of the ccs::instruction_t
+/// @param[in] i_target target to use to get mirroring attribute
+/// @param[in] i_rank the rank in question
+/// @param[in, out] io_inst reference to a CCS instruction to be mirrored
+/// @return FAPI2_RC_SUCESS iff ok
+/// @note assumes the input is from an even number rank
+///
+template<fapi2::TargetType T>
+fapi2::ReturnCode address_mirror(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t i_rank,
+ ccs::instruction_t<T>& io_inst)
+{
+ // We only mirror if the mirroring attribute is set.
+ uint8_t l_mirror = 0;
+ FAPI_TRY( eff_dimm_rcd_mirror_mode(i_target, l_mirror),
+ "Failed to invoke rcd_mirror_mode accesor on %s", mss::c_str(i_target) );
+
+ // We only mirror odd ranks.
+ if ((l_mirror == fapi2::ENUM_ATTR_EFF_DIMM_RCD_MIRROR_MODE_ON) && (i_rank & 0x1))
+ {
+ address_mirror_impl(io_inst);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Invert (side to side) the ADR bits of a CCS instruction
+/// @param[in] i_inst const reference to a CCS instruction.
+/// @return[out] ccs instruction with the ADR bits inverted (side-to-side)
+///
+template<fapi2::TargetType T>
+ccs::instruction_t<T> address_invert(const ccs::instruction_t<T>& i_inst)
+{
+ // Copy the input as the output doesn't all change.
+ ccs::instruction_t<T> i_out(i_inst);
+
+ // Nothing fancy here, just negate the bits we're told to negate in Table 14 — Address Mirroring and Inversion
+ mss::template negate<A3>(i_out.arr0);
+ mss::template negate<A4>(i_out.arr0);
+ mss::template negate<A5>(i_out.arr0);
+ mss::template negate<A6>(i_out.arr0);
+ mss::template negate<A7>(i_out.arr0);
+ mss::template negate<A8>(i_out.arr0);
+ mss::template negate<A9>(i_out.arr0);
+
+ mss::template negate<A11>(i_out.arr0);
+ mss::template negate<A13>(i_out.arr0);
+ mss::template negate<A17>(i_out.arr0);
+
+ mss::template negate<BA0>(i_out.arr0);
+ mss::template negate<BA1>(i_out.arr0);
+ mss::template negate<BG0>(i_out.arr0);
+ mss::template negate<BG1>(i_out.arr0);
+
+ return i_out;
+}
+
+///
+/// @brief Helper function to make a CCS instruction for an MRS
+/// @tparam T TargetType of the CCS instruction
+/// @tparam D the mrs data structure to send out
+/// @param[in] i_target a fapi2::Target DIMM
+/// @param[in] i_data the completed MRS data to send
+/// @param[in] i_rank the rank to send to
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< fapi2::TargetType T, typename D >
+static inline fapi2::ReturnCode make_ccs_helper( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const D& i_data,
+ const uint64_t i_rank,
+ ccs::instruction_t<T>& io_inst )
+{
+ FAPI_TRY( D::make_ccs_instruction(i_target, i_data, io_inst, i_rank),
+ "Failed making a CCS instruction for templated MRS data. MR%d rank %d on %s",
+ i_data.iv_mrs, i_rank, mss::c_str(i_target) );
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to make a CCS instruction for an MRS
+/// @param[in] i_target a fapi2::Target DIMM
+/// @param[in] i_data the completed MRS data to send
+/// @param[in] i_rank the rank to send to
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< >
+fapi2::ReturnCode make_ccs_helper( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const mrs_data<fapi2::TARGET_TYPE_MCBIST>& i_data,
+ const uint64_t i_rank,
+ ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst )
+{
+ FAPI_TRY( i_data.iv_func(i_target, io_inst, i_rank),
+ "Failed making a CCS instruction for mrs_data<TARGET_TYPE_MCBIST> specialization. MR%d rank %d on %s",
+ i_data.iv_mrs, i_rank, mss::c_str(i_target) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to decode MRS and trace CCS instructions
+/// @tparam T TargetType of the CCS instruction
+/// @tparam D the mrs data structure to send out
+/// @param[in] i_data the completed MRS data to send
+/// @param[in] i_rank the rank to send to
+/// @param[in] i_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< fapi2::TargetType T, typename D >
+static inline fapi2::ReturnCode decode_helper(const D& i_data,
+ const uint64_t i_rank,
+ const ccs::instruction_t<T>& i_inst )
+{
+ // Dump out the 'decoded' MRS and trace the CCS instructions.
+ FAPI_TRY( D::decode(i_inst, i_rank),
+ "Failed dumping information for MR%d rank%d",
+ i_data.iv_mrs, i_rank );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to decode MRS and trace CCS instructions
+/// @param[in] i_data the completed MRS data to send
+/// @param[in] i_rank the rank to send to
+/// @param[in] i_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< >
+inline fapi2::ReturnCode decode_helper(const mrs_data<fapi2::TARGET_TYPE_MCBIST>& i_data,
+ const uint64_t i_rank,
+ const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst )
+{
+ // Dump out the 'decoded' MRS and trace the CCS instructions.
+ FAPI_TRY( i_data.iv_dumper(i_inst, i_rank),
+ "Failed dumping information for MR%d rank%d",
+ i_data.iv_mrs, i_rank );
+
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Sets up MRS CCS instructions
+/// @tparam T TargetType of the CCS instruction
+/// @tparam D the mrs data structure to send out
+/// @param[in] i_target a fapi2::Target DIMM
+/// @param[in] i_data the completed MRS data to send
+/// @param[in] i_rank the rank to send to
+/// @param[in] i_delay_in_cycles the delay, in cycles
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< fapi2::TargetType T, typename D >
+fapi2::ReturnCode mrs_engine( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const D& i_data,
+ const uint64_t i_rank,
+ const uint64_t i_delay_in_cycles,
+ std::vector< ccs::instruction_t<T> >& io_inst )
+{
+ ccs::instruction_t<T> l_inst_a_side = ccs::mrs_command<T>(i_target, i_rank, i_data.iv_mrs);
+ ccs::instruction_t<T> l_inst_b_side;
+
+ // Thou shalt send 2 MRS, one for the a-side and the other inverted for the b-side.
+ // If we're on an odd-rank then we need to mirror
+ // So configure the A-side, mirror if necessary and invert for the B-side
+ FAPI_TRY( make_ccs_helper(i_target, i_data, i_rank, l_inst_a_side),
+ "Failed to make CCS instruction for MR%d on %s",
+ i_data.iv_mrs, mss::c_str(i_target) );
+
+ FAPI_TRY( mss::address_mirror(i_target, i_rank, l_inst_a_side),
+ "Failed mirroring MR%d rank %d on %s",
+ i_data.iv_mrs, i_rank, mss::c_str(i_target) );
+
+ l_inst_b_side = mss::address_invert(l_inst_a_side);
+
+ // Not sure if we can get tricky here and only delay after the b-side MR. The question is whether the delay
+ // is needed/assumed by the register or is purely a DRAM mandated delay. We know we can't go wrong having
+ // both delays but if we can ever confirm that we only need one we can fix this. BRS
+ l_inst_a_side.arr1.template insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
+ MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(i_delay_in_cycles);
+ l_inst_b_side.arr1.template insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
+ MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(i_delay_in_cycles);
+
+ // Dump out the 'decoded' MRS and trace the CCS instructions.
+ FAPI_TRY(decode_helper(i_data, i_rank, l_inst_a_side),
+ "Failed to decode information for MR%d on %s",
+ i_data.iv_mrs, mss::c_str(i_target) );
+
+ FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d a-side", uint8_t(i_data.iv_mrs), i_delay_in_cycles,
+ l_inst_a_side.arr0, l_inst_a_side.arr1, mss::c_str(i_target), i_rank);
+ FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d b-side", uint8_t(i_data.iv_mrs), i_delay_in_cycles,
+ l_inst_b_side.arr0, l_inst_b_side.arr1, mss::c_str(i_target), i_rank);
+
+ // Add both to the CCS program
+ io_inst.push_back(l_inst_a_side);
+ io_inst.push_back(l_inst_b_side);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Sets up MRS CCS instructions
+/// @tparam T TargetType of the CCS instruction
+/// @tparam D the mrs data structure to send out
+/// @param[in] i_target a fapi2::Target DIMM
+/// @param[in] i_data the completed MRS data to send
+/// @param[in] i_rank the rank to send to
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< fapi2::TargetType T, typename D >
+fapi2::ReturnCode mrs_engine( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const D& i_data,
+ const uint64_t i_rank,
+ std::vector< ccs::instruction_t<T> >& io_inst );
+
namespace ddr4
{
@@ -483,7 +759,7 @@ fapi2::ReturnCode mrs06_decode(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIS
struct mrs00_data
{
// Needed as we need to know what MR for the CCS instruction created by the lab tooling
- static constexpr uint64_t iv_number = 0;
+ static constexpr uint64_t iv_mrs = 0;
// Helper function needed by the lab tooling to find our instruction maker and our dumper
// Kind of inverted; normally you'd implement this as a method of this class. But that
@@ -518,7 +794,7 @@ struct mrs00_data
struct mrs01_data
{
// Needed as we need to know what MR for the CCS instruction created by the lab tooling
- static constexpr uint64_t iv_number = 1;
+ static constexpr uint64_t iv_mrs = 1;
// Helper function needed by the lab tooling to find our instruction maker and our dumper
static fapi2::ReturnCode (*make_ccs_instruction)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
@@ -551,7 +827,7 @@ struct mrs01_data
struct mrs02_data
{
// Needed as we need to know what MR for the CCS instruction created by the lab tooling
- static constexpr uint64_t iv_number = 2;
+ static constexpr uint64_t iv_mrs = 2;
// Helper function needed by the lab tooling to find our instruction maker and our dumper
static fapi2::ReturnCode (*make_ccs_instruction)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
@@ -563,7 +839,7 @@ struct mrs02_data
const uint64_t i_rank);
///
- /// @brief mrs03_data ctor
+ /// @brief mrs02_data ctor
/// @param[in] a fapi2::TARGET_TYPE_DIMM target
/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
@@ -582,7 +858,7 @@ struct mrs02_data
struct mrs03_data
{
// Needed as we need to know what MR for the CCS instruction created by the lab tooling
- static constexpr uint64_t iv_number = 3;
+ static constexpr uint64_t iv_mrs = 3;
// Helper function needed by the lab tooling to find our instruction maker and our dumper
static fapi2::ReturnCode (*make_ccs_instruction)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
@@ -616,7 +892,7 @@ struct mrs03_data
struct mrs04_data
{
// Needed as we need to know what MR for the CCS instruction created by the lab tooling
- static constexpr uint64_t iv_number = 4;
+ static constexpr uint64_t iv_mrs = 4;
// Helper function needed by the lab tooling to find our instruction maker and our dumper
static fapi2::ReturnCode (*make_ccs_instruction)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
@@ -652,7 +928,7 @@ struct mrs04_data
struct mrs05_data
{
// Needed as we need to know what MR for the CCS instruction created by the lab tooling
- static constexpr uint64_t iv_number = 5;
+ static constexpr uint64_t iv_mrs = 5;
// Helper function needed by the lab tooling to find our instruction maker and our dumper
static fapi2::ReturnCode (*make_ccs_instruction)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
@@ -687,7 +963,7 @@ struct mrs05_data
struct mrs06_data
{
// Needed as we need to know what MR for the CCS instruction created by the lab tooling
- static constexpr uint64_t iv_number = 6;
+ static constexpr uint64_t iv_mrs = 6;
// Helper function needed by the lab tooling to find our instruction maker and our dumper
static fapi2::ReturnCode (*make_ccs_instruction)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
@@ -722,114 +998,108 @@ struct mrs06_data
fapi2::ReturnCode mrs_load( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst);
-} // ns ddr4
-
-// Map bits in the ARR0 register(s) to MRS address bits. Should be traits related to ARR0. BRS
-enum address_bits
-{
- A0 = 0,
- A1 = 1,
- A2 = 2,
- A3 = 3,
- A4 = 4,
- A5 = 5,
- A6 = 6,
- A7 = 7,
- A8 = 8,
- A9 = 9,
- A10 = 10,
- A11 = 11,
- A12 = 12,
- A13 = 13,
- A14 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_14,
- A15 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_15,
- A16 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_16,
- A17 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_17,
-
- // Only kind of address bits ... <shrug>
- BA0 = 17,
- BA1 = 18,
- BG0 = 19,
- BG1 = 15,
-};
-
///
-/// @brief Mirror (front to back) the ADR bits of a CCS instruction - implementation
-/// @tparam T typename of the ccs::instruction_t
-/// @param[in, out] io_inst reference to a CCS instruction to be mirrored
-/// @return FAPI2_RC_SUCESS iff ok
-/// @note written this way so this is easier to test
+/// @brief Makes CCS instruction to set MPR Mode
+/// @param[in] i_target a DIMM target
+/// @param[in] i_mode setting for MPR mode
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
///
-template<fapi2::TargetType T>
-void address_mirror_impl(ccs::instruction_t<T>& io_inst)
+template< fapi2::TargetType T >
+fapi2::ReturnCode set_dram_mpr_mode(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t i_rank,
+ const uint8_t i_mode,
+ std::vector< ccs::instruction_t<T> >& io_inst )
{
- // Nothing fancy here, just mirror the bits we're told to mirror in Table 14 — Address Mirroring and Inversion
- mss::template swap<A3, A4>(io_inst.arr0);
- mss::template swap<A5, A6>(io_inst.arr0);
- mss::template swap<A7, A8>(io_inst.arr0);
- mss::template swap<A11, A13>(io_inst.arr0);
- mss::template swap<BA0, BA1>(io_inst.arr0);
- mss::template swap<BG0, BG1>(io_inst.arr0);
+ constexpr uint64_t MAX_MPR_MODE = 0b1;
+ fapi2::ReturnCode l_rc;
+
+ mrs03_data l_data(i_target, l_rc);
+ FAPI_TRY( l_rc, "Unable to instantiate mrs03_data for %s", i_target );
+
+ if(i_mode > MAX_MPR_MODE)
+ {
+ FAPI_ERR("Invalid MPR Mode recieved: %d. Max encoding allowed: %d.", i_mode, MAX_MPR_MODE);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ }
+
+ l_data.iv_mpr_mode = i_mode;
+ FAPI_TRY( mrs_engine(i_target, l_data, i_rank, mss::tmrd(), io_inst),
+ "Failed to send MRS03 on %s, rank: %d, delay (in cycles): %d",
+ i_target, i_rank, mss::tmrd());
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Mirror (front to back) the ADR bits of a CCS instruction
-/// @tparam T typename of the ccs::instruction_t
-/// @param[in] i_target target to use to get mirroring attribute
-/// @param[in] i_rank the rank in question
-/// @param[in, out] io_inst reference to a CCS instruction to be mirrored
-/// @return FAPI2_RC_SUCESS iff ok
-/// @note assumes the input is from an even number rank
+/// @brief Makes CCS instruction to set MPR Read
+/// @param[in] i_target a DIMM target
+/// @param[in] i_format setting for MPR read format
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
///
-template<fapi2::TargetType T>
-fapi2::ReturnCode address_mirror(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const uint64_t i_rank, ccs::instruction_t<T>& io_inst)
+template< fapi2::TargetType T >
+fapi2::ReturnCode set_dram_mpr_read(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t i_rank,
+ const uint8_t i_format,
+ std::vector< ccs::instruction_t<T> >& io_inst )
{
- // We only mirror if the mirroring attribute is set.
- uint8_t l_mirror = 0;
- FAPI_TRY( eff_dimm_rcd_mirror_mode(i_target, l_mirror) );
+ constexpr uint64_t MAX_READ_FORMAT = 0b10;
- // We only mirror odd ranks.
- if ((l_mirror == fapi2::ENUM_ATTR_EFF_DIMM_RCD_MIRROR_MODE_ON) && (i_rank & 0x1))
+ fapi2::ReturnCode l_rc;
+ mrs03_data l_data(i_target, l_rc);
+ FAPI_TRY( l_rc, "Unable to instantiate mrs03_data for %s", i_target );
+
+ if(i_format > MAX_READ_FORMAT)
{
- address_mirror_impl(io_inst);
+ FAPI_ERR("Invalid MPR Read Format recieved: %d. Max encoding allowed: %d.", i_format, MAX_READ_FORMAT);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
}
+ l_data.iv_read_format = i_format;
+ FAPI_TRY( mrs_engine(i_target, l_data, i_rank, mss::tmrd(), io_inst),
+ "Failed to send MRS03 on %s, rank: %d, delay (in cycles): %d",
+ i_target, i_rank, mss::tmrd());
+
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Invert (side to side) the ADR bits of a CCS instruction
-/// @param[in] i_inst const reference to a CCS instruction.
-/// @return[out] ccs instruction with the ADR bits inverted (side-to-side)
+/// @brief Makes CCS instruction to set MPR Read
+/// @param[in] i_target a DIMM target
+/// @param[in] i_page setting for MPR read format
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
///
-template<fapi2::TargetType T>
-ccs::instruction_t<T> address_invert(const ccs::instruction_t<T>& i_inst)
+template< fapi2::TargetType T >
+fapi2::ReturnCode set_dram_mpr_page(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t i_rank,
+ const uint8_t i_page,
+ std::vector< ccs::instruction_t<T> >& io_inst )
{
- // Copy the input as the output doesn't all change.
- ccs::instruction_t<T> i_out(i_inst);
+ constexpr uint64_t MAX_PAGE = 0b11;
- // Nothing fancy here, just negate the bits we're told to negate in Table 14 — Address Mirroring and Inversion
- mss::template negate<A3>(i_out.arr0);
- mss::template negate<A4>(i_out.arr0);
- mss::template negate<A5>(i_out.arr0);
- mss::template negate<A6>(i_out.arr0);
- mss::template negate<A7>(i_out.arr0);
- mss::template negate<A8>(i_out.arr0);
- mss::template negate<A9>(i_out.arr0);
+ fapi2::ReturnCode l_rc;
+ mrs03_data l_data(i_target, l_rc);
+ FAPI_TRY( l_rc, "Unable to instantiate mrs03_data for %s", i_target );
- mss::template negate<A11>(i_out.arr0);
- mss::template negate<A13>(i_out.arr0);
- mss::template negate<A17>(i_out.arr0);
+ if(i_page > MAX_PAGE)
+ {
+ FAPI_ERR("Invalid MPR Page recieved: %d. Max encoding allowed: %d.", i_page, MAX_PAGE);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ }
- mss::template negate<BA0>(i_out.arr0);
- mss::template negate<BA1>(i_out.arr0);
- mss::template negate<BG0>(i_out.arr0);
- mss::template negate<BG1>(i_out.arr0);
+ l_data.iv_mpr_page = i_page;
+ FAPI_TRY( mrs_engine(i_target, l_data, i_rank, mss::tmrd(), io_inst),
+ "Failed to send MRS03 on %s, rank: %d, delay (in cycles): %d",
+ i_target, i_rank, mss::tmrd());
- return i_out;
+fapi_try_exit:
+ return fapi2::current_err;
}
-} // namespace
+} // ddr4
+} // mss
#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H
index db3fc7feb..22838dc4d 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H
@@ -104,7 +104,6 @@ struct mrs_data
template< fapi2::TargetType T >
fapi2::ReturnCode mrs_load( const fapi2::Target<T>& i_target );
-
//
// Implement the polymorphism for mrs_load
//
OpenPOWER on IntegriCloud