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