From 57bcb1f7cc08311036ddedcebfa788b7947cc59b Mon Sep 17 00:00:00 2001 From: Andre Marin Date: Thu, 15 Dec 2016 11:04:42 -0600 Subject: 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 Tested-by: Jenkins Server Reviewed-by: JACOB L. HARVEY Reviewed-by: Christian R. Geddes Reviewed-by: Brian R. Silver Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33978 Tested-by: Jenkins OP Build CI Tested-by: FSP CI Jenkins --- .../p9/procedures/hwp/memory/lib/dimm/bcw_load.H | 25 -- .../procedures/hwp/memory/lib/dimm/bcw_load_ddr4.C | 61 +-- .../hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H | 455 +++++++++++++++++++++ .../hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C | 15 +- .../xml/error_info/p9_memory_mss_data_buffer.xml | 56 +++ 5 files changed, 546 insertions(+), 66 deletions(-) create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H create mode 100644 src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_data_buffer.xml (limited to 'src/import/chips/p9') 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,35 +42,10 @@ #include #include -#include 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 >& 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(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 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 #include #include -#include #include +#include #include using fapi2::TARGET_TYPE_MCBIST; @@ -74,21 +74,21 @@ fapi2::ReturnCode bcw_load_ddr4( const fapi2::Target& 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& 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(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(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(i_target, l_data, io_inst) ); + } - FAPI_TRY( function_space_select<5>(i_target, io_inst) ); - FAPI_TRY( control_word_engine(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(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 +// *HWP HWP Backup: Brian Silver +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_DATA_BUFFER_DDR4_H_ +#define _MSS_DATA_BUFFER_DDR4_H_ + +#include +#include +#include +#include +#include +#include + +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 >& 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(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 >& 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(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& i_target, + const training i_mode, + std::vector< ccs::instruction_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 > 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(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& 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& i_target, + const uint64_t i_num_package_ranks, + std::vector< ccs::instruction_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(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& i_target, + const uint64_t i_rank, + const uint64_t i_trained_timing, + std::vector< ccs::instruction_t >& 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(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& i_target, + const command i_command, + std::vector< ccs::instruction_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(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 #include -#include +#include +#include #include using fapi2::TARGET_TYPE_MCBIST; @@ -150,17 +151,7 @@ fapi2::ReturnCode mrs_load( const fapi2::Target& 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(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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RC_MSS_INVALID_NUM_PKG_RANKS + + 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. + + NUM_PKG_RANKS + + DIMM_TARGET + HIGH + + + DIMM_TARGET + + + + -- cgit v1.2.1