diff options
Diffstat (limited to 'src/import/chips')
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; |