summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp
diff options
context:
space:
mode:
authorTsung Yeung <tyeung@us.ibm.com>2019-03-22 09:43:38 -0400
committerChristian R. Geddes <crgeddes@us.ibm.com>2019-04-04 09:35:17 -0500
commit9ab1bc28a6d2b703cab2d36985e17601d85b0c20 (patch)
treee385e653759c55e2f89d481bee0d981754a960b7 /src/import/chips/p9/procedures/hwp
parent0c1d170c7552632462a0986ebfc64e21f7b36039 (diff)
downloadtalos-hostboot-9ab1bc28a6d2b703cab2d36985e17601d85b0c20.tar.gz
talos-hostboot-9ab1bc28a6d2b703cab2d36985e17601d85b0c20.zip
Preload CCS program to support EPOW on NVDIMM
This is written specifically for NVDIMM on P9 Nimbus. The current recipe relies on the MC sequencer to enter STR in the event of EPOW and could be delayed depending on the status of the bus. CCS will ensure the immediate entry of the STR and the order of execution (STR -> assert RESETn) Change-Id: Ic117b489582aaf92810e905f43fe2e4e0408eeeb CQ:SW458983 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/74969 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@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: Louis Stermole <stermole@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/75019 Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H7
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C69
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.H9
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C79
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H12
5 files changed, 173 insertions, 3 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H
index 6de8554b9..0d0434bc1 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H
@@ -521,13 +521,14 @@ inline instruction_t<T> mrs_command( const fapi2::Target<fapi2::TARGET_TYPE_DIMM
/// @brief Create, initialize a JEDEC Device Deselect CCS command
/// @tparam T the target type of the chiplet which executes the CCS instruction
/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_idle the idle time to the next command (default to 0)
/// @return the Device Deselect CCS instruction
/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
/// in this template definition)
///
template< fapi2::TargetType T, typename TT = ccsTraits<T> >
-inline instruction_t<T> des_command()
+inline instruction_t<T> des_command(const uint16_t i_idle = 0)
{
fapi2::buffer<uint64_t> rcd_boilerplate_arr0;
fapi2::buffer<uint64_t> rcd_boilerplate_arr1;
@@ -539,6 +540,9 @@ inline instruction_t<T> des_command()
// CKE is high Note: P8 set all 4 of these high - not sure if that's correct. BRS
rcd_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_HIGH);
+ // Insert idle
+ rcd_boilerplate_arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>( i_idle );
+
// ACT is high no-care
// RAS, CAS, WE no-care
@@ -679,6 +683,7 @@ inline instruction_t<T> initial_cal_command(const uint64_t i_rp)
/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
/// @param[in] i_target the DIMM this instruction is headed for
/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_idle the idle time to the next command (default to 0)
/// @return the MRS CCS instruction
/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C
index d2ddaf136..ed63071d5 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C
@@ -651,6 +651,75 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief Preload the CCS with the EPOW sequence
+/// @param[in] i_target the target associated with this subroutine
+/// @return FAPI2_RC_SUCCESS iff setup was successful
+/// @note This is written specifically to support EPOW on NVDIMM and
+/// should only be called after all the draminit.
+///
+fapi2::ReturnCode preload_epow_sequence( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target )
+{
+ typedef ccsTraits<fapi2::TARGET_TYPE_MCBIST> TT;
+ const auto& l_mcbist = mss::find_target<TARGET_TYPE_MCBIST>(i_target);
+ const auto& l_dimms = mss::find_targets<TARGET_TYPE_DIMM>(i_target);
+ constexpr uint64_t CS_N_ACTIVE = 0b00;
+ uint8_t l_trp = 0;
+ uint16_t l_trfc = 0;
+ std::vector<uint64_t> l_ranks;
+ ccs::program<TARGET_TYPE_MCBIST> l_program;
+ ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst;
+
+ // Get tRP and tRFC
+ FAPI_TRY(mss::eff_dram_trp(i_target, l_trp));
+ FAPI_TRY(mss::eff_dram_trfc(i_target, l_trfc));
+
+ l_program.iv_poll.iv_initial_delay = 0;
+ l_program.iv_poll.iv_initial_sim_delay = 0;
+
+ // Start the program with DES and wait for tRFC
+ // All CKE = high, all CSn = high, Reset_n = high, wait tRFC
+ l_inst = ccs::des_command<TARGET_TYPE_MCBIST>(l_trfc);
+ l_inst.arr0.setBit<TT::ARR0_DDR_RESETN>();
+ FAPI_INF("des_command() arr0 = 0x%016lx , arr1 = 0x%016lx", l_inst.arr0, l_inst.arr1);
+ l_program.iv_instructions.push_back(l_inst);
+
+ // Precharge all command
+ // All CKE = high, all CSn = low, Reset_n = high, wait tRP
+ l_inst = ccs::precharge_all_command<TARGET_TYPE_MCBIST>(l_dimms[0], 0, l_trp);
+ l_inst.arr0.insertFromRight<TT::ARR0_DDR_CSN_0_1, TT::ARR0_DDR_CSN_0_1_LEN>(CS_N_ACTIVE);
+ l_inst.arr0.insertFromRight<TT::ARR0_DDR_CSN_2_3, TT::ARR0_DDR_CSN_2_3_LEN>(CS_N_ACTIVE);
+ l_inst.arr0.setBit<TT::ARR0_DDR_RESETN>();
+ FAPI_INF("precharge_all_command() arr0 = 0x%016lx , arr1 = 0x%016lx", l_inst.arr0, l_inst.arr1);
+ l_program.iv_instructions.push_back(l_inst);
+
+ // Self-refresh entry command
+ // All CKE = low, all CSn = low, Reset_n = high, wait tCKSRE
+ l_inst = ccs::self_refresh_entry_command<TARGET_TYPE_MCBIST>(l_dimms[0], 0, mss::tcksre(l_dimms[0]));
+ l_inst.arr0.insertFromRight<TT::ARR0_DDR_CSN_0_1, TT::ARR0_DDR_CSN_0_1_LEN>(CS_N_ACTIVE);
+ l_inst.arr0.insertFromRight<TT::ARR0_DDR_CSN_2_3, TT::ARR0_DDR_CSN_2_3_LEN>(CS_N_ACTIVE);
+ l_inst.arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(mss::CKE_LOW);
+ l_inst.arr0.setBit<TT::ARR0_DDR_RESETN>();
+ FAPI_INF("self_refresh_entry_command() arr0 = 0x%016lx , arr1 = 0x%016lx", l_inst.arr0, l_inst.arr1);
+ l_program.iv_instructions.push_back(l_inst);
+
+ // Push in an empty instruction for RESETn
+ // All CKE = low, all CSn = high (default), Reset_n = low
+ l_inst = ccs::instruction_t<TARGET_TYPE_MCBIST>(l_dimms[0]);
+ FAPI_INF("Assert RESETn arr0 = 0x%016lx , arr1 = 0x%016lx", l_inst.arr0, l_inst.arr1);
+ l_program.iv_instructions.push_back(l_inst);
+
+ // Load the program
+ FAPI_TRY( mss::ccs::workarounds::preload_ccs_for_epow(l_mcbist, l_program),
+ "Failed to preload the ccs for epow %s", mss::c_str(i_target) );
+
+ // The actual execution of this program will be trigger by EPOW. When EPOW occurs,
+ // OCC will change the mux and hit the go button to execute CCS
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
}//ns nvdimm
}//ns mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.H
index fe58fae31..538a650ba 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.H
@@ -171,6 +171,15 @@ fapi2::ReturnCode post_restore_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_MCA
template< fapi2::TargetType T >
fapi2::ReturnCode post_restore_transition( const fapi2::Target<T>& i_target );
+///
+/// @brief Preload the CCS with the EPOW sequence
+/// @param[in] i_target the target associated with this subroutine
+/// @return FAPI2_RC_SUCCESS iff setup was successful
+/// @note This is written specifically to support EPOW on NVDIMM and
+/// should only be called after all the draminit.
+///
+fapi2::ReturnCode preload_epow_sequence( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target );
+
}//ns nvdimm
}//ns mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C
index e7ceb2b0b..42374919c 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2017,2018 */
+/* Contributors Listed Below - COPYRIGHT 2017,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -136,6 +136,83 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief Preload the CCS program for epow
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the vector of instructions
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note This is written specifically to support EPOW on NVDIMM
+/// This function loads the input program to the CCS arrays
+/// without execute as opposed to ccs::execute(). The actual
+/// ccs program execution will be handled by OCC
+///
+fapi2::ReturnCode preload_ccs_for_epow( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+ ccs::program<fapi2::TARGET_TYPE_MCBIST>& i_program)
+{
+ typedef ccsTraits<fapi2::TARGET_TYPE_MCBIST> TT;
+
+ // Subtract one for the idle we insert at the end
+ constexpr size_t CCS_INSTRUCTION_DEPTH = 32 - 1;
+ constexpr uint64_t CCS_ARR0_ZERO = MCBIST_CCS_INST_ARR0_00;
+ constexpr uint64_t CCS_ARR1_ZERO = MCBIST_CCS_INST_ARR1_00;
+
+ FAPI_INF("loading ccs instructions (%d) for epow on %s", i_program.iv_instructions.size(), mss::c_str(i_target));
+
+ auto l_inst_iter = i_program.iv_instructions.begin();
+
+ // Stop the CCS engine just for giggles - it might be running ...
+ FAPI_TRY( start_stop(i_target, mss::states::STOP), "Error in ccs::workarounds::preload_ccs_for_epow" );
+
+ FAPI_ASSERT( mss::poll(i_target, TT::STATQ_REG, poll_parameters(),
+ [](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_INF("ccs statq (stop) 0x%llx, remaining: %d", stat_reg, poll_remaining);
+ return stat_reg.getBit<TT::CCS_IN_PROGRESS>() != 1;
+ }),
+ fapi2::MSS_CCS_HUNG_TRYING_TO_STOP().set_MCBIST_TARGET(i_target) );
+
+ while (l_inst_iter != i_program.iv_instructions.end())
+ {
+ size_t l_inst_count = 0;
+
+ // Shove the instructions into the CCS engine, in 32 instruction chunks, and execute them
+ for (; l_inst_iter != i_program.iv_instructions.end()
+ && l_inst_count < CCS_INSTRUCTION_DEPTH; ++l_inst_count, ++l_inst_iter)
+ {
+ // If we are on the last instruction we want to stay there. If we exit
+ // the sequencer could take back the control. This is also the reason
+ // we are not adding up the delays here.
+ if (l_inst_iter + 1 == i_program.iv_instructions.end())
+ {
+ l_inst_iter->arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_GOTO_CMD,
+ MCBIST_CCS_INST_ARR1_00_GOTO_CMD_LEN>(l_inst_count);
+ }
+ else
+ {
+ l_inst_iter->arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_GOTO_CMD,
+ MCBIST_CCS_INST_ARR1_00_GOTO_CMD_LEN>(l_inst_count + 1);
+ }
+
+ FAPI_TRY( mss::putScom(i_target, CCS_ARR0_ZERO + l_inst_count, l_inst_iter->arr0),
+ "Error in ccs::workarounds::preload_ccs_for_epow" );
+ FAPI_TRY( mss::putScom(i_target, CCS_ARR1_ZERO + l_inst_count, l_inst_iter->arr1),
+ "Error in ccs::workarounds::preload_ccs_for_epow" );
+
+ FAPI_INF("css inst %d: 0x%016lX 0x%016lX (0x%lx, 0x%lx)",
+ l_inst_count, l_inst_iter->arr0, l_inst_iter->arr1,
+ CCS_ARR0_ZERO + l_inst_count, CCS_ARR1_ZERO + l_inst_count,
+ mss::c_str(i_target));
+ }
+ }
+
+ // No need to set the ports here. This will be done by OCC before poking the start bit
+
+fapi_try_exit:
+ i_program.iv_instructions.clear();
+ return fapi2::current_err;
+}
+
+
namespace wr_lvl
{
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H
index eb496f383..60c7ef23d 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2017,2018 */
+/* Contributors Listed Below - COPYRIGHT 2017,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -147,6 +147,16 @@ inline void hold_cke_high( ccs::program<fapi2::TARGET_TYPE_MCBIST>& io_program )
}
}
+///
+/// @brief Preload the CCS program for epow
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the vector of instructions
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note This is written specifically to support EPOW on NVDIMM
+///
+fapi2::ReturnCode preload_ccs_for_epow( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+ ccs::program<fapi2::TARGET_TYPE_MCBIST>& i_program);
+
namespace wr_lvl
{
OpenPOWER on IntegriCloud