Skip to content

Commit

Permalink
Fix tWLDQSEN and IPW_WR_WR timing parameters for MSS training
Browse files Browse the repository at this point in the history
Change-Id: Iee425c7c404720275f3789436c698892e39842c2
CQ: SW407830
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/49352
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Dev-Ready: Louis Stermole <stermole@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/49358
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
  • Loading branch information
stermole authored and crgeddes committed Nov 21, 2017
1 parent dc276ea commit d7750b7
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 13 deletions.
53 changes: 42 additions & 11 deletions src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H
Expand Up @@ -393,16 +393,6 @@ constexpr uint64_t tzqcs()
return 128;
}

///
/// @brief DQS_t/DQS_n delay after write leveling mode is programmed
/// @return constexpr value of 25 clocks
///
constexpr uint64_t twldqsen()
{
// Per DDR4 Full spec update (79-4A) - timing requirements
return 25;
}

///
/// @brief First DQS_t/DQS_n rising edge after write leveling mode is programmed
/// @return constexpr value of 40 clocks
Expand Down Expand Up @@ -436,6 +426,45 @@ inline uint64_t tmod( const fapi2::Target<T>& i_target )
return mss::max_ck_ns( i_target, 24, 15 );
}

///
/// @brief RTT change skew
/// @return constexpr value of 1 clock
///
constexpr uint8_t tadc()
{
// Per DDR4 spec, this value is between 0.3 and 0.7, so round up to 1 clk
return 1;
}

///
/// @brief DQS_t/DQS_n delay after write leveling mode is programmed
/// @tparam T fapi2::TargetType of the target used to calculate cycles from ns
/// @param[in] i_target the target used to get tMOD clocks
/// @param[out] o_twldqsen *in clocks*
/// @return FAPI2_RC_SUCCESS iff ok
///
template< fapi2::TargetType T >
inline fapi2::ReturnCode twldqsen( const fapi2::Target<T>& i_target, uint8_t& o_twldqsen )
{
const uint8_t l_tadc = tadc();
const auto l_tmod = tmod(i_target);
uint8_t l_ca_parity_latency = 0;
uint8_t l_al = 0;
uint8_t l_cwl = 0;

FAPI_TRY( mss::eff_ca_parity_latency(i_target, l_ca_parity_latency) );
FAPI_TRY( mss::eff_dram_al(i_target, l_al) );
FAPI_TRY( mss::eff_dram_cwl(i_target, l_cwl) );

// tWLDQSEN >= tMOD + WL + tADC
// WL = CWL + AL + PL
o_twldqsen = l_tmod + l_cwl + l_al + l_ca_parity_latency + l_tadc;
FAPI_INF("twldqsen %d for %s", o_twldqsen, mss::c_str(i_target));

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Calculate TWLO_TWLOE
/// @tparam T fapi2::TargetType of the target used to calculate cycles from ns
Expand All @@ -454,12 +483,14 @@ inline uint64_t twlo_twloe(const fapi2::Target<T>& i_target)
uint8_t l_wlo_ck = 0;
uint64_t l_wloe_ck = mss::ns_to_cycles(i_target, 2);
uint64_t l_twlo_twloe = 0;
uint8_t l_twldqsen = 0;

FAPI_TRY( mss::vpd_mr_dphy_wlo(i_target, l_wlo_ck) );
FAPI_TRY( mss::twldqsen(i_target, l_twldqsen) );

// TODO RTC:160356 This changes if wlo is signed, which it's not but I wonder if it should
// be ... (the PHY register is.) It changes because we need to round up to 0 if needed.
l_twlo_twloe = 12 + std::max( (twldqsen() + tmod(i_target)), (l_wlo_ck + l_wloe_ck) ) + l_dq_ck + l_dqs_ck;
l_twlo_twloe = 12 + std::max( (l_twldqsen + tmod(i_target)), (l_wlo_ck + l_wloe_ck) ) + l_dq_ck + l_dqs_ck;
FAPI_INF("twlo_twloe %d for %s", l_twlo_twloe, mss::c_str(i_target));
return l_twlo_twloe;

Expand Down
10 changes: 8 additions & 2 deletions src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.C
Expand Up @@ -167,12 +167,18 @@ fapi2::ReturnCode reset_timing1( const fapi2::Target<TARGET_TYPE_MCA>& i_target
// TWRMRD_CYCLES tWLMRD

uint64_t l_tzqint = std::max( mss::tzqinit(), mss::tzqoper() );
uint8_t l_twldqsen = 0;
FAPI_TRY( mss::twldqsen(i_target, l_twldqsen), "%s Failed to calculate tWLDQSEN", mss::c_str(i_target) );

l_data.insertFromRight<TT::TZQINIT_CYCLES, TT::TZQINIT_CYCLES_LEN>( exp_helper(l_tzqint) );
l_data.insertFromRight<TT::TZQCS_CYCLES, TT::TZQCS_CYCLES_LEN>( exp_helper(mss::tzqcs()) );
l_data.insertFromRight<TT::TWLDQSEN_CYCLES, TT::TWLDQSEN_CYCLES_LEN>( exp_helper(mss::twldqsen()) );
l_data.insertFromRight<TT::TWLDQSEN_CYCLES, TT::TWLDQSEN_CYCLES_LEN>( exp_helper(l_twldqsen) );
l_data.insertFromRight<TT::TWRMRD_CYCLES, TT::TWRMRD_CYCLES_LEN>( exp_helper(mss::twlmrd()) );

return mss::putScom(i_target, TT::SEQ_TIMING1_REG, l_data);
FAPI_TRY( mss::putScom(i_target, TT::SEQ_TIMING1_REG, l_data) );

fapi_try_exit:
return fapi2::current_err;
}

///
Expand Down
Expand Up @@ -397,10 +397,16 @@ inline fapi2::ReturnCode reset_config2( const fapi2::Target<T>& i_target )
fapi2::buffer<uint64_t> l_data;
uint8_t l_fw_rd_wr = 0;

// Memory clock cycle separation value for write commands during Initial Pattern Write.
// This value needs to be set to 5 to get the desired value of 24 clock cycles.
// (ipw_wr_wr + 1) * 4 = 24
constexpr uint64_t IPW_WR_WR = 5;

FAPI_TRY( mss::fw_rd_wr(i_target, l_fw_rd_wr) );

l_data.insertFromRight<TT::NUM_VALID_SAMPLES, TT::NUM_VALID_SAMPLES_LEN>(WR_LVL_NUM_VALID_SAMPLES);
l_data.insertFromRight<TT::FW_RD_WR, TT::FW_RD_WR_LEN>(l_fw_rd_wr);
l_data.insertFromRight<TT::IPW_WR_WR, TT::IPW_WR_WR_LEN>(IPW_WR_WR);

FAPI_DBG("%s wc_config2 reset 0x%llx", mss::c_str(i_target), l_data);
FAPI_TRY( write_config2(i_target, l_data), "%s failed to reset wc_config2 register via write", mss::c_str(i_target) );
Expand Down

0 comments on commit d7750b7

Please sign in to comment.