From d27962f1bfbd74cde2eb3e643579e11db7ea77b5 Mon Sep 17 00:00:00 2001 From: Stephen Glancy Date: Fri, 1 Mar 2019 14:27:34 -0500 Subject: 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 Tested-by: Jenkins Server Tested-by: HWSV CI Tested-by: Hostboot CI Reviewed-by: Louis Stermole Dev-Ready: STEPHEN GLANCY Reviewed-by: ANDRE A. MARIN Reviewed-by: Jennifer A. Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72928 Reviewed-by: Daniel M. Crowell Tested-by: Daniel M. Crowell --- .../chips/p9/procedures/hwp/memory/lib/ccs/ccs.C | 192 ++++++++----- .../chips/p9/procedures/hwp/memory/lib/ccs/ccs.H | 308 +++++++++++++-------- .../hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H | 6 +- .../hwp/memory/lib/dimm/ddr4/nvdimm_utils.C | 10 +- .../p9/procedures/hwp/memory/lib/dimm/ddr4/zqcal.C | 2 +- .../hwp/memory/lib/phy/mss_lrdimm_training.H | 3 +- .../procedures/hwp/memory/lib/shared/mss_const.H | 3 + .../p9/procedures/hwp/memory/p9_mss_draminit.C | 1 - 8 files changed, 338 insertions(+), 187 deletions(-) (limited to 'src/import/chips/p9/procedures/hwp') 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. */ /* */ /* */ @@ -49,6 +49,57 @@ namespace mss 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& i_target, + std::vector& 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(PORTS_PER_MCBIST); + + for(const auto& l_mca : mss::find_targets(i_target)) + { + rank_configuration l_config; + FAPI_TRY(get_rank_config(l_mca, l_config)); + o_rank_config[mss::relative_pos(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& 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 @@ -189,6 +240,9 @@ fapi2::ReturnCode execute( const fapi2::Target& i_target, auto l_inst_iter = i_program.iv_instructions.begin(); + std::vector 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& 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(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(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(l_delay); - l_inst_iter->arr1.extractToRight(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(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(); - 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(p), mss::c_str(p)); - FAPI_TRY( select_ports( i_target, mss::relative_pos(p)), "Error in ccs execute" ); + const auto l_port_index = mss::relative_pos(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(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(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(l_delay); + l_inst_iter->arr1.extractToRight(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(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(); + 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" ); } } 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 606014ee7..923b84052 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 @@ -70,6 +70,7 @@ class ccsTraits static constexpr uint64_t MCB_CNTL_REG = MCBIST_MCB_CNTLQ; static constexpr uint64_t CNTLQ_REG = MCBIST_CCS_CNTLQ; static constexpr uint64_t STATQ_REG = MCBIST_CCS_STATQ; + static constexpr fapi2::TargetType PORT_TARGET_TYPE = fapi2::TARGET_TYPE_MCA; enum { @@ -216,6 +217,15 @@ static constexpr uint64_t CKE_ARY_SRX[] = namespace ccs { +enum rank_configuration +{ + DUAL_DIRECT = 0, + QUAD_ENCODED = 1, + // Note: we don't include QUAD_DIRECT in here + // That's because it uses 4 CS and is board wiring dependent + // Not sure if it would use CS23 or CID01 for CS2/3 +}; + /// /// @brief Enums for CCS return codes /// @@ -245,98 +255,173 @@ class instruction_t public: fapi2::buffer arr0; fapi2::buffer arr1; + // The MCA indexed rank on which to operate. If this is invalid, all ranks will be disabled + uint64_t iv_rank; + // We want to have a switch to update rank or not. A user might want to setup CS in some weird way + // In that case, they don't want us "fixing" their CS values + // We'll default the rank to be updated - we want to send out CS properly + bool iv_update_rank; /// /// @brief intstruction_t ctor - /// @param[in] i_target the DIMM this instruction is headed for /// @param[in] i_rank the rank this instruction is headed for /// @param[in] i_arr0 the initial value for arr0, defaults to 0 /// @param[in] i_arr1 the initial value for arr1, defaults to 0 + /// @param[in] i_update_rank true if the rank should be updated before being sent, defaults to true /// - instruction_t( const fapi2::Target& i_target = fapi2::Target(), - uint64_t i_rank = NO_CHIP_SELECT_ACTIVE, + instruction_t( uint64_t i_rank = NO_CHIP_SELECT_ACTIVE, const fapi2::buffer i_arr0 = 0, - const fapi2::buffer i_arr1 = 0): + const fapi2::buffer i_arr1 = 0, + const bool i_update_rank = true): arr0(i_arr0), - arr1(i_arr1) + arr1(i_arr1), + iv_rank(i_rank), + iv_update_rank(i_update_rank) { - // For DIMM0 .first is the CSN_0_1 setting, .second is the CSN_2_3 setting. - // For DIMM1 .first is the CSN_2_3 setting, .second is the CSN_0_1 setting. - static const std::pair CS_N[mss::MAX_RANK_PER_DIMM] = + // Skip setting up the rank if hte user doesn't want us to + if(iv_update_rank) { - // CS0 L CS1 H => CS2 => H CS3 => H Rank 0 - { 0b01, 0b11 }, - - // CS0 H CS1 L => CS2 => H CS3 => H Rank 1 - { 0b10, 0b11 }, - - // CS0 H CS1 H => CS2 => L CS3 => H Rank 2 - { 0b11, 0b01 }, + // Set the chip selects to be 1's (not active) + // We'll fix these up before executing the instructions + arr0.insertFromRight(0b11); + arr0.insertFromRight(0b11); + } + } - // CS0 H CS1 H => CS2 => H CS3 => L Rank 3 - { 0b11, 0b10 }, - }; + /// + /// @brief Updates the rank based upon the passed in rank configuration encoding + /// @param[in] i_target the port target for this instruction - for error logging + /// @param[in] i_rank_config the rank configuration + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS if ok + /// + fapi2::ReturnCode configure_rank(const fapi2::Target& i_target, + const rank_configuration i_rank_config ) + { + // If this instrunction is set to not update the rank, then don't update the rank + if(!iv_update_rank) + { + return fapi2::FAPI2_RC_SUCCESS; + } - // If the rank indicates nothing selected (active low) then we're done. - if (i_rank == NO_CHIP_SELECT_ACTIVE) + // Regardless of rank configurations, if we have NO_CHIP_SELECT_ACTIVE, deactivate all CS + if(iv_rank == NO_CHIP_SELECT_ACTIVE) { arr0.insertFromRight(0b11); arr0.insertFromRight(0b11); - return; + return fapi2::FAPI2_RC_SUCCESS; } - // - // Note: This likely needs to be able to handle all DIMM, stacked, encoded CS_n, etc. This - // might not cut it. Turn this in to a dispatched funtion like c_str() and rcd_load() BRS - // + // First, check rank - we need to make sure that we have a valid rank + FAPI_ASSERT(iv_rank < MAX_MRANK_PER_PORT, + fapi2::MSS_INVALID_RANK() + .set_MCA_TARGET(i_target) + .set_RANK(iv_rank) + .set_FUNCTION(ffdc_function_codes::CCS_INST_CONFIGURE_RANK), + "%s rank out of bounds rank%u", mss::c_str(i_target), iv_rank); + + // Now the fun happens and we can deal with the actual encoding - // Direct CS mode - just clear the CS_N you're interested in. - // Setup the chip select based on which dimm in the slot and the rank - if (mss::index(i_target) == 0) + // If we're quad mode, setup the encoding accordingly + if(i_rank_config == rank_configuration::QUAD_ENCODED) { - // Sanity check the incoming rank. It has to be 0-3 since we're DIMM0 - // Assert since this is a programming error - if (i_rank >= MAX_RANK_PER_DIMM) + // CS 0/1 are first, while CID0/1 are second + // In quad enabled mode, CID acts as a "package select" + // It selects R0/2 vs R1/3 + // CS0 vs CS1 selects the low vs high rank in the package + // CS0 will select rank 0/1 + // CS1 will select rank 2/3 + + // Note: this is to workaround a Nimbus CCS bug + // 1) Nimbus thinks that CID0 is a CID not part of the CS for encoded mode + // 2) CID1 doesn't matter for quad encode + // 3) we only access ranks 2,3 in encoded mode + // 4) we can fake out parity by adding in another 1, so let's do that with CID1 + // This is easier than calculating our own parity + // CS0 H, CS1 L, CID0-> L => Rank 2 + + static const std::pair CS_N[mss::MAX_RANK_PER_DIMM] = { - FAPI_ERR("DIMM0 %s CCS instruction looking for bad rank/chip select (%d)", - mss::c_str(i_target), i_rank); - fapi2::Assert(false); - // Not reached but fapi2::Assert isn't [[no return]] so the compiler thinks we're going - // to run off the array but we're not so this makes the compiler happy. - return; - } + // CS0 L, CS1 H, CID0-> L => Rank 0 + { 0b01, 0b00 }, + + // CS0 L, CS1 H, CID0-> H => Rank 1 + { 0b01, 0b11 }, + + // CS0 H, CS1 L, CID0-> L => Rank 2 + { 0b10, 0b00 }, + + // CS0 H, CS1 L, CID0-> H => Rank 3 + { 0b10, 0b11 }, + }; + const auto l_dimm_rank = mss::index(iv_rank); + const bool l_is_dimm0 = iv_rank < MAX_RANK_PER_DIMM; + constexpr uint64_t NON_DIMM_CS = 0b11; + + // Assigns the CS based upon which DIMM we're at + const auto CS01 = l_is_dimm0 ? CS_N[l_dimm_rank].first : NON_DIMM_CS; + const auto CS23 = l_is_dimm0 ? NON_DIMM_CS : CS_N[l_dimm_rank].first; + + // Setup that rank arr0.insertFromRight(CS_N[i_rank].first); + TT::ARR0_DDR_CSN_0_1_LEN>(CS01); arr0.insertFromRight(CS_N[i_rank].second); + TT::ARR0_DDR_CSN_2_3_LEN>(CS23); + arr0.insertFromRight(CS_N[l_dimm_rank].second); } + + // Otherwise, setup for dual-direct mode (our only other supported mode at the moment) else { - // DIMM1's ranks are {4,5,6,7} so we subract the mid-point rank to normalize i_rank for DIMM1 - const uint64_t l_effective_rank = i_rank - RANK_MID_POINT; - - // Sanity check that we don't have more than 2 ranks on DIMM1. Effective Config - // should have caught this with the plug rules, but we will select the rank in the - // wrong DIMM with this CCS instruction if we blew it, so lets check ... We can assert - // our way out of this as this is a code bug in Effective Config, so they should have - // reported a real error long ago ... - if (l_effective_rank >= MAX_RANKS_DIMM1) + // For DIMM0 .first is the CSN_0_1 setting, .second is the CSN_2_3 setting. + // For DIMM1 .first is the CSN_2_3 setting, .second is the CSN_0_1 setting. + static const std::pair CS_N[mss::MAX_RANK_PER_DIMM] = { - FAPI_ERR("DIMM1 %s CCS instruction looking for bad rank/chip select (%d, %d)", - mss::c_str(i_target), i_rank, l_effective_rank); - fapi2::Assert(false); - // Not reached but fapi2::Assert isn't [[no return]] so the compiler thinks we're going - // to run off the array but we're not so this makes the compiler happy. - return; - } - - // Deselect ranks on DIMM1 + // CS0 L CS1 H => CS2 => H CS3 => H Rank 0 + { 0b01, 0b11 }, + + // CS0 H CS1 L => CS2 => H CS3 => H Rank 1 + { 0b10, 0b11 }, + + // CS0 H CS1 H => CS2 => L CS3 => H Rank 2 + { 0b11, 0b01 }, + + // CS0 H CS1 H => CS2 => H CS3 => L Rank 3 + { 0b11, 0b10 }, + }; + + const auto l_dimm_rank = mss::index(iv_rank); + const bool l_is_dimm0 = iv_rank < MAX_RANK_PER_DIMM; + + // Assigns the CS based upon which DIMM we're at + const auto CS01 = l_is_dimm0 ? CS_N[l_dimm_rank].first : CS_N[l_dimm_rank].second; + const auto CS23 = l_is_dimm0 ? CS_N[l_dimm_rank].second : CS_N[l_dimm_rank].first; + + // Setup that rank arr0.insertFromRight(CS_N[l_effective_rank].second); + TT::ARR0_DDR_CSN_0_1_LEN>(CS01); arr0.insertFromRight(CS_N[l_effective_rank].first); + TT::ARR0_DDR_CSN_2_3_LEN>(CS23); + + // Check that we don't have a rank out of bounds case here + // We can only have that if + // 1) we are DIMM1 + // 2) our DIMM rank is greater than the maximum allowed number of ranks on DIMM1 + // So, we pass always if we're DIMM0, or if our DIMM rank is less than the maximum number of DIMM's on rank 1 + FAPI_ASSERT(l_dimm_rank < MAX_RANKS_DIMM1 || l_is_dimm0, + fapi2::MSS_INVALID_RANK() + .set_MCA_TARGET(i_target) + .set_RANK(iv_rank) + .set_FUNCTION(ffdc_function_codes::CCS_INST_CONFIGURE_RANK), + "%s rank out of bounds rank%u", mss::c_str(i_target), iv_rank); } + + return fapi2::FAPI2_RC_SUCCESS; + fapi_try_exit: + return fapi2::current_err; } /// @@ -347,10 +432,30 @@ class instruction_t inline bool operator==( const instruction_t& i_rhs ) const { return arr0 == i_rhs.arr0 && - arr1 == i_rhs.arr1; + arr1 == i_rhs.arr1 && + iv_rank == i_rhs.iv_rank && + iv_update_rank == i_rhs.iv_update_rank; } }; +/// +/// @brief Determines our rank configuration type across all ports +/// @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& i_target, + std::vector& o_rank_config); + +/// +/// @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& i_target, + rank_configuration& o_rank_config); + /// /// @brief A class representing a series of CCS instructions, and the /// CCS engine parameters associated with running the instructions @@ -402,12 +507,10 @@ static void mrs_rcd_helper( fapi2::buffer& i_arr0 ) /// @brief Setup activate command instruction /// @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_target the DIMM this instruction is headed for /// @param[in] i_rank the rank on this dimm /// template< fapi2::TargetType T, typename TT = ccsTraits > -inline instruction_t act_command( const fapi2::Target& i_target, - const uint64_t i_rank) +inline instruction_t act_command( const uint64_t i_rank) { fapi2::buffer l_boilerplate_arr0; fapi2::buffer l_boilerplate_arr1; @@ -432,7 +535,7 @@ inline instruction_t act_command( const fapi2::Target(); l_boilerplate_arr0.clearBit(); - return instruction_t(i_target, i_rank, l_boilerplate_arr0, l_boilerplate_arr1); + return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1); } /// @@ -478,14 +581,13 @@ inline instruction_t rcd_command( const fapi2::Target(); // RCD always goes to the 0th rank on the DIMM; either 0 or 4. - return instruction_t(i_target, (mss::index(i_target) == 0) ? 0 : 4, rcd_boilerplate_arr0, rcd_boilerplate_arr1); + return instruction_t((mss::index(i_target) == 0) ? 0 : 4, rcd_boilerplate_arr0, rcd_boilerplate_arr1); } /// /// @brief Create, initialize an MRS 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_target the DIMM this instruction is headed for /// @param[in] i_rank the rank on this dimm /// @param[in] i_mrs the specific MRS /// @return the MRS CCS instruction @@ -494,8 +596,7 @@ inline instruction_t rcd_command( const fapi2::Target > -inline instruction_t mrs_command( const fapi2::Target& i_target, - const uint64_t i_rank, +inline instruction_t mrs_command (const uint64_t i_rank, const uint64_t i_mrs ) { fapi2::buffer rcd_boilerplate_arr0; @@ -514,7 +615,7 @@ inline instruction_t mrs_command( const fapi2::Target(); mss::swizzle(mrs, rcd_boilerplate_arr0); FAPI_DBG("mrs rcd boiler 0x%llx 0x%llx", uint8_t(mrs), uint64_t(rcd_boilerplate_arr0)); - return instruction_t(i_target, i_rank, rcd_boilerplate_arr0, rcd_boilerplate_arr1); + return instruction_t(i_rank, rcd_boilerplate_arr0, rcd_boilerplate_arr1); } /// @@ -547,8 +648,9 @@ inline instruction_t des_command(const uint16_t i_idle = 0) // RAS, CAS, WE no-care // Device Deslect wants CS_n always high (select nothing using rank NO_CHIP_SELECT_ACTIVE) - return instruction_t(fapi2::Target(), NO_CHIP_SELECT_ACTIVE, - rcd_boilerplate_arr0, rcd_boilerplate_arr1); + return instruction_t( NO_CHIP_SELECT_ACTIVE, + rcd_boilerplate_arr0, + rcd_boilerplate_arr1); } /// @@ -690,8 +792,7 @@ inline instruction_t initial_cal_command(const uint64_t i_rp) /// in this template definition) /// template< fapi2::TargetType T, typename TT = ccsTraits > -inline instruction_t zqcl_command( const fapi2::Target& i_target, - const uint64_t i_rank, +inline instruction_t zqcl_command( const uint64_t i_rank, const uint16_t i_idle = 0 ) { fapi2::buffer l_boilerplate_arr0; @@ -714,14 +815,13 @@ inline instruction_t zqcl_command( const fapi2::Target( i_idle ); - return instruction_t(i_target, i_rank, l_boilerplate_arr0, l_boilerplate_arr1); + return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1); } /// /// @brief Setup read command helper function /// @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_target the DIMM this instruction is headed for /// @param[in] i_rank the rank on this dimm /// @param[in] i_bank_addr bank address bits [BG0:BG1] = [62:63] (right aligned) /// @param[in] i_bank_group_addr bank group address bits [BA0:BA1] = [62:63] (right aligned) @@ -732,8 +832,7 @@ inline instruction_t zqcl_command( const fapi2::Target > -static fapi2::buffer read_cmd_boilerplate( const fapi2::Target& i_target, - const uint64_t i_rank, +static fapi2::buffer read_cmd_boilerplate( const uint64_t i_rank, const fapi2::buffer& i_bank_addr = 0, const fapi2::buffer& i_bank_group_addr = 0, const fapi2::buffer& i_column_addr = 0) @@ -774,7 +873,6 @@ static fapi2::buffer read_cmd_boilerplate( const fapi2::Target read_cmd_boilerplate( const fapi2::Target > -inline instruction_t wr_command( const fapi2::Target& i_target, - const uint64_t i_rank, +inline instruction_t wr_command( const uint64_t i_rank, const fapi2::buffer& i_bank_addr = 0, const fapi2::buffer& i_bank_group_addr = 0, const fapi2::buffer& i_column_addr = 0) { // WR's and RD's are very similar, so we just use the RD command boiler plate and modify the command to a WR - fapi2::buffer l_boilerplate_arr0 = read_cmd_boilerplate(i_target, - i_rank, + fapi2::buffer l_boilerplate_arr0 = read_cmd_boilerplate(i_rank, i_bank_addr, i_bank_group_addr, i_column_addr); @@ -804,14 +900,13 @@ inline instruction_t wr_command( const fapi2::Target .template clearBit() .template clearBit(); - return instruction_t(i_target, i_rank, l_boilerplate_arr0, l_boilerplate_arr1); + return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1); } /// /// @brief Setup read command (Fixed BL8 or BC4) instruction /// @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_target the DIMM this instruction is headed for /// @param[in] i_rank the rank on this dimm /// @param[in] i_bank_addr bank address bits [BA0:BA1] = [62:63] (right aligned) /// @param[in] i_bank_group_addr bank group address bits [BG0:BG1] = [62:63] (right aligned) @@ -822,8 +917,7 @@ inline instruction_t wr_command( const fapi2::Target /// in this template definition) /// template< fapi2::TargetType T, typename TT = ccsTraits > -inline instruction_t rd_command( const fapi2::Target& i_target, - const uint64_t i_rank, +inline instruction_t rd_command( const uint64_t i_rank, const fapi2::buffer& i_bank_addr = 0, const fapi2::buffer& i_bank_group_addr = 0, const fapi2::buffer& i_column_addr = 0) @@ -831,20 +925,21 @@ inline instruction_t rd_command( const fapi2::Target fapi2::buffer l_boilerplate_arr0; fapi2::buffer l_boilerplate_arr1; - l_boilerplate_arr0 = read_cmd_boilerplate(i_target, i_rank, i_bank_addr, - i_bank_group_addr, i_column_addr); + l_boilerplate_arr0 = read_cmd_boilerplate(i_rank, + i_bank_addr, + i_bank_group_addr, + i_column_addr); // Setup ADDR10/AP based on read type l_boilerplate_arr0.clearBit(); - return instruction_t(i_target, i_rank, l_boilerplate_arr0, l_boilerplate_arr1); + return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1); } /// /// @brief Setup read w/auto precharge command (Fixed BL8 or BC4) instruction /// @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_target the DIMM this instruction is headed for /// @param[in] i_rank the rank on this dimm /// @param[in] i_bank_addr bank address bits [BG0:BG1] = [62:63] (right aligned) /// @param[in] i_bank_group_addr bank group address bits [BA0:BA1] = [62:63] (right aligned) @@ -855,8 +950,7 @@ inline instruction_t rd_command( const fapi2::Target /// in this template definition) /// template< fapi2::TargetType T, typename TT = ccsTraits > -inline instruction_t rda_command( const fapi2::Target& i_target, - const uint64_t i_rank, +inline instruction_t rda_command( const uint64_t i_rank, const fapi2::buffer& i_bank_addr = 0, const fapi2::buffer& i_bank_group_addr = 0, const fapi2::buffer& i_column_addr = 0) @@ -864,20 +958,21 @@ inline instruction_t rda_command( const fapi2::Target l_boilerplate_arr0; fapi2::buffer l_boilerplate_arr1; - l_boilerplate_arr0 = read_cmd_boilerplate(i_target, i_rank, i_bank_addr, - i_bank_group_addr, i_column_addr); + l_boilerplate_arr0 = read_cmd_boilerplate(i_rank, + i_bank_addr, + i_bank_group_addr, + i_column_addr); // Setup ADDR10/AP based on read type l_boilerplate_arr0.setBit(); - return instruction_t(i_target, i_rank, l_boilerplate_arr0, l_boilerplate_arr1); + return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1); } /// /// @brief Setup precharge all banks command instruction /// @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_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 precharge all banks command CCS instruction @@ -886,8 +981,7 @@ inline instruction_t rda_command( const fapi2::Target > -inline instruction_t precharge_all_command( const fapi2::Target& i_target, - const uint64_t i_rank, +inline instruction_t precharge_all_command( const uint64_t i_rank, const uint16_t i_idle = 0 ) { fapi2::buffer l_boilerplate_arr0; @@ -913,22 +1007,20 @@ inline instruction_t precharge_all_command( const fapi2::Target(i_target, i_rank, l_boilerplate_arr0, l_boilerplate_arr1); + return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1); } /// /// @brief Setup self-refresh entry command instruction /// @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_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 self-refresh entry command CCS instruction /// @note THIS IS FOR DDR4 NON-LRDIMM ONLY RIGHT NOW /// template< fapi2::TargetType T, typename TT = ccsTraits > -inline instruction_t self_refresh_entry_command( const fapi2::Target& i_target, - const uint64_t i_rank, const uint16_t i_idle = 0 ) +inline instruction_t self_refresh_entry_command( const uint64_t i_rank, const uint16_t i_idle = 0 ) { fapi2::buffer l_boilerplate_arr0; fapi2::buffer l_boilerplate_arr1; @@ -950,14 +1042,13 @@ inline instruction_t self_refresh_entry_command( const fapi2::Target(i_target, i_rank, l_boilerplate_arr0, l_boilerplate_arr1); + return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1); } /// /// @brief Setup self-refresh exit using NOP command instruction /// @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_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 self-refresh exit command CCS instruction @@ -965,8 +1056,7 @@ inline instruction_t self_refresh_entry_command( const fapi2::Target > -inline instruction_t self_refresh_exit_command( const fapi2::Target& i_target, - const uint64_t i_rank, const uint16_t i_idle = 0 ) +inline instruction_t self_refresh_exit_command( const uint64_t i_rank, const uint16_t i_idle = 0 ) { fapi2::buffer l_boilerplate_arr0; fapi2::buffer l_boilerplate_arr1; @@ -988,7 +1078,7 @@ inline instruction_t self_refresh_exit_command( const fapi2::Target(i_target, i_rank, l_boilerplate_arr0, l_boilerplate_arr1); + return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1); } // diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H index 0d7b2d018..bd8277daa 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H @@ -308,7 +308,7 @@ fapi2::ReturnCode mrs_engine( const fapi2::Target& i_ta const uint64_t i_delay_in_cycles, std::vector< ccs::instruction_t >& io_inst ) { - ccs::instruction_t l_inst_a_side = ccs::mrs_command(i_target, i_rank, i_data.iv_mrs); + ccs::instruction_t l_inst_a_side = ccs::mrs_command(i_rank, i_data.iv_mrs); ccs::instruction_t l_inst_b_side; bool l_is_a17 = false; @@ -1914,7 +1914,7 @@ fapi2::ReturnCode mpr_read( const fapi2::Target& i_targ // Right now we only have support for RD and RDA // Unclear if we want the API select the type of read command right now // Note the auto precharge is ignored with MPR mode on so we just do a read cmd - ccs::instruction_t l_inst = ccs::rd_command (i_target, i_rank, i_mpr_loc); + ccs::instruction_t l_inst = ccs::rd_command (i_rank, i_mpr_loc); // In MPR Mode: // Reads (back-to-back) from Page 0 may use tCCD_S or tCCD_L timing between read commands @@ -1959,7 +1959,7 @@ fapi2::ReturnCode precharge_all( const fapi2::Target& i const uint64_t i_rank, std::vector< ccs::instruction_t >& io_inst ) { - ccs::instruction_t l_inst = ccs::precharge_all_command (i_target, i_rank); + ccs::instruction_t l_inst = ccs::precharge_all_command (i_rank); // From the DDR4 Spec tRP is the precharge command period uint8_t l_delay = 0; 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 0374da3dc..b35c5084f 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 @@ -527,9 +527,9 @@ fapi2::ReturnCode post_restore_zqcal( const fapi2::Target(d, r, l_trp[0]) ); + l_program.iv_instructions.push_back( ccs::precharge_all_command(r, l_trp[0]) ); FAPI_DBG("zqcal_command for %s", mss::c_str(d)); - l_program.iv_instructions.push_back( ccs::zqcl_command(d, r, mss::tzqinit()) ); + l_program.iv_instructions.push_back( ccs::zqcl_command(r, mss::tzqinit()) ); } }// dimms @@ -661,7 +661,7 @@ fapi2::ReturnCode preload_epow_sequence( const fapi2::Target(l_dimms[0], 0, l_trp); + l_inst = ccs::precharge_all_command(0, l_trp); l_inst.arr0.insertFromRight(CS_N_ACTIVE); l_inst.arr0.insertFromRight(CS_N_ACTIVE); l_inst.arr0.setBit(); @@ -670,7 +670,7 @@ fapi2::ReturnCode preload_epow_sequence( const fapi2::Target(l_dimms[0], 0, mss::tcksre(l_dimms[0])); + l_inst = ccs::self_refresh_entry_command(0, mss::tcksre(l_dimms[0])); l_inst.arr0.insertFromRight(CS_N_ACTIVE); l_inst.arr0.insertFromRight(CS_N_ACTIVE); l_inst.arr0.insertFromRight(mss::CKE_LOW); @@ -680,7 +680,7 @@ fapi2::ReturnCode preload_epow_sequence( const fapi2::Target(l_dimms[0]); + l_inst = ccs::instruction_t(); FAPI_INF("Assert RESETn arr0 = 0x%016lx , arr1 = 0x%016lx", l_inst.arr0, l_inst.arr1); l_program.iv_instructions.push_back(l_inst); diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/zqcal.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/zqcal.C index 844765f44..6e53bddd8 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/zqcal.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/zqcal.C @@ -69,7 +69,7 @@ fapi2::ReturnCode setup_dram_zqcal( const fapi2::Target FAPI_TRY( mss::tdllk(i_target, tDLLK) ); // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS - l_inst = ccs::zqcl_command(i_target, i_rank); + l_inst = ccs::zqcl_command(i_rank); // Doubling tZQ to better margin per lab request { diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.H index fb9362680..c7d92d98a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.H @@ -122,8 +122,7 @@ inline fapi2::ReturnCode add_mpr_pattern_writes(const fapi2::Target( i_target, - i_rank, + auto l_wr = mss::ccs::wr_command( i_rank, l_ba, MPR_WR_BG, l_pattern); diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H index e61edfc78..db61b8afb 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H @@ -211,6 +211,9 @@ enum ffdc_function_codes // LR training function DWL_CALL_OUT = 130, MREP_CALL_OUT = 131, + + + CCS_INST_CONFIGURE_RANK = 132, }; // Static consts describing the bits used in the cal_step_enable attribute diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C index 795107bfb..559593111 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit.C @@ -60,7 +60,6 @@ extern "C" { fapi2::buffer l_data; - mss::ccs::instruction_t l_inst; mss::ccs::instruction_t l_des = mss::ccs::des_command(); mss::ccs::program l_program; -- cgit v1.2.1