diff options
author | Stephen Glancy <sglancy@us.ibm.com> | 2019-03-01 14:27:34 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2019-04-10 13:50:37 -0500 |
commit | d27962f1bfbd74cde2eb3e643579e11db7ea77b5 (patch) | |
tree | ddf7944259576769fed238fa765fe777620b0722 /src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C | |
parent | 8d531bced31e0dd68706db205b586c1e9e34b336 (diff) | |
download | talos-hostboot-d27962f1bfbd74cde2eb3e643579e11db7ea77b5.tar.gz talos-hostboot-d27962f1bfbd74cde2eb3e643579e11db7ea77b5.zip |
Updates CCS to run with quad encoded chip select
Change-Id: I29566f1a77d244fa7cbd600e7a83da9784a66f51
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72720
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>
Dev-Ready: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72928
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Tested-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C')
-rw-r--r-- | src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C | 192 |
1 files changed, 126 insertions, 66 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C index 2c937cd11..89e4be5ee 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2018 */ +/* Contributors Listed Below - COPYRIGHT 2015,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -50,6 +50,57 @@ namespace ccs { /// +/// @brief Determines our rank configuration type across all ports +/// @param[in] i_target the MCBIST target on which to operate +/// @param[out] o_rank_config the rank configuration +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode get_rank_config(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, + std::vector<rank_configuration>& o_rank_config) +{ + o_rank_config.clear(); + // Create one per port, we then use relative indexing to get us the number we need + o_rank_config = std::vector<rank_configuration>(PORTS_PER_MCBIST); + + for(const auto& l_mca : mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target)) + { + rank_configuration l_config; + FAPI_TRY(get_rank_config(l_mca, l_config)); + o_rank_config[mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(l_mca)] = l_config; + } + + return fapi2::FAPI2_RC_SUCCESS; +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines our rank configuration type +/// @param[in] i_target the MCA target on which to operate +/// @param[out] o_rank_config the rank configuration +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode get_rank_config(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + rank_configuration& o_rank_config) +{ + constexpr uint8_t QUAD_RANK_ENABLE = 4; + o_rank_config = rank_configuration::DUAL_DIRECT; + + uint8_t l_num_master_ranks[MAX_DIMM_PER_PORT] = {}; + FAPI_TRY(mss::eff_num_master_ranks_per_dimm(i_target, l_num_master_ranks)); + + // We only need to check DIMM0 + // Our number of ranks should be the same between DIMM's 0/1 + // Check if we have the right number for encoded mode + o_rank_config = l_num_master_ranks[0] == QUAD_RANK_ENABLE ? + rank_configuration::QUAD_ENCODED : + rank_configuration::DUAL_DIRECT; + +fapi_try_exit: + return fapi2::current_err; +} + +/// /// @brief Start or stop the CCS engine /// @param[in] i_target The MCBIST containing the CCS engine /// @param[in] i_start_stop bool MSS_CCS_START for starting, MSS_CCS_STOP otherwise @@ -189,6 +240,9 @@ fapi2::ReturnCode execute( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, auto l_inst_iter = i_program.iv_instructions.begin(); + std::vector<rank_configuration> l_rank_configs; + FAPI_TRY(get_rank_config(i_target, l_rank_configs)); + // Stop the CCS engine just for giggles - it might be running ... FAPI_TRY( start_stop(i_target, mss::states::STOP), "Error in ccs::execute" ); @@ -202,75 +256,81 @@ fapi2::ReturnCode execute( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, while (l_inst_iter != i_program.iv_instructions.end()) { - size_t l_inst_count = 0; - - uint64_t l_total_delay = 0; - uint64_t l_delay = 0; - uint64_t l_repeat = 0; - uint8_t l_current_cke = 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) - { - l_inst_iter->arr0.extractToRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(l_current_cke); - - // Make sure this instruction leads to the next. Notice this limits this mechanism to pretty - // simple (straight line) CCS programs. Anything with a loop or such will need another mechanism. - 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::execute" ); - FAPI_TRY( mss::putScom(i_target, CCS_ARR1_ZERO + l_inst_count, l_inst_iter->arr1), "Error in ccs::execute" ); - - // arr1 contains a specification of the delay and repeat after this instruction, as well - // as a repeat. Total up the delays as we go so we know how long to wait before polling - // the CCS engine for completion - l_inst_iter->arr1.extractToRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(l_delay); - l_inst_iter->arr1.extractToRight<MCBIST_CCS_INST_ARR1_00_REPEAT_CMD_CNT, - MCBIST_CCS_INST_ARR1_00_REPEAT_CMD_CNT>(l_repeat); - - l_total_delay += l_delay * (l_repeat + 1); - - FAPI_INF("css inst %d: 0x%016lX 0x%016lX (0x%lx, 0x%lx) delay: 0x%x (0x%x) %s", - l_inst_count, l_inst_iter->arr0, l_inst_iter->arr1, - CCS_ARR0_ZERO + l_inst_count, CCS_ARR1_ZERO + l_inst_count, - l_delay, l_total_delay, mss::c_str(i_target)); - } - - // Check our program for any delays. If there isn't a iv_initial_delay configured, then - // we use the delay we just summed from the instructions. - if (i_program.iv_poll.iv_initial_delay == 0) - { - i_program.iv_poll.iv_initial_delay = cycles_to_ns(i_target, l_total_delay); - } - - if (i_program.iv_poll.iv_initial_sim_delay == 0) - { - i_program.iv_poll.iv_initial_sim_delay = cycles_to_simcycles(l_total_delay); - } - - FAPI_INF("executing ccs instructions (%d:%d, %d) for %s", - i_program.iv_instructions.size(), l_inst_count, i_program.iv_poll.iv_initial_delay, mss::c_str(i_target)); - - // Deselect - l_des.arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(l_current_cke); - - // Insert a DES as our last instruction. DES is idle state anyway and having this - // here as an instruction forces the CCS engine to wait the delay specified in - // the last instruction in this array (which it otherwise doesn't do.) - l_des.arr1.setBit<MCBIST_CCS_INST_ARR1_00_END>(); - FAPI_TRY( mss::putScom(i_target, CCS_ARR0_ZERO + l_inst_count, l_des.arr0), "Error in ccs::execute" ); - FAPI_TRY( mss::putScom(i_target, CCS_ARR1_ZERO + l_inst_count, l_des.arr1), "Error in ccs::execute" ); - - FAPI_INF("css inst %d fixup: 0x%016lX 0x%016lX (0x%lx, 0x%lx) %s", - l_inst_count, l_des.arr0, l_des.arr1, - CCS_ARR0_ZERO + l_inst_count, CCS_ARR1_ZERO + l_inst_count, mss::c_str(i_target)); // Kick off the CCS engine - per port. No broadcast mode for CCS (per Shelton 9/23/15) for (const auto& p : i_ports) { - FAPI_INF("executing CCS array for port %d (%s)", mss::relative_pos<TARGET_TYPE_MCBIST>(p), mss::c_str(p)); - FAPI_TRY( select_ports( i_target, mss::relative_pos<TARGET_TYPE_MCBIST>(p)), "Error in ccs execute" ); + const auto l_port_index = mss::relative_pos<TARGET_TYPE_MCBIST>(p); + size_t l_inst_count = 0; + + uint64_t l_total_delay = 0; + uint64_t l_delay = 0; + uint64_t l_repeat = 0; + uint8_t l_current_cke = 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) + { + // First, update the current instruction's chip selects for the current port + FAPI_TRY(l_inst_iter->configure_rank(p, l_rank_configs[l_port_index]), "Error in rank config"); + + l_inst_iter->arr0.extractToRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(l_current_cke); + + // Make sure this instruction leads to the next. Notice this limits this mechanism to pretty + // simple (straight line) CCS programs. Anything with a loop or such will need another mechanism. + 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::execute" ); + FAPI_TRY( mss::putScom(i_target, CCS_ARR1_ZERO + l_inst_count, l_inst_iter->arr1), "Error in ccs::execute" ); + + // arr1 contains a specification of the delay and repeat after this instruction, as well + // as a repeat. Total up the delays as we go so we know how long to wait before polling + // the CCS engine for completion + l_inst_iter->arr1.extractToRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(l_delay); + l_inst_iter->arr1.extractToRight<MCBIST_CCS_INST_ARR1_00_REPEAT_CMD_CNT, + MCBIST_CCS_INST_ARR1_00_REPEAT_CMD_CNT>(l_repeat); + + l_total_delay += l_delay * (l_repeat + 1); + + FAPI_INF("css inst %d: 0x%016lX 0x%016lX (0x%lx, 0x%lx) delay: 0x%x (0x%x) %s", + l_inst_count, l_inst_iter->arr0, l_inst_iter->arr1, + CCS_ARR0_ZERO + l_inst_count, CCS_ARR1_ZERO + l_inst_count, + l_delay, l_total_delay, mss::c_str(i_target)); + } + + // Check our program for any delays. If there isn't a iv_initial_delay configured, then + // we use the delay we just summed from the instructions. + if (i_program.iv_poll.iv_initial_delay == 0) + { + i_program.iv_poll.iv_initial_delay = cycles_to_ns(i_target, l_total_delay); + } + + if (i_program.iv_poll.iv_initial_sim_delay == 0) + { + i_program.iv_poll.iv_initial_sim_delay = cycles_to_simcycles(l_total_delay); + } + + FAPI_INF("executing ccs instructions (%d:%d, %d) for %s", + i_program.iv_instructions.size(), l_inst_count, i_program.iv_poll.iv_initial_delay, mss::c_str(i_target)); + + // Deselect + l_des.arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(l_current_cke); + + // Insert a DES as our last instruction. DES is idle state anyway and having this + // here as an instruction forces the CCS engine to wait the delay specified in + // the last instruction in this array (which it otherwise doesn't do.) + l_des.arr1.setBit<MCBIST_CCS_INST_ARR1_00_END>(); + FAPI_TRY( mss::putScom(i_target, CCS_ARR0_ZERO + l_inst_count, l_des.arr0), "Error in ccs::execute" ); + FAPI_TRY( mss::putScom(i_target, CCS_ARR1_ZERO + l_inst_count, l_des.arr1), "Error in ccs::execute" ); + + FAPI_INF("css inst %d fixup: 0x%016lX 0x%016lX (0x%lx, 0x%lx) %s", + l_inst_count, l_des.arr0, l_des.arr1, + CCS_ARR0_ZERO + l_inst_count, CCS_ARR1_ZERO + l_inst_count, mss::c_str(i_target)); + + + FAPI_INF("executing CCS array for port %d (%s)", l_port_index, mss::c_str(p)); + FAPI_TRY( select_ports( i_target, l_port_index), "Error in ccs execute" ); FAPI_TRY( execute_inst_array(i_target, i_program, p), "Error in ccs execute" ); } } |