summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2016-12-15 11:04:42 -0600
committerChristian R. Geddes <crgeddes@us.ibm.com>2017-01-03 21:37:40 -0500
commit57bcb1f7cc08311036ddedcebfa788b7947cc59b (patch)
tree87e55117854db2204e492dfc21af71a635fb757f /src/import/chips/p9
parent2ed96daee929460c101fbd1051045502268c66e2 (diff)
downloadtalos-hostboot-57bcb1f7cc08311036ddedcebfa788b7947cc59b.tar.gz
talos-hostboot-57bcb1f7cc08311036ddedcebfa788b7947cc59b.zip
Add BCW API for rank presence, buffer training, mrep timing and UTs.
Change-Id: I9346c280ba95d792b6fb7d1047a6a25ea8ea66ba Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33959 Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com> Reviewed-by: Brian R. Silver <bsilver@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33978 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load.H25
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load_ddr4.C61
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H455
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C15
-rw-r--r--src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_data_buffer.xml56
5 files changed, 546 insertions, 66 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 f487a826d..9482de6fa 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,36 +42,11 @@
#include <lib/utils/c_str.H>
#include <lib/shared/mss_kind.H>
-#include <lib/dimm/ddr4/control_word_ddr4.H>
namespace mss
{
///
-/// @brief Sets the function space for the BCW
-/// @tparam T the functon space number we want
-/// @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< uint64_t T >
-inline fapi2::ReturnCode function_space_select(const fapi2::Target< fapi2::TARGET_TYPE_DIMM >& i_target,
- std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
-{
- // function space bits for the function space selector are
- // don't cares. We choose 0 for simplicity.
- constexpr uint8_t FSPACE = 0;
- constexpr uint8_t WORD = 7;
-
- 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;
-}
-
-///
/// @brief Perform the bcw_load operations
/// @tparam T the fapi2::TargetType of i_target
/// @param[in] i_target a fapi2::Target
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 379dee9ac..024923c04 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
@@ -41,8 +41,8 @@
#include <lib/eff_config/timing.H>
#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/dimm/ddr4/data_buffer_ddr4.H>
#include <lib/mss_attribute_accessors.H>
using fapi2::TARGET_TYPE_MCBIST;
@@ -74,21 +74,21 @@ fapi2::ReturnCode bcw_load_ddr4( const fapi2::Target<TARGET_TYPE_DIMM>& i_target
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() },
- { 0, 1, eff_dimm_ddr4_bc01, mss::tmrc() },
- { 0, 2, eff_dimm_ddr4_bc02, mss::tmrc() },
- { 0, 3, eff_dimm_ddr4_bc03, mss::tmrc() },
- { 0, 4, eff_dimm_ddr4_bc04, mss::tmrc() },
- { 0, 5, eff_dimm_ddr4_bc05, mss::tmrc() },
- { 0, 7, eff_dimm_ddr4_bc07, mss::tmrc() },
- { 0, 9, eff_dimm_ddr4_bc09, mss::tmrc() },
- { 0, 8, eff_dimm_ddr4_bc08, mss::tmrc() },
- { 0, 10, eff_dimm_ddr4_bc0a, l_tDLLK },
- { 0, 11, eff_dimm_ddr4_bc0b, mss::tmrc() },
- { 0, 12, eff_dimm_ddr4_bc0c, mss::tmrc() },
- { 0, 13, eff_dimm_ddr4_bc0d, mss::tmrc() },
- { 0, 14, eff_dimm_ddr4_bc0e, mss::tmrc() },
- { 0, 15, eff_dimm_ddr4_bc0f, mss::tmrc() },
+ { FUNC_SPACE_0, DQ_RTT_NOM_CW, eff_dimm_ddr4_bc00, mss::tmrc() },
+ { FUNC_SPACE_0, DQ_RTT_WR_CW, eff_dimm_ddr4_bc01, mss::tmrc() },
+ { FUNC_SPACE_0, DQ_RTT_PARK_CW, eff_dimm_ddr4_bc02, mss::tmrc() },
+ { FUNC_SPACE_0, DQ_DRIVER_CW, eff_dimm_ddr4_bc03, mss::tmrc() },
+ { FUNC_SPACE_0, MDQ_RTT_CW, eff_dimm_ddr4_bc04, mss::tmrc() },
+ { FUNC_SPACE_0, MDQ_DRIVER_CW, eff_dimm_ddr4_bc05, mss::tmrc() },
+ { FUNC_SPACE_0, RANK_PRESENCE_CW, eff_dimm_ddr4_bc07, mss::tmrc() },
+ { FUNC_SPACE_0, RANK_SELECTION_CW, eff_dimm_ddr4_bc08, mss::tmrc() },
+ { FUNC_SPACE_0, POWER_SAVING_CW, eff_dimm_ddr4_bc09, mss::tmrc() },
+ { FUNC_SPACE_0, OPERATING_SPEED, eff_dimm_ddr4_bc0a, l_tDLLK },
+ { FUNC_SPACE_0, VOLT_AND_SLEW_RATE_CW, eff_dimm_ddr4_bc0b, mss::tmrc() },
+ { FUNC_SPACE_0, BUFF_TRAIN_MODE_CW, eff_dimm_ddr4_bc0c, mss::tmrc() },
+ { FUNC_SPACE_0, LDQ_OPERATION_CW, eff_dimm_ddr4_bc0d, mss::tmrc() },
+ { FUNC_SPACE_0, PARITY_CW, eff_dimm_ddr4_bc0e, mss::tmrc() },
+ { FUNC_SPACE_0, ERROR_STATUS_CW, eff_dimm_ddr4_bc0f, mss::tmrc() },
};
// This initialization may be vendor specific. We might need a different
@@ -101,25 +101,28 @@ 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( ddr4::function_space_select<0>(i_target, 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( control_word_engine<BCW_8BIT>(i_target,
- cw_data(6, 4, eff_dimm_ddr4_f6bc4x, mss::tmrc()),
- io_inst) );
+ // We set our 8-bit buffer control words but have to switch function space
+ // number for different control words. So it doesn't fit cleanly into a
+ // vector like the 4-bit buffer control words that are all in function space 0
+ // (feels like we should be initializing more control word....)
+ {
+ cw_data l_data(FUNC_SPACE_6, BUFF_TRAIN_CONFIG_CW, eff_dimm_ddr4_f6bc4x, mss::tmrc());
+ FAPI_TRY( ddr4::function_space_select<6>(i_target, io_inst) );
+ FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, io_inst) );
+ }
- FAPI_TRY( function_space_select<5>(i_target, io_inst) );
- FAPI_TRY( control_word_engine<BCW_8BIT>(i_target,
- cw_data(5, 6, eff_dimm_ddr4_f5bc6x, mss::tmrc()),
- io_inst) );
+ {
+ cw_data l_data(FUNC_SPACE_5, DRAM_VREF_CW, eff_dimm_ddr4_f5bc6x, mss::tmrc());
+ FAPI_TRY( ddr4::function_space_select<5>(i_target, io_inst) );
+ FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, io_inst) );
+ }
// Its recommended to always return to the function space
// "pointer" back to 0 so we always know where we are starting from
- FAPI_TRY( function_space_select<0>(i_target, io_inst) );
+ FAPI_TRY( ddr4::function_space_select<0>(i_target, io_inst) );
}
fapi_try_exit:
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H
new file mode 100644
index 000000000..9c28ef8e7
--- /dev/null
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H
@@ -0,0 +1,455 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,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 data_buffer_ddr4.H
+/// @brief Code to support data_buffer_ddr4
+///
+// *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: HB:FSP
+
+#ifndef _MSS_DATA_BUFFER_DDR4_H_
+#define _MSS_DATA_BUFFER_DDR4_H_
+
+#include <vector>
+#include <fapi2.H>
+#include <lib/utils/c_str.H>
+#include <lib/dimm/bcw_load_ddr4.H>
+#include <lib/phy/dp16.H>
+#include <lib/dimm/ddr4/control_word_ddr4.H>
+
+namespace mss
+{
+
+enum nibble : size_t
+{
+ LOWER = 2,
+ UPPER = 3,
+};
+
+// function space and control word definitions
+enum db02_def
+{
+ // Function spaces
+ FUNC_SPACE_0 = 0,
+ FUNC_SPACE_1 = 1,
+ FUNC_SPACE_2 = 2,
+ FUNC_SPACE_3 = 3,
+ FUNC_SPACE_4 = 4,
+ FUNC_SPACE_5 = 5,
+ FUNC_SPACE_6 = 6,
+ FUNC_SPACE_7 = 7,
+
+ // 4 bit BCWs
+ DQ_RTT_NOM_CW = 0x0,
+ DQ_RTT_WR_CW = 0x1,
+ DQ_RTT_PARK_CW = 0x2,
+ DQ_DRIVER_CW = 0x3,
+ MDQ_RTT_CW = 0x4,
+ MDQ_DRIVER_CW = 0x5,
+ CMD_SPACE_CW = 0x6,
+ RANK_PRESENCE_CW = 0x7,
+ RANK_SELECTION_CW = 0x8,
+ POWER_SAVING_CW = 0x9,
+ OPERATING_SPEED = 0xA,
+ VOLT_AND_SLEW_RATE_CW = 0xB,
+ BUFF_TRAIN_MODE_CW = 0xC,
+ LDQ_OPERATION_CW = 0xD,
+ PARITY_CW = 0xE,
+ ERROR_STATUS_CW = 0xF,
+ FUNC_SPACE_SELECT_CW = 0x7,
+
+ // 8 bit BCWs
+ BUFF_TRAIN_CONFIG_CW = 0x4,
+ DRAM_VREF_CW = 0x6,
+};
+
+namespace ddr4
+{
+
+// buffer training steps from DB02 DDR4 spec
+// which makes them ddr4 specific
+enum training : size_t
+{
+ NORMAL,
+ MREP,
+ DWL,
+ HWL,
+ MRD,
+ MWD,
+ HIW,
+};
+
+enum command : size_t
+{
+ RESET_DLL = 0,
+ ZQCL = 1,
+ ZQCS = 2,
+ CLEAR_ERR_STAT = 3,
+ SOFT_RESET = 4
+};
+
+///
+/// @brief Sets the function space for the BCW
+/// @tparam T the functon space number we want
+/// @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< uint64_t T >
+inline fapi2::ReturnCode function_space_select(const fapi2::Target< fapi2::TARGET_TYPE_DIMM >& i_target,
+ std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
+{
+ // From DB02 spec - F[3:0]BC7x control word
+ constexpr size_t MAX_FUNC_SPACE = 7;
+
+ if( T > MAX_FUNC_SPACE )
+ {
+ // Function spaces are typically user selected.
+ // Sometimes function spaces are selected based on rank number
+ // or MDQ lane number which currently are also user inputs.
+
+ // We assert out for user programming erros
+ FAPI_ERR("%s. Invalid function space selection: %d, max valid function space is %d",
+ mss::c_str(i_target), T, MAX_FUNC_SPACE);
+
+ fapi2::Assert(false);
+ }
+
+ // function space bits for the function space selector are
+ // don't cares (XXX). We choose 0 for simplicity.
+ cw_data l_data( FUNC_SPACE_0, FUNC_SPACE_SELECT_CW, T, mss::tmrd() );
+
+ FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, io_inst),
+ "%s. Failed control_word_engine for 8-bit BCW (F%dBC%02lxX)",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number) );
+
+ // I don't know what already existed in this ccs instruction vector beforehand so
+ // I use the back() method to access the last added ccs instruction of interest
+ FAPI_INF("%s. F%dBC%02lx ccs inst 0x%016llx:0x%016llx, data: %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number),
+ uint64_t(io_inst.back().arr0), uint64_t(io_inst.back().arr1), uint8_t(l_data.iv_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Sets the function space for the BCW
+/// @param[in] i_target a DIMM target
+/// @param[in] i_func_space the functon space number we want
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+inline fapi2::ReturnCode function_space_select(const fapi2::Target< fapi2::TARGET_TYPE_DIMM >& i_target,
+ const uint64_t i_func_space,
+ std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
+{
+ // From DB02 spec - F[3:0]BC7x control word
+ constexpr size_t MAX_FUNC_SPACE = 7;
+
+ if( i_func_space > MAX_FUNC_SPACE )
+ {
+ // Function spaces are typically user selected.
+ // Sometimes function spaces are selected based on rank number
+ // or MDQ lane number which currently are also user inputs.
+
+ // We assert out for user programming erros
+ FAPI_ERR("%s. Invalid function space selection: %d, max valid function space is %d",
+ mss::c_str(i_target), i_func_space, MAX_FUNC_SPACE);
+
+ fapi2::Assert(false);
+ }
+
+ // function space bits for the function space selector are
+ // don't cares (XXX). We choose 0 for simplicity.
+ cw_data l_data( FUNC_SPACE_0, FUNC_SPACE_SELECT_CW, i_func_space, mss::tmrd() );
+
+ FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, io_inst),
+ "%s. Failed control_word_engine for 8-bit BCW (F%dBC%02lxX)",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number) );
+
+ // I don't know what already existed in this ccs instruction vector beforehand so
+ // I use the back() method to access the last added ccs instruction of interest
+ FAPI_INF("%s. F%dBC%02lx ccs inst 0x%016llx:0x%016llx, data: %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number),
+ uint64_t(io_inst.back().arr0), uint64_t(io_inst.back().arr1), uint8_t(l_data.iv_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Sets data buffer training mode control word
+/// @tparam T TargetType of the CCS instruction
+/// @param[in] i_target the DIMM target
+/// @param[in] i_mode buffer training mode
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note Sets buffer control word (BC0C) setting
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode set_buffer_training( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const training i_mode,
+ std::vector< ccs::instruction_t<T> >& io_inst )
+{
+ // This doesn't need to be reused so it is left local to this function scope
+ static const std::vector< std::pair<training, uint64_t> > BUFF_TRAINING =
+ {
+ { NORMAL, 0 },
+ { MREP, 1 },
+ { DWL, 4 },
+ { HWL, 5 },
+ { MRD, 6 },
+ { MWD, 7 },
+ { HIW, 8 },
+ };
+
+ // If we can't find the key then the user passed in an invalid mode
+ // and this is a user programming error. So we assert out.
+ // find_value_from_key API does the error checking and fails out
+ // for any invalid user input. Easier to handle for sparsed arrays.
+ uint64_t l_encoding = 0;
+ fapi2::Assert(find_value_from_key(BUFF_TRAINING, i_mode, l_encoding));
+
+ cw_data l_data(FUNC_SPACE_0, BUFF_TRAIN_MODE_CW, l_encoding, mss::tmrc());
+
+ FAPI_TRY( function_space_select(i_target, l_data.iv_func_space, io_inst),
+ "%s. Failed to select function space %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space) );
+
+ FAPI_TRY( control_word_engine<BCW_4BIT>(i_target, l_data, io_inst),
+ "%s. Failed control_word_engine for 4-bit BCW (F%dBC%02lx)",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number) );
+
+ // I don't know what already existed in this ccs instruction vector beforehand so
+ // I use the back() method to access the last added ccs instruction of interest
+ FAPI_INF("%s. F%dBC%02lx ccs inst 0x%016llx:0x%016llx, data: %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number),
+ uint64_t(io_inst.back().arr0), uint64_t(io_inst.back().arr1), uint8_t(l_data.iv_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Sets rank presence control word
+/// @param[in] i_num_package_ranks num of package ranks for LRDIMM
+/// @param[out] o_setting bc07 settings
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+static fapi2::ReturnCode rank_presence_helper(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t i_num_package_ranks,
+ uint64_t& o_setting)
+{
+ switch(i_num_package_ranks)
+ {
+ case 1:
+ o_setting = 0b1110;
+ break;
+
+ case 2:
+ o_setting = 0b1100;
+ break;
+
+ case 3:
+ o_setting = 0b1000;
+ break;
+
+ case 4:
+ o_setting = 0b0000;
+ break;
+
+ default:
+ // While an invalid input can signify a programming error
+ // it is expected that this input can come from the eff_master_rank accessor.
+ // If it is the latter than we will want to call out an error
+ // to raise red flags regarding decoded SPD data that sets this attribute
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_NUM_PKG_RANKS()
+ .set_DIMM_TARGET(i_target)
+ .set_NUM_PKG_RANKS(i_num_package_ranks),
+ "%s. Received invalid package rank %d",
+ mss::c_str(i_target), i_num_package_ranks );
+ break;
+ }
+
+ // If we got here than success
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ // If we are here than we FAPI_ASSERT'ed out
+ return fapi2::current_err;
+}
+
+///
+/// @brief Sets rank presence control word
+/// @tparam T TargetType of the CCS instruction
+/// @param[in] i_target the DIMM target
+/// @param[in] i_num_package_ranks num of package ranks for LRDIMM
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note Sets buffer control word (BC07) setting
+///
+template< fapi2::TargetType T>
+inline fapi2::ReturnCode set_rank_presence( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t i_num_package_ranks,
+ std::vector< ccs::instruction_t<T> >& io_inst )
+{
+ // Helper function handles error checking
+ uint64_t l_encoding = 0;
+ FAPI_TRY( rank_presence_helper( i_target, i_num_package_ranks, l_encoding),
+ "%s. Failed to set rank_presence BCW for %d number of package ranks",
+ mss::c_str(i_target), i_num_package_ranks );
+ {
+ cw_data l_data(FUNC_SPACE_0, RANK_PRESENCE_CW, l_encoding, mss::tmrc());
+
+ FAPI_TRY( function_space_select(i_target, l_data.iv_func_space, io_inst),
+ "%s. Failed to select function space %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space) );
+
+ FAPI_TRY( control_word_engine<BCW_4BIT>(i_target, l_data, io_inst),
+ "%s. Failed control_word_engine for 4-bit BCW (F%dBC%02lx)",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number) );
+
+ // I don't know what already existed in this ccs instruction vector beforehand so
+ // I use the back() method to access the last added ccs instruction of interest
+ FAPI_INF("%s. F%dBC%02lx ccs inst 0x%016llx:0x%016llx, data: %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number),
+ uint64_t(io_inst.back().arr0), uint64_t(io_inst.back().arr1), uint8_t(l_data.iv_data) );
+
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Sets Upper/Lower nibble DRAM interface receive enable training control word
+/// @tparam T the nibble of in training (upper/lower)
+/// @tparam OT TargetType of the CCS instruction
+/// @param[in] i_target the DIMM target
+/// @param[in] i_rank DIMM0 rank [0:3] or DIMM1 rank [4:7]
+/// @param[in] i_trained_timing the delay MDQS receive enable timing
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note Sets buffer control word ( F[3:0]BC2x ) setting
+///
+template< mss::nibble N, fapi2::TargetType OT>
+fapi2::ReturnCode set_mrep_timing_control( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_trained_timing,
+ std::vector< ccs::instruction_t<OT> >& io_inst )
+{
+ constexpr size_t MAX_DELAY = 63;
+
+ // These fail assertions are programming input erros
+ if( i_rank >= MAX_MRANK_PER_PORT )
+ {
+ FAPI_ERR("Invalid ranks received (%d) from max allowed (%d)]", i_rank, MAX_MRANK_PER_PORT - 1);
+ fapi2::Assert(false);
+ }
+
+ if( i_trained_timing > MAX_DELAY )
+ {
+ FAPI_ERR("Invalid trained delay received (%d tCK) from max allowed (%d tck)", i_trained_timing, MAX_DELAY);
+ fapi2::Assert(false);
+ }
+
+ // Function space is determined by rank index for control word since it has a [0:3] range
+ cw_data l_data( mss::index(i_rank), N, i_trained_timing, mss::tmrc() );
+
+ FAPI_TRY( function_space_select(i_target, l_data.iv_func_space, io_inst),
+ "%s. Failed to select function space %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space) );
+
+ FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, io_inst),
+ "%s. Failed control_word_engine for 8-bit BCW (F%dBC%02lxX)",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number) );
+
+ // I don't know what already existed in this ccs instruction vector beforehand so
+ // I use the back() method to access the last added ccs instruction of interest
+ FAPI_INF("%s. F%dBC%02lxX ccs inst 0x%016llx:0x%016llx, data: %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number),
+ uint64_t(io_inst.back().arr0), uint64_t(io_inst.back().arr1), uint8_t(l_data.iv_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Sets command space control word
+/// @tparam T TargetType of the CCS instruction
+/// @param[in] i_target the DIMM target
+/// @param[in] i_command command name
+/// @param[in,out] io_inst a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note Sets buffer control word (BC06) setting
+///
+template< fapi2::TargetType T>
+inline fapi2::ReturnCode set_command_space( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const command i_command,
+ std::vector< ccs::instruction_t<T> >& io_inst )
+{
+ constexpr uint64_t MAX_VALID_CMD = 4;
+
+ // User input programming error asserts program termination
+ if( i_command > MAX_VALID_CMD )
+ {
+ FAPI_ERR( "%s. Invalid command received: %d, largest valid command is %d",
+ mss::c_str(i_target), i_command, MAX_VALID_CMD );
+ fapi2::Assert(false);
+ }
+
+ // From the DDR4DB02 Spec: BC06 - Command Space Control Word
+ // After issuing a data buffer command via writes to BC06 waiting for tMRC(16 tCK)
+ // is required before the next DRAM command or BCW write can be issued.
+ cw_data l_data(FUNC_SPACE_0, CMD_SPACE_CW, i_command, mss::tmrc());
+
+ FAPI_TRY( function_space_select(i_target, l_data.iv_func_space, io_inst),
+ "%s. Failed to select function space %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space) );
+
+ FAPI_TRY( control_word_engine<BCW_4BIT>(i_target, l_data, io_inst),
+ "%s. Failed control_word_engine for 4-bit BCW (F%dBC%02lx)",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number) );
+
+ // I don't know what already existed in this ccs instruction vector beforehand so
+ // I use the back() method to access the last added ccs instruction of interest
+ FAPI_INF("%s. F%dBC%02lx ccs inst 0x%016llx:0x%016llx, data: %d",
+ mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number),
+ uint64_t(io_inst.back().arr0), uint64_t(io_inst.back().arr1), uint8_t(l_data.iv_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}// namespace ddr4
+} // namespace 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 a3e4542b5..7f42d97d6 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
@@ -37,7 +37,8 @@
#include <mss.H>
#include <lib/dimm/ddr4/mrs_load_ddr4.H>
-#include <lib/dimm/bcw_load.H>
+#include <lib/dimm/ddr4/control_word_ddr4.H>
+#include <lib/dimm/ddr4/data_buffer_ddr4.H>
#include <lib/eff_config/timing.H>
using fapi2::TARGET_TYPE_MCBIST;
@@ -150,17 +151,7 @@ fapi2::ReturnCode mrs_load( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
if( l_dimm_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM )
{
- constexpr uint8_t FSPACE = 0;
- constexpr uint8_t WORD = 6;
-
- // From the DDR4DB02 Spec: BC06 - Command Space Control Word
- // After issuing a data buffer command via writes to BC06 waiting for tMRC(16 tCK)
- // 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( control_word_engine<BCW_8BIT>(i_target,
- cw_data(FSPACE, WORD, eff_dimm_ddr4_bc06, mss::tmrc()),
- io_inst) );
+ FAPI_TRY( set_command_space(i_target, command::ZQCL, io_inst) );
}
fapi_try_exit:
diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_data_buffer.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_data_buffer.xml
new file mode 100644
index 000000000..230278c33
--- /dev/null
+++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_data_buffer.xml
@@ -0,0 +1,56 @@
+<!-- IBM_PROLOG_BEGIN_TAG -->
+<!-- This is an automatically generated prolog. -->
+<!-- -->
+<!-- $Source: src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_data_buffer.xml $ -->
+<!-- -->
+<!-- OpenPOWER HostBoot Project -->
+<!-- -->
+<!-- Contributors Listed Below - COPYRIGHT 2015,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 memory_mss_spd_decoder.xml -->
+<!-- @brief Error xml for spd_decoder -->
+<!-- -->
+<!-- *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: HB:FSP -->
+<!-- -->
+
+<hwpErrors>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_NUM_PKG_RANKS</rc>
+ <description>
+ Recieved an invalid number of package ranks when setting the
+ BC07 - Rank Presence Control Word. Could signify bad SPD data,
+ invalid decoding of SPD data, or invalid user input.
+ </description>
+ <ffdc>NUM_PKG_RANKS</ffdc>
+ <callout>
+ <target>DIMM_TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <deconfigure>
+ <target>DIMM_TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+</hwpErrors>
OpenPOWER on IntegriCloud