Skip to content

Commit

Permalink
Remove ZQCAL redundant CCS inst, move to draminit_training
Browse files Browse the repository at this point in the history
Lab requested to move ZQCL to draminit_training to control
(with granularity) all enabled cal steps from an attribute in
training. Also removing redundant ZQCAL being sent out for both
 a-side/b-side and addr_mirroring since this only applies to MRS cmds.

Added new attribute proposal for CAL_STEPS_ENABLE to
account for LRDIMM training steps and more control bits
such as INITIAL_PAT_WR and WR_VRE_LATCH

Change-Id: Ibb758af74966a5dd659bf3dda86f283f73956bca
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/38648
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com>
Reviewed-by: Matt K. Light <mklight@us.ibm.com>
Reviewed-by: Thi N. Tran <thi@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/38650
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
  • Loading branch information
aamarin authored and dcrowell77 committed May 25, 2017
1 parent 4d9e5a4 commit c00a806
Show file tree
Hide file tree
Showing 21 changed files with 480 additions and 236 deletions.
Expand Up @@ -43,6 +43,7 @@
#include <lib/dimm/bcw_load_ddr4.H>
#include <lib/phy/dp16.H>
#include <lib/dimm/ddr4/control_word_ddr4.H>
#include <lib/eff_config/timing.H>

