summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2016-12-01 03:56:02 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-12-07 13:55:06 -0500
commitd1fe32b96c0f48c266da346fa2d05676b3f1e4f8 (patch)
treed1ab3c66b7be16d9a4f813df15324953e3b9b0d8 /src/import/chips/p9/procedures/hwp
parent6d5be25917e0bd675147bf0cec03dc9da517d53a (diff)
downloadtalos-hostboot-d1fe32b96c0f48c266da346fa2d05676b3f1e4f8.tar.gz
talos-hostboot-d1fe32b96c0f48c266da346fa2d05676b3f1e4f8.zip
Add common functionality between RCD and data buffer control word API
Change-Id: I601f143578a796f30ad582c1581f73ebf413840c Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33247 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: JACOB L. HARVEY <jlharvey@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33260 Reviewed-by: Hostboot Team <hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load.H198
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load_ddr4.C19
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H345
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C6
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load.H20
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C116
6 files changed, 400 insertions, 304 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load.H
index 58480c6aa..f487a826d 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load.H
@@ -42,200 +42,11 @@
#include <lib/utils/c_str.H>
#include <lib/shared/mss_kind.H>
+#include <lib/dimm/ddr4/control_word_ddr4.H>
namespace mss
{
-enum data_buffer
-{
- BCW_4BIT,
- BCW_8BIT,
-};
-
-struct bcw_data
-{
- // function space #
- fapi2::buffer<uint8_t> iv_func_space;
-
- // Which buffer control word (bcw) # this is
- fapi2::buffer<uint8_t> iv_number;
-
- // The attribute getter
- fapi2::ReturnCode (*iv_attr_get)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&, uint8_t&);
-
- // The bcw value
- fapi2::buffer<uint8_t> iv_data;
-
- // The delay needed after this BCW word is written
- uint64_t iv_delay;
-
- ///
- /// @brief NO-OP function to avoid a function nullptr
- /// @param[in] i_target a DIMM target
- /// @param[out] o_output output remains unchanged
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode no_op_func(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_output)
- {
- return fapi2::FAPI2_RC_SUCCESS;
- }
-
- ///
- /// @brief ctor for attribute driven data
- ///
- bcw_data( uint64_t i_func_space,
- uint64_t i_number,
- fapi2::ReturnCode (*i_func)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&, uint8_t&),
- uint64_t i_delay ):
- iv_func_space(i_func_space),
- iv_number(i_number),
- iv_attr_get(i_func),
- iv_data(0),
- iv_delay(i_delay)
- {}
-
- ///
- /// @brief ctor for custom data
- ///
- bcw_data( uint64_t i_func_space,
- uint64_t i_number,
- uint64_t i_data,
- uint64_t i_delay):
- iv_func_space(i_func_space),
- iv_number(i_number),
- iv_data(i_data),
- iv_delay(i_delay)
- {
- // Setting the attribute accessor function pointer to NO-OP
- // when we call the ctor that doesn't use it to avoid cases
- // when iv_attr_get can be nullptr and potentially cause a seg fault
- iv_attr_get = &no_op_func;
- }
-
-};
-
-template< data_buffer T >
-class bcwTraits;
-
-template< >
-class bcwTraits< BCW_8BIT >
-{
- public:
- static constexpr uint64_t DATA_LEN = 8;
- static constexpr uint64_t WORD_LEN = 4;
- static constexpr uint64_t SWIZZLE_START = 7;
-};
-
-template< >
-class bcwTraits< BCW_4BIT >
-{
- public:
- static constexpr uint64_t DATA_LEN = 4;
- static constexpr uint64_t WORD_LEN = 4;
- static constexpr uint64_t SWIZZLE_START = 7;
-};
-
-///
-/// @brief Helper function to load BCWs
-/// @tparam T the buffer control word type (4 bit or 8 bit)
-/// @tparam TT traits type defaults to bcwTraits<T>
-/// @param[in] i_target a DIMM target
-/// @param[in] i_data bcw data to send
-/// @param[in,out] io_inst a vector of CCS instructions we should add to
-/// @return FAPI2_RC_SUCCESS if and only if ok
-///
-template< data_buffer T, typename TT = bcwTraits<T> >
-static fapi2::ReturnCode bcw_engine_boilerplate(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const bcw_data& i_data,
- std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
-{
- constexpr uint64_t DDR_ADDRESS_12 = 12;
-
- // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
- ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> l_inst = ccs::rcd_command<fapi2::TARGET_TYPE_MCBIST>(i_target);
-
- // Address bit 12 must be 1 for accesses to Data Buffer (DB) Control Words.
- // Consider adding more commonality between RCD/BCW commands - AAM
- l_inst.arr0.setBit<DDR_ADDRESS_12>();
-
- // For user defined data, iv_data is user defined and iv_attr_get is a NO-OP
- // For attribute defined data, iv_attr_get will define data and l_value initialization is overwritten
- // I need l_value integral because the attribute accessor template deduction doesn't let me use buffers
- // and since I'm passing in bcw data as const I can't pass in iv_data to the attribute accessor
- // which would break const correctness
- uint8_t l_value = i_data.iv_data;
- FAPI_TRY( i_data.iv_attr_get(i_target, l_value) );
-
- // Data to be written into the configuration registers
- // 4-bit control are containned in bits DA0 thorugh DA3
- // 8-bit control are contained in bits DA0 thorugh DA7
- mss::swizzle< MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13,
- TT::DATA_LEN, TT::SWIZZLE_START >(fapi2::buffer<uint8_t>(l_value), l_inst.arr0);
-
- // Selection of each word of control bits
- // 4-bit control words are selected by bits on DA4 through DA11
- // 8-bit control words are selected by bits on DA8 through DA11
- mss::swizzle < MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13 + TT::DATA_LEN,
- TT::WORD_LEN, TT::SWIZZLE_START > (i_data.iv_number, l_inst.arr0);
-
- // For changes to the control word setting [...] the controller needs to wait tMRC[tDLLK] after
- // the last control word access, before further access to the DRAM can take place.
- l_inst.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
- MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(i_data.iv_delay);
-
- FAPI_INF("F%dBC%02d%s value 0x%x (%d cycles) 0x%016llx:0x%016llx %s",
- uint8_t(i_data.iv_func_space), uint8_t(i_data.iv_number), (T == BCW_4BIT ? "" : "X"), l_value,
- i_data.iv_delay, uint64_t(l_inst.arr0), uint64_t(l_inst.arr1), mss::c_str(i_target));
-
- io_inst.push_back(l_inst);
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Sets buffer control words (BCW)
-/// @tparam T the buffer control word type (4 bit or 8 bit)
-/// @tparam TT traits type defaults to bcwTraits<T>
-/// @param[in] i_target a DIMM target
-/// @param[in] i_data a vector bcw data to send
-/// @param[in,out] io_inst a vector of CCS instructions we should add to
-/// @return FAPI2_RC_SUCCESS if and only if ok
-///
-template< data_buffer T, typename TT = bcwTraits<T> >
-inline fapi2::ReturnCode bcw_engine( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const bcw_data& i_data,
- std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
-{
- FAPI_TRY( bcw_engine_boilerplate<T>(i_target, i_data, io_inst) );
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Sets buffer control words (BCW)
-/// @tparam T the buffer control word type (4 bit or 8 bit)
-/// @tparam TT traits type defaults to bcwTraits<T>
-/// @param[in] i_target a DIMM target
-/// @param[in] i_data_list a vector bcw data to send
-/// @param[in,out] io_inst a vector of CCS instructions we should add to
-/// @return FAPI2_RC_SUCCESS if and only if ok
-///
-template<data_buffer T, typename TT = bcwTraits<T> >
-inline fapi2::ReturnCode bcw_engine( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<bcw_data>& i_data_list,
- std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
-{
- for (const auto& data : i_data_list)
- {
- FAPI_TRY( bcw_engine_boilerplate<T>(i_target, data, io_inst) );
- }
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
///
/// @brief Sets the function space for the BCW
/// @tparam T the functon space number we want
@@ -252,9 +63,9 @@ inline fapi2::ReturnCode function_space_select(const fapi2::Target< fapi2::TARGE
constexpr uint8_t FSPACE = 0;
constexpr uint8_t WORD = 7;
- FAPI_TRY( bcw_engine<BCW_8BIT>(i_target,
- bcw_data( FSPACE, WORD, T, mss::tmrd() ),
- io_inst) );
+ FAPI_TRY( control_word_engine<BCW_8BIT>(i_target,
+ cw_data( FSPACE, WORD, T, mss::tmrd() ),
+ io_inst) );
fapi_try_exit:
return fapi2::current_err;
@@ -269,7 +80,6 @@ fapi_try_exit:
template< fapi2::TargetType T >
fapi2::ReturnCode bcw_load( const fapi2::Target<T>& i_target );
-
//
// Implement the polymorphism for bcw_load
//
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load_ddr4.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load_ddr4.C
index 3182654bf..379dee9ac 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load_ddr4.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load_ddr4.C
@@ -42,6 +42,7 @@
#include <lib/ccs/ccs.H>
#include <lib/dimm/bcw_load_ddr4.H>
#include <lib/dimm/bcw_load.H>
+#include <lib/dimm/ddr4/control_word_ddr4.H>
#include <lib/mss_attribute_accessors.H>
using fapi2::TARGET_TYPE_MCBIST;
@@ -67,10 +68,10 @@ fapi2::ReturnCode bcw_load_ddr4( const fapi2::Target<TARGET_TYPE_DIMM>& i_target
// Per DDR4BC01
uint64_t l_tDLLK = 0;
- FAPI_TRY( tdllk(i_target, l_tDLLK), "Failed to get tdllk for %s", mss::c_str(i_target) );
+ FAPI_TRY( tdllk(i_target, l_tDLLK), "Failed to get tDLLK for %s", mss::c_str(i_target) );
{
- static const std::vector< bcw_data > l_bcw_4bit_data =
+ static const std::vector< cw_data > l_bcw_4bit_data =
{
// function space #, bcw #, attribute accessor, timing delay
{ 0, 0, eff_dimm_ddr4_bc00, mss::tmrc() },
@@ -101,20 +102,20 @@ fapi2::ReturnCode bcw_load_ddr4( const fapi2::Target<TARGET_TYPE_DIMM>& i_target
// We set the 4-bit buffer control words first (they live in function space 0
// hw is supposed to default to function space 0 but Just.In.Case.
FAPI_TRY( function_space_select<0>(i_target, io_inst) );
- FAPI_TRY( bcw_engine<BCW_4BIT>(i_target, l_bcw_4bit_data, io_inst) );
+ FAPI_TRY( control_word_engine<BCW_4BIT>(i_target, l_bcw_4bit_data, io_inst) );
// We set our 8-bit buffer control words but switch function space
// for control words that live in a different one
// (feels a little on the light side...)
FAPI_TRY( function_space_select<6>(i_target, io_inst) );
- FAPI_TRY( bcw_engine<BCW_8BIT>(i_target,
- bcw_data(6, 4, eff_dimm_ddr4_f6bc4x, mss::tmrc()),
- io_inst) );
+ FAPI_TRY( control_word_engine<BCW_8BIT>(i_target,
+ cw_data(6, 4, eff_dimm_ddr4_f6bc4x, mss::tmrc()),
+ io_inst) );
FAPI_TRY( function_space_select<5>(i_target, io_inst) );
- FAPI_TRY( bcw_engine<BCW_8BIT>(i_target,
- bcw_data(5, 6, eff_dimm_ddr4_f5bc6x, mss::tmrc()),
- io_inst) );
+ FAPI_TRY( control_word_engine<BCW_8BIT>(i_target,
+ cw_data(5, 6, eff_dimm_ddr4_f5bc6x, mss::tmrc()),
+ io_inst) );
// Its recommended to always return to the function space
// "pointer" back to 0 so we always know where we are starting from
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H
new file mode 100644
index 000000000..093437e81
--- /dev/null
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H
@@ -0,0 +1,345 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] 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 control_word_ddr4.C
+/// @brief Run and manage the DDR4 control words for the RCD and data buffers
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 1
+// *HWP Consumed by: FSP:HB
+
+
+#ifndef _MSS_CONTROL_WORD_H_
+#define _MSS_CONTROL_WORD_H_
+
+#include <fapi2.H>
+
+#include <p9_mc_scom_addresses.H>
+
+#include <lib/utils/c_str.H>
+#include <lib/ccs/ccs.H>
+
+namespace mss
+{
+
+enum control_word
+{
+ // buffer control words
+ BCW_4BIT,
+ BCW_8BIT,
+
+ // register control words
+ RCW_4BIT,
+ RCW_8BIT,
+
+};
+
+///
+/// @class cw_data
+/// @brief class that represents (register/buffer) control word data
+///
+struct cw_data
+{
+ // function space #
+ fapi2::buffer<uint8_t> iv_func_space;
+
+ // Which control word# this is (rcw or bcw)
+ fapi2::buffer<uint8_t> iv_number;
+
+ // The attribute getter
+ fapi2::ReturnCode (*iv_attr_get)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&, uint8_t&);
+
+ // The cw value
+ fapi2::buffer<uint8_t> iv_data;
+
+ // The delay needed after this CW word is written
+ uint64_t iv_delay;
+
+ ///
+ /// @brief NO-OP function to avoid a function nullptr
+ /// @param[in] i_target a DIMM target
+ /// @param[out] o_output output remains unchanged
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode no_op_func(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_output)
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief ctor for attribute driven data
+ ///
+ cw_data( const uint64_t i_func_space,
+ const uint64_t i_number,
+ fapi2::ReturnCode (*i_func)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&, uint8_t&),
+ const uint64_t i_delay ):
+ iv_func_space(i_func_space),
+ iv_number(i_number),
+ iv_attr_get(i_func),
+ iv_data(0),
+ iv_delay(i_delay)
+ {}
+
+ ///
+ /// @brief ctor for custom data
+ ///
+ cw_data( const uint64_t i_func_space,
+ const uint64_t i_number,
+ const uint64_t i_data,
+ const uint64_t i_delay):
+ iv_func_space(i_func_space),
+ iv_number(i_number),
+ iv_data(i_data),
+ iv_delay(i_delay)
+ {
+ // Setting the attribute accessor function pointer to NO-OP
+ // when we call the ctor that doesn't use it to avoid cases
+ // when iv_attr_get can be nullptr and potentially cause a seg fault
+ iv_attr_get = &no_op_func;
+ }
+
+};
+
+///
+/// @class cwTraits
+/// @brief a collection of traits associated with the control word engine
+///
+template< control_word T >
+class cwTraits;
+
+///
+/// @class cwTraits
+/// @brief a collection of traits associated with the 8-bit buffer control words
+///
+template< >
+class cwTraits< BCW_8BIT >
+{
+ public:
+ static constexpr uint64_t DATA_LEN = 8;
+ static constexpr uint64_t WORD_LEN = 4;
+ static constexpr uint64_t SWIZZLE_START = 7;
+};
+
+///
+/// @class cwTraits
+/// @brief a collection of traits associated with the 4-bit buffer control words
+///
+template< >
+class cwTraits< BCW_4BIT >
+{
+ public:
+ static constexpr uint64_t DATA_LEN = 4;
+ static constexpr uint64_t WORD_LEN = 4;
+ static constexpr uint64_t SWIZZLE_START = 7;
+};
+
+///
+/// @class cwTraits
+/// @brief a collection of traits associated with the 8-bit register control words
+///
+template< >
+class cwTraits< RCW_8BIT >
+{
+ public:
+ static constexpr uint64_t DATA_LEN = 8;
+ static constexpr uint64_t WORD_LEN = 5;
+ static constexpr uint64_t SWIZZLE_START = 7;
+};
+
+///
+/// @class cwTraits
+/// @brief a collection of traits associated with the 4-bit register control words
+///
+template< >
+class cwTraits< RCW_4BIT >
+{
+ public:
+ static constexpr uint64_t DATA_LEN = 4;
+ static constexpr uint64_t WORD_LEN = 4;
+ static constexpr uint64_t SWIZZLE_START = 7;
+};
+
+///
+/// @brief Helper function to set an RCD or data buffer command to the CCS instruction
+/// @tparam T the buffer control word type (4 bit or 8 bit)
+/// @tparam TT traits type defaults to cwTraits<T>
+/// @tparam OT the TargetType of the CCS instruction
+/// @param[in] i_target a DIMM target
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< control_word T, typename TT = cwTraits<T>, fapi2::TargetType OT >
+static void set_cw_command( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ ccs::instruction_t<OT>& o_inst);
+
+///
+/// @brief Helper function to set an RCD or data buffer command to the CCS instruction
+/// @param[in] i_target a DIMM target
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note BCW_4BIT specialization
+///
+template< >
+inline void set_cw_command<BCW_4BIT>( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_inst)
+{
+ // Address bit 12 must be 1 for accesses to Data Buffer (DB) Control Words.
+ constexpr uint64_t DDR_ADDRESS_12 = 12;
+
+ o_inst = ccs::rcd_command<fapi2::TARGET_TYPE_MCBIST>(i_target);
+ o_inst.arr0.setBit<DDR_ADDRESS_12>();
+}
+
+///
+/// @brief Helper function to set an RCD or data buffer command to the CCS instruction
+/// @param[in] i_target a DIMM target
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note BCW_8BIT specialization
+///
+template< >
+inline void set_cw_command<BCW_8BIT> ( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_inst)
+{
+ set_cw_command<BCW_4BIT>(i_target, o_inst);
+}
+
+///
+/// @brief Helper function to set an RCD or data buffer command to the CCS instruction
+/// @param[in] i_target a DIMM target
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note RCW_4BIT specialization
+///
+template< >
+inline void set_cw_command<RCW_4BIT>( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_inst)
+{
+ o_inst = ccs::rcd_command<fapi2::TARGET_TYPE_MCBIST>(i_target);
+}
+
+///
+/// @brief Helper function to set an RCD or data buffer command to the CCS instruction
+/// @param[in] i_target a DIMM target
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note RCW_8BIT specialization
+///
+template< >
+inline void set_cw_command<RCW_8BIT>( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_inst)
+{
+ set_cw_command<RCW_4BIT>(i_target, o_inst);
+}
+
+///
+/// @brief Control word engine that sets the CCS instruction
+/// @tparam T the buffer control word type (4 bit or 8 bit)
+/// @tparam TT traits type defaults to cwTraits<T>
+/// @tparam OT the TargetType of the CCS instruction
+/// @param[in] i_target a DIMM target
+/// @param[in] i_data control word data to send
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< control_word T, typename TT = cwTraits<T>, fapi2::TargetType OT >
+fapi2::ReturnCode control_word_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const cw_data& i_data,
+ std::vector< ccs::instruction_t<OT> >& io_inst)
+{
+ ccs::instruction_t<OT> l_inst;
+ set_cw_command<T>(i_target, l_inst);
+
+ // For user defined data, iv_data is user defined and iv_attr_get is a NO-OP
+ // For attribute defined data, iv_attr_get will define datna and l_value initialization is overwritten
+ // I need l_value integral because the attribute accessor template deduction doesn't let me use buffers
+ // and since I'm passing in bcw data as const I can't pass in iv_data to the attribute accessor
+ // which would break const correctness
+ uint8_t l_value = i_data.iv_data;
+ FAPI_TRY( i_data.iv_attr_get(i_target, l_value) );
+
+ // Data to be written into the configuration registers
+ // 4-bit control are containned in bits DA0 thorugh DA3
+ // 8-bit control are contained in bits DA0 thorugh DA7
+ mss::swizzle< MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13,
+ TT::DATA_LEN, TT::SWIZZLE_START >(fapi2::buffer<uint8_t>(l_value), l_inst.arr0);
+
+ // Selection of each word of control bits
+ // 4-bit control words are selected by bits on DA4 through DA11
+ // 8-bit control words are selected by bits on DA8 through DA11
+ mss::swizzle < MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13 + TT::DATA_LEN,
+ TT::WORD_LEN, TT::SWIZZLE_START > (i_data.iv_number, l_inst.arr0);
+
+ // For changes to the control word setting [...] the controller needs to wait tMRC[tDLLK] after
+ // the last control word access, before further access to the DRAM can take place.
+ l_inst.arr1.template insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
+ MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(i_data.iv_delay);
+
+ FAPI_INF("F%d%s%02d%s value 0x%x (%d cycles) 0x%016llx:0x%016llx %s",
+ uint8_t(i_data.iv_func_space),
+ (T == BCW_4BIT || T == BCW_8BIT ? "BC" : "RC"),
+ uint8_t(i_data.iv_number),
+ (T == BCW_4BIT || T == RCW_4BIT ? "" : "X"),
+ l_value,
+ i_data.iv_delay,
+ uint64_t(l_inst.arr0), uint64_t(l_inst.arr1),
+ mss::c_str(i_target));
+
+ io_inst.push_back(l_inst);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Control word engine that sets the CCS instruction
+/// @tparam T the buffer control word type (4 bit or 8 bit)
+/// @tparam TT traits type defaults to cwTraits<T>
+/// @tparam OT the TargetType of the CCS instruction
+/// @param[in] i_target a DIMM target
+/// @param[in] i_data_list a vector of control word data to send
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< control_word T, typename TT = cwTraits<T>, fapi2::TargetType OT >
+fapi2::ReturnCode control_word_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<cw_data>& i_data_list,
+ std::vector< ccs::instruction_t<OT> >& io_inst)
+{
+ for (const auto& data : i_data_list)
+ {
+ FAPI_TRY( control_word_engine<T>(i_target, data, io_inst) );
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}// mss
+
+#endif
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 67349352a..a3e4542b5 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
@@ -158,9 +158,9 @@ fapi2::ReturnCode mrs_load( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
// is required before the next DRAM command or BCW write can be issued.
FAPI_TRY( function_space_select<0>(i_target, io_inst) );
- FAPI_TRY( bcw_engine<BCW_8BIT>(i_target,
- bcw_data(FSPACE, WORD, eff_dimm_ddr4_bc06, mss::tmrc()),
- io_inst) );
+ FAPI_TRY( control_word_engine<BCW_8BIT>(i_target,
+ cw_data(FSPACE, WORD, eff_dimm_ddr4_bc06, mss::tmrc()),
+ io_inst) );
}
fapi_try_exit:
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load.H
index ce17f855d..d75d57732 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load.H
@@ -46,26 +46,6 @@
namespace mss
{
-struct rcd_data
-{
- // Which RC# this is
- fapi2::buffer<uint8_t> iv_rcd;
-
- // The attribute getter
- fapi2::ReturnCode (*iv_func)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&, uint8_t&);
-
- // The delay needed after this RCD word is written
- uint64_t iv_delay;
-
- rcd_data( uint64_t i_rcd,
- fapi2::ReturnCode (*i_func)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&, uint8_t&),
- uint64_t i_delay ):
- iv_rcd(i_rcd),
- iv_func(i_func),
- iv_delay(i_delay)
- {}
-};
-
///
/// @brief Perform the rcd_load operations
/// @tparam T, the fapi2::TargetType of i_target
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C
index acad2884d..05b2b0e34 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C
@@ -37,6 +37,7 @@
#include <mss.H>
#include <lib/dimm/rcd_load_ddr4.H>
+#include <lib/dimm/ddr4/control_word_ddr4.H>
using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
@@ -51,100 +52,59 @@ namespace mss
///
/// @brief Perform the rcd_load_ddr4 operations - TARGET_TYPE_DIMM specialization
/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_DIMM>
-/// @param[in] a vector of CCS instructions we should add to
+/// @param[in,out] a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode rcd_load_ddr4( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
- std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& i_inst)
+ std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& io_inst)
{
FAPI_INF("rcd_load_ddr4 %s", mss::c_str(i_target));
// Per DDR4RCD02, tSTAB is us. We want this in cycles for the CCS.
const uint64_t tSTAB = mss::us_to_cycles(i_target, mss::tstab());
+ constexpr uint8_t FS0 = 0; // Function space 0
- static const std::vector< rcd_data > l_rcd_4bit_data =
+ // RCD 4-bit data - integral represents rc#
+ static const std::vector< cw_data > l_rcd_4bit_data =
{
- { 0, eff_dimm_ddr4_rc00, mss::tmrd() }, { 1, eff_dimm_ddr4_rc01, mss::tmrd() },
- { 2, eff_dimm_ddr4_rc02, tSTAB }, { 3, eff_dimm_ddr4_rc03, mss::tmrd_l() },
- { 4, eff_dimm_ddr4_rc04, mss::tmrd_l() }, { 5, eff_dimm_ddr4_rc05, mss::tmrd_l() },
- { 6, eff_dimm_ddr4_rc06_07, mss::tmrd() }, { 8, eff_dimm_ddr4_rc08, mss::tmrd() },
- { 9, eff_dimm_ddr4_rc09, mss::tmrd() }, { 10, eff_dimm_ddr4_rc10, tSTAB },
- { 11, eff_dimm_ddr4_rc11, mss::tmrd() }, { 12, eff_dimm_ddr4_rc12, mss::tmrd() },
- { 13, eff_dimm_ddr4_rc13, mss::tmrd() }, { 14, eff_dimm_ddr4_rc14, mss::tmrd() },
- { 15, eff_dimm_ddr4_rc15, mss::tmrd() },
+ { FS0, 0, eff_dimm_ddr4_rc00, mss::tmrd() },
+ { FS0, 1, eff_dimm_ddr4_rc01, mss::tmrd() },
+ { FS0, 2, eff_dimm_ddr4_rc02, tSTAB },
+ { FS0, 3, eff_dimm_ddr4_rc03, mss::tmrd_l() },
+ { FS0, 4, eff_dimm_ddr4_rc04, mss::tmrd_l() },
+ { FS0, 5, eff_dimm_ddr4_rc05, mss::tmrd_l() },
+ { FS0, 6, eff_dimm_ddr4_rc06_07, mss::tmrd() },
+ { FS0, 8, eff_dimm_ddr4_rc08, mss::tmrd() },
+ { FS0, 9, eff_dimm_ddr4_rc09, mss::tmrd() },
+ { FS0, 10, eff_dimm_ddr4_rc10, tSTAB },
+ { FS0, 11, eff_dimm_ddr4_rc11, mss::tmrd() },
+ { FS0, 12, eff_dimm_ddr4_rc12, mss::tmrd() },
+ { FS0, 13, eff_dimm_ddr4_rc13, mss::tmrd() },
+ { FS0, 14, eff_dimm_ddr4_rc14, mss::tmrd() },
+ { FS0, 15, eff_dimm_ddr4_rc15, mss::tmrd() },
};
- static const std::vector< rcd_data > l_rcd_8bit_data =
+ // RCD 8-bit data - integral represents rc#
+ static const std::vector< cw_data > l_rcd_8bit_data =
{
- { 1, eff_dimm_ddr4_rc_1x, mss::tmrd() }, { 2, eff_dimm_ddr4_rc_2x, mss::tmrd() },
- { 3, eff_dimm_ddr4_rc_3x, tSTAB }, { 4, eff_dimm_ddr4_rc_4x, mss::tmrd() },
- { 5, eff_dimm_ddr4_rc_5x, mss::tmrd() }, { 6, eff_dimm_ddr4_rc_6x, mss::tmrd() },
- { 7, eff_dimm_ddr4_rc_7x, mss::tmrd() }, { 8, eff_dimm_ddr4_rc_8x, mss::tmrd() },
- { 9, eff_dimm_ddr4_rc_9x, mss::tmrd() }, { 10, eff_dimm_ddr4_rc_ax, mss::tmrd() },
- { 11, eff_dimm_ddr4_rc_bx, mss::tmrd_l() }
+ { FS0, 1, eff_dimm_ddr4_rc_1x, mss::tmrd() },
+ { FS0, 2, eff_dimm_ddr4_rc_2x, mss::tmrd() },
+ { FS0, 3, eff_dimm_ddr4_rc_3x, tSTAB },
+ { FS0, 4, eff_dimm_ddr4_rc_4x, mss::tmrd() },
+ { FS0, 5, eff_dimm_ddr4_rc_5x, mss::tmrd() },
+ { FS0, 6, eff_dimm_ddr4_rc_6x, mss::tmrd() },
+ { FS0, 7, eff_dimm_ddr4_rc_7x, mss::tmrd() },
+ { FS0, 8, eff_dimm_ddr4_rc_8x, mss::tmrd() },
+ { FS0, 9, eff_dimm_ddr4_rc_9x, mss::tmrd() },
+ { FS0, 10, eff_dimm_ddr4_rc_ax, mss::tmrd() },
+ { FS0, 11, eff_dimm_ddr4_rc_bx, mss::tmrd_l() }
};
- fapi2::buffer<uint8_t> l_value;
+ // Load 4-bit data
+ FAPI_TRY( control_word_engine<RCW_4BIT>(i_target, l_rcd_4bit_data, io_inst) );
- // A little 4bit RCD love ...
- for (const auto& d : l_rcd_4bit_data)
- {
- // Keep in mind that swizzles count back from SWIZZLE_START for the apprporiate length in bits
- constexpr uint64_t DATA_LEN = 4;
- constexpr uint64_t WORD_LEN = 4;
- constexpr uint64_t SWIZZLE_START = 7;
-
- // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
- ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst = ccs::rcd_command<TARGET_TYPE_MCBIST>(i_target);
- FAPI_TRY( d.iv_func(i_target, l_value) );
-
- // Don't care if the value is 0 - send it anyway
- // Data to be written into the 4-bit configuration registers need to be presented on DA0 .. DA3
- mss::swizzle<MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13,
- DATA_LEN, SWIZZLE_START>(l_value, l_inst.arr0);
-
- // Selection of each word of 4-bit control bits is presented on inputs DA4 through DA12
- mss::swizzle < MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13 + DATA_LEN,
- WORD_LEN, SWIZZLE_START > (d.iv_rcd, l_inst.arr0);
-
- // For changes to the control word setting [...] the controller needs to wait tMRD[tSTAB] after
- // the last control word access, before further access to the DRAM can take place.
- l_inst.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(d.iv_delay);
-
- FAPI_INF("RCD%02d value 0x%x (%d) 0x%016llx:0x%016llx %s", uint8_t(d.iv_rcd), l_value, d.iv_delay,
- l_inst.arr0, l_inst.arr1, mss::c_str(i_target));
- i_inst.push_back(l_inst);
- }
-
- // 8bit's turn
- for (auto d : l_rcd_8bit_data)
- {
- // Keep in mind that swizzles count back from SWIZZLE_START for the apprporiate length in bits
- constexpr uint64_t DATA_LEN = 8;
- constexpr uint64_t WORD_LEN = 5;
- constexpr uint64_t SWIZZLE_START = 7;
-
- // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
- ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst = ccs::rcd_command<TARGET_TYPE_MCBIST>(i_target);
- FAPI_TRY( d.iv_func(i_target, l_value) );
-
- // Don't care if the value is 0 - send it anyway
- // Data to be written into the 8-bit configuration registers need to be presented on DA0 .. DA7
- mss::swizzle<MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13,
- DATA_LEN, SWIZZLE_START>(l_value, l_inst.arr0);
-
- // Selection of each word of 8-bit control bits is presented on inputs DA8 through DA12.
- mss::swizzle < MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_0_13 + DATA_LEN,
- WORD_LEN, SWIZZLE_START > (d.iv_rcd, l_inst.arr0);
-
- // For changes to the control word setting [...] the controller needs to wait tMRD[tSTAB] after
- // the last control word access, before further access to the DRAM can take place.
- l_inst.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(d.iv_delay);
-
- FAPI_INF("RCD%XX value 0x%x (%d) 0x%016llx:0x%016llx %s", uint8_t(d.iv_rcd), l_value, d.iv_delay,
- l_inst.arr0, l_inst.arr1, mss::c_str(i_target));
- i_inst.push_back(l_inst);
- }
+ // Load 8-bit data
+ FAPI_TRY( control_word_engine<RCW_8BIT>(i_target, l_rcd_8bit_data, io_inst) );
fapi_try_exit:
return fapi2::current_err;
OpenPOWER on IntegriCloud