namespace mss
{
Expand Down
Expand Up @@ -84,11 +84,7 @@ fapi2::ReturnCode mrs_load( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
{
FAPI_INF("ddr4::mrs_load %s", mss::c_str(i_target));

fapi2::buffer<uint16_t> l_cal_steps;
uint64_t tDLLK = 0;
uint8_t l_dimm_type = 0;

static std::vector< mrs_data<TARGET_TYPE_MCBIST> > l_mrs_data =
static const std::vector< mrs_data<TARGET_TYPE_MCBIST> > MRS_DATA =
{
// JEDEC ordering of MRS per DDR4 power on sequence
{ 3, mrs03, mrs03_decode, mss::tmrd() },
Expand All @@ -97,64 +93,22 @@ fapi2::ReturnCode mrs_load( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
{ 4, mrs04, mrs04_decode, mss::tmrd() },
{ 2, mrs02, mrs02_decode, mss::tmrd() },
{ 1, mrs01, mrs01_decode, mss::tmrd() },

// We need to wait either tmod or tmrd before zqcl.
{ 0, mrs00, mrs00_decode, std::max(mss::tmrd(), mss::tmod(i_target)) },
// We need to wait tmod before zqcl, a non-mrs command
{ 0, mrs00, mrs00_decode, mss::tmod(i_target) },
};

std::vector< uint64_t > l_ranks;
FAPI_TRY( mss::rank::ranks(i_target, l_ranks) );
FAPI_TRY( mss::tdllk(i_target, tDLLK) );

// Load MRS
for (const auto& d : l_mrs_data)
for (const auto& d : MRS_DATA)
{
for (const auto& r : l_ranks)
{
FAPI_TRY( mrs_engine(i_target, d, r, io_inst) );
}
}

// Load ZQ Cal Long instruction only if the bit in the cal steps says to do so.
FAPI_TRY( mss::cal_step_enable(i_target, l_cal_steps) );

if (l_cal_steps.getBit<EXT_ZQCAL>() != 0)
{
for (const auto& r : l_ranks)
{
// Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_a_side = ccs::zqcl_command<TARGET_TYPE_MCBIST>(i_target, r);
ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_b_side;

FAPI_TRY( mss::address_mirror(i_target, r, l_inst_a_side) );
l_inst_b_side = mss::address_invert(l_inst_a_side);

l_inst_a_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(tDLLK + mss::tzqinit());
l_inst_b_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(tDLLK + mss::tzqinit());

// There's nothing to decode here.
FAPI_INF("ZQCL 0x%016llx:0x%016llx %s:rank %d a-side",
l_inst_a_side.arr0, l_inst_a_side.arr1, mss::c_str(i_target), r);
FAPI_INF("ZQCL 0x%016llx:0x%016llx %s:rank %d b-side",
l_inst_b_side.arr0, l_inst_b_side.arr1, mss::c_str(i_target), r);

// Add both to the CCS program
io_inst.push_back(l_inst_a_side);
io_inst.push_back(l_inst_b_side);
}
}

// For LRDIMMs, program BCW to send ZQCal Long command to all databuffers
// in broadcast mode
FAPI_TRY( eff_dimm_type(i_target, l_dimm_type) );

if( l_dimm_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM )
{
FAPI_TRY( set_command_space(i_target, command::ZQCL, io_inst) );
}

fapi_try_exit:
return fapi2::current_err;
}
Expand Down
131 changes: 131 additions & 0 deletions src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/zqcal.C
Expand Up @@ -22,3 +22,134 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */

///
/// @file zqcal.C
/// @brief Subroutines to send ZQCL commands
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <vector>
#include <fapi2.H>

#include <lib/dimm/ddr4/zqcal.H>
#include <lib/dimm/ddr4/data_buffer_ddr4.H>
#include <lib/ccs/ccs.H>
#include <lib/eff_config/timing.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_DIMM;

namespace mss
{

///
/// @brief Setup DRAM ZQCL
/// Specializaton for TARGET_TYPE_DIMM
/// @param[in] i_target the target associated with this cal
/// @param[in] i_rank the current rank
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template<>
fapi2::ReturnCode setup_dram_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
const uint64_t i_rank,
std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst;

uint64_t tDLLK = 0;
FAPI_TRY( mss::tdllk(i_target, tDLLK) );

// Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
l_inst = ccs::zqcl_command<TARGET_TYPE_MCBIST>(i_target, i_rank);

l_inst.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(tDLLK + mss::tzqinit());

// There's nothing to decode here.
FAPI_INF("ZQCL 0x%016llx:0x%016llx %s:rank %d",
l_inst.arr0, l_inst.arr1, mss::c_str(i_target), i_rank);

// Add both to the CCS program
io_inst.push_back(l_inst);

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Setup LRDIMM data buffer ZQCL
/// Specializaton for TARGET_TYPE_DIMM
/// @param[in] i_target the target associated with this cal
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template<>
fapi2::ReturnCode setup_data_buffer_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
// For LRDIMMs, program BCW to send ZQCal Long command to all data buffers
// in broadcast mode
uint8_t l_dimm_type = 0;
FAPI_TRY( eff_dimm_type(i_target, l_dimm_type) );

if( l_dimm_type != fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM )
{
FAPI_INF("%s Skipping LRDIMM data buffer ZQCL, only done on LRDIMMs", mss::c_str(i_target));
return fapi2::FAPI2_RC_SUCCESS;
}

FAPI_TRY( ddr4::set_command_space(i_target, ddr4::command::ZQCL, io_inst) );

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Setup and execute DRAM ZQCL
/// Specializaton for TARGET_TYPE_MCA
/// @param[in] i_target the target associated with this cal
/// @param[in] i_cal_steps_enabled fapi2::buffer<uint16_t> representing the cal steps to enable
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template<>
fapi2::ReturnCode setup_and_execute_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
const fapi2::buffer<uint32_t>& i_cal_steps_enabled)
{
mss::ccs::program<TARGET_TYPE_MCBIST> l_program;

for ( const auto& d : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) )
{
// If this bit isn't set, nothing to do here...
if ( i_cal_steps_enabled.getBit<DRAM_ZQCAL>() )
{
std::vector<uint64_t> l_ranks;
FAPI_TRY( mss::rank::ranks(d, l_ranks) );

for( const auto& r : l_ranks)
{
FAPI_TRY( mss::setup_dram_zqcal(d, r, l_program.iv_instructions) );
}// ranks
}

// If this bit isn't set, nothing to do here...
if ( i_cal_steps_enabled.getBit<DB_ZQCAL>() )
{
FAPI_TRY( mss::setup_data_buffer_zqcal(d, l_program.iv_instructions) );
}
}// dimm

// execute ZQCAL instructions
FAPI_TRY( mss::ccs::execute(mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_program, i_target) );

fapi_try_exit:
return fapi2::current_err;
}

} // ns mss
61 changes: 61 additions & 0 deletions src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/zqcal.H
Expand Up @@ -22,3 +22,64 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */

///
/// @file zqcal.H
/// @brief Subroutines to send ZQCL commands
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#ifndef _MSS_ZQCAL_H_
#define _MSS_ZQCAL_H_

#include <vector>
#include <fapi2.H>
#include <lib/ccs/ccs.H>

namespace mss
{

///
/// @brief Setup DRAM ZQCL
/// @tparam T the target type associated with this cal
/// @tparam TT the target type of the CCS instruction
/// @param[in] i_target the target associated with this cal
/// @param[in] i_rank the current rank
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template< fapi2::TargetType T, fapi2::TargetType TT >
fapi2::ReturnCode setup_dram_zqcal( const fapi2::Target<T>& i_target,
const uint64_t i_rank,
std::vector< ccs::instruction_t<TT> >& io_inst);

///
/// @brief Setup LRDIMM data buffer ZQCL
/// @tparam T the target type associated with this cal
/// @tparam TT the target type of the CCS instruction
/// @param[in] i_target the target associated with this cal
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template< fapi2::TargetType T, fapi2::TargetType TT >
fapi2::ReturnCode setup_data_buffer_zqcal( const fapi2::Target<T>& i_target,
std::vector< ccs::instruction_t<TT> >& io_inst);

///
/// @brief Setup and execute DRAM ZQCL
/// @tparam T, the target type associated with this cal
/// @param[in] i_target the target associated with this cal
/// @param[in] i_cal_steps_enabled fapi2::buffer<uint16_t> representing the cal steps to enable
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template< fapi2::TargetType T >
fapi2::ReturnCode setup_and_execute_zqcal( const fapi2::Target<T>& i_target,
const fapi2::buffer<uint32_t>& i_cal_steps_enabled);

}// mss

#endif
29 changes: 16 additions & 13 deletions src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C
Expand Up @@ -4574,20 +4574,17 @@ fapi_try_exit:
///
fapi2::ReturnCode eff_dimm::cal_step_enable()
{
// These constexpr values are taken from the defiitions in ATTR_MSS_CAL_STEP_ENABLE
// RD/WR VREF correspond to 0x0400 and 0x0100 respectively.
constexpr uint64_t ONLY_1D = 0xFAC0;
constexpr uint64_t RD_VREF_WR_VREF_1D = 0xFFC0;
const uint16_t l_cal_step_value = (mss::chip_ec_feature_skip_hw_vref_cal(iv_mcs) ? ONLY_1D : RD_VREF_WR_VREF_1D);
const uint32_t l_cal_step_value = (mss::chip_ec_feature_skip_hw_vref_cal(iv_mcs) ?
RUN_CAL_SKIP_WR_RD_2D_VREF : RUN_ALL_CAL_STEPS);

FAPI_DBG("%s %s running HW VREF cal. cal_step value: 0x%0x VREF", mss::c_str(iv_mcs),
mss::chip_ec_feature_skip_hw_vref_cal(iv_mcs) ? "not" : "", l_cal_step_value);

// Sets up the vector
std::vector<uint16_t> l_cal_step(PORTS_PER_MCS, l_cal_step_value);
std::vector<uint32_t> l_cal_step(PORTS_PER_MCS, l_cal_step_value);

// Sets the values
return FAPI_ATTR_SET(fapi2::ATTR_MSS_CAL_STEP_ENABLE, iv_mcs, UINT16_VECTOR_TO_1D_ARRAY(l_cal_step, PORTS_PER_MCS));
// Sets the value
return FAPI_ATTR_SET(fapi2::ATTR_MSS_CAL_STEP_ENABLE, iv_mcs, UINT32_VECTOR_TO_1D_ARRAY(l_cal_step, PORTS_PER_MCS));
}

///
Expand All @@ -4597,8 +4594,9 @@ fapi2::ReturnCode eff_dimm::cal_step_enable()
fapi2::ReturnCode eff_dimm::rdvref_enable_bit()
{
// This enables which bits should be run for RD VREF, all 1's indicates that all bits should be run
constexpr uint64_t DISABLE = 0x0000;
constexpr uint64_t ENABLE = 0xFFFF;
constexpr uint16_t DISABLE = 0x0000;
constexpr uint16_t ENABLE = 0xFFFF;

const uint16_t l_vref_enable_value = (mss::chip_ec_feature_skip_hw_vref_cal(iv_mcs) ? DISABLE : ENABLE);

FAPI_DBG("%s %s running HW VREF cal. VREF enable value: 0x%0x", mss::c_str(iv_mcs),
Expand All @@ -4608,16 +4606,21 @@ fapi2::ReturnCode eff_dimm::rdvref_enable_bit()
std::vector<uint16_t> l_vref_enable(PORTS_PER_MCS, l_vref_enable_value);

// Sets the values
return FAPI_ATTR_SET(fapi2::ATTR_MSS_RDVREF_CAL_ENABLE, iv_mcs, UINT16_VECTOR_TO_1D_ARRAY(l_vref_enable,
PORTS_PER_MCS));
return FAPI_ATTR_SET(fapi2::ATTR_MSS_RDVREF_CAL_ENABLE,
iv_mcs,
UINT16_VECTOR_TO_1D_ARRAY(l_vref_enable, PORTS_PER_MCS));
}

///
/// @brief Determines and sets ATTR_MSS_PHY_SEQ_REFRESH_
/// @brief Determines and sets ATTR_MSS_PHY_SEQ_REFRESH
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
fapi2::ReturnCode eff_dimm::phy_seq_refresh()
{
// default setting is to turn on this workaround, this
// isn't an ec_chip_feature attribute because there is no
// known fix for this coming in DD2.0 modules. But the
// lab wants a control switch
constexpr size_t ENABLE = 1;

FAPI_DBG("Setting PHY_SEQ_REFRESH to %d on %s", ENABLE, mss::c_str(iv_mcs));
Expand Down

0 comments on commit c00a806

Please sign in to comment.