diff options
author | Brian Silver <bsilver@us.ibm.com> | 2016-07-11 08:06:54 -0500 |
---|---|---|
committer | Stephen Cprek <smcprek@us.ibm.com> | 2016-07-18 16:36:57 -0500 |
commit | f2921db8ffcf4284ab8efbd181420c2cf54935a3 (patch) | |
tree | e20d68cbaec85e1d5736356e9d3ab106655bf6f0 /src/import/chips/p9/procedures/hwp/memory/lib | |
parent | 92dba09ec8f4ba46bb9488723eeaa8e7832757bd (diff) | |
download | talos-hostboot-f2921db8ffcf4284ab8efbd181420c2cf54935a3.tar.gz talos-hostboot-f2921db8ffcf4284ab8efbd181420c2cf54935a3.zip |
Add support for dynamic MC PERF2 register setup
Add dimm::kind::vector function to get vectors of kinds
Add slave rank calculation to dimm::kind
Change-Id: I6fce24b30bb9c455f5b3f213e05ca1b956492b4e
Depends-On: I0fc6f6ab6f209f7399d0f5369b03a4504838a026
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/26865
Tested-by: Jenkins Server <pfd-jenkins+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>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib')
6 files changed, 229 insertions, 103 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H index 3f68ce830..62cacb269 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H @@ -49,25 +49,68 @@ class kind { public: + /// + /// @brief Generate a vector of DIMM kind from a vector of DIMM + /// @param[in] i_dimm a vector of DIMM + /// @return std::vector of dimm::kind relating to the DIMM passed in + /// + static std::vector<kind> vector(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>>& i_dimm) + { + std::vector<kind> l_kinds; + + for (const auto& d : i_dimm) + { + l_kinds.push_back( kind(d) ); + } + + return l_kinds; + } + + + /// + /// @brief operator==() - are two kinds the same? + /// @param[in] i_rhs the right hand side of the comparison statement + /// @return boll true iff the two kind are of the same kind + /// @warning this does not compare the targets (iv_target,) just the values + /// + inline bool operator==(const kind& i_rhs) const + { + return ((iv_master_ranks == i_rhs.iv_master_ranks) && + (iv_slave_ranks == i_rhs.iv_slave_ranks) && + (iv_dram_density == i_rhs.iv_dram_density) && + (iv_dram_width == i_rhs.iv_dram_width) && + (iv_dram_generation == i_rhs.iv_dram_generation) && + (iv_dimm_type == i_rhs.iv_dimm_type) && + (iv_rows == i_rhs.iv_rows) && + (iv_size == i_rhs.iv_size)); + } + + /// + /// @brief Construct a dimm::kind data structure - information about the kind of DIMM this is + /// @param[in] i_target a DIMM target + /// kind(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target): iv_target(i_target) { + uint8_t l_ranks = 0; + FAPI_TRY( mss::eff_dram_gen(i_target, iv_dram_generation) ); FAPI_TRY( mss::eff_dimm_type(i_target, iv_dimm_type) ); FAPI_TRY( mss::eff_dram_density(i_target, iv_dram_density) ); FAPI_TRY( mss::eff_dram_width(i_target, iv_dram_width) ); FAPI_TRY( mss::eff_num_master_ranks_per_dimm(i_target, iv_master_ranks) ); + FAPI_TRY( mss::eff_num_ranks_per_dimm(i_target, l_ranks) ); FAPI_TRY( mss::eff_dram_row_bits(i_target, iv_rows) ); FAPI_TRY( mss::eff_dimm_size(i_target, iv_size) ); - // TK: Attribute for slave ranks. - iv_slave_ranks = 0; + iv_slave_ranks = l_ranks - iv_master_ranks; return; fapi_try_exit: // Not 100% sure what to do here ... FAPI_ERR("error initializing DIMM structure: %s 0x%016lx", mss::c_str(i_target), uint64_t(fapi2::current_err)); + fapi2::Assert(false); } const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.C b/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.C index c8a58a083..c76eecbcd 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.C @@ -46,101 +46,7 @@ namespace mss template<> fapi2::ReturnCode dump_regs( const fapi2::Target<TARGET_TYPE_MCS>& i_target ) { - // To generate this vector: - // grep MCA_MBA chips/p9/common/include/p9_mc_scom_addresses.H | awk '{ print "{\42" $2 "\42,", $2, "}," }' - static const std::vector< std::pair<char const*, uint64_t> > l_mba_registers = - { - {"MCA_MBACALFIRQ", MCA_MBACALFIRQ }, - {"MCA_MBACALFIRQ_AND", MCA_MBACALFIRQ_AND }, - {"MCA_MBACALFIRQ_OR", MCA_MBACALFIRQ_OR }, - {"MCA_MBACALFIR_ACTION0", MCA_MBACALFIR_ACTION0 }, - {"MCA_MBACALFIR_ACTION1", MCA_MBACALFIR_ACTION1 }, - {"MCA_MBACALFIR_MASK", MCA_MBACALFIR_MASK }, - {"MCA_MBACALFIR_MASK_AND", MCA_MBACALFIR_MASK_AND }, - {"MCA_MBACALFIR_MASK_OR", MCA_MBACALFIR_MASK_OR }, - {"MCA_MBAREF0Q", MCA_MBAREF0Q }, - {"MCA_MBAREFAQ", MCA_MBAREFAQ }, - {"MCA_MBARPC0Q", MCA_MBARPC0Q }, - {"MCA_MBASTR0Q", MCA_MBASTR0Q }, - {"MCA_MBA_CAL0Q", MCA_MBA_CAL0Q }, - {"MCA_MBA_CAL1Q", MCA_MBA_CAL1Q }, - {"MCA_MBA_CAL2Q", MCA_MBA_CAL2Q }, - {"MCA_MBA_CAL3Q", MCA_MBA_CAL3Q }, - {"MCA_MBA_DBG0Q", MCA_MBA_DBG0Q }, - {"MCA_MBA_DBG1Q", MCA_MBA_DBG1Q }, - {"MCA_MBA_DSM0Q", MCA_MBA_DSM0Q }, - {"MCA_MBA_ERR_REPORTQ", MCA_MBA_ERR_REPORTQ }, - {"MCA_MBA_FARB0Q", MCA_MBA_FARB0Q }, - {"MCA_MBA_FARB1Q", MCA_MBA_FARB1Q }, - {"MCA_MBA_FARB2Q", MCA_MBA_FARB2Q }, - {"MCA_MBA_FARB3Q", MCA_MBA_FARB3Q }, - {"MCA_MBA_FARB4Q", MCA_MBA_FARB4Q }, - {"MCA_MBA_FARB5Q", MCA_MBA_FARB5Q }, - {"MCA_MBA_FARB6Q", MCA_MBA_FARB6Q }, - {"MCA_MBA_FARB7Q", MCA_MBA_FARB7Q }, - {"MCA_MBA_PMU0Q", MCA_MBA_PMU0Q }, - {"MCA_MBA_PMU1Q", MCA_MBA_PMU1Q }, - {"MCA_MBA_PMU2Q", MCA_MBA_PMU2Q }, - {"MCA_MBA_PMU3Q", MCA_MBA_PMU3Q }, - {"MCA_MBA_PMU4Q", MCA_MBA_PMU4Q }, - {"MCA_MBA_PMU5Q", MCA_MBA_PMU5Q }, - {"MCA_MBA_PMU6Q", MCA_MBA_PMU6Q }, - {"MCA_MBA_PMU7Q", MCA_MBA_PMU7Q }, - {"MCA_MBA_PMU8Q", MCA_MBA_PMU8Q }, - {"MCA_MBA_RRQ0Q", MCA_MBA_RRQ0Q }, - {"MCA_MBA_TMR0Q", MCA_MBA_TMR0Q }, - {"MCA_MBA_TMR1Q", MCA_MBA_TMR1Q }, - {"MCA_MBA_TMR2Q", MCA_MBA_TMR2Q }, - {"MCA_MBA_WRQ0Q", MCA_MBA_WRQ0Q }, - }; - - // To generate this vector: - // grep MCA_M chips/p9/common/include/p9_mc_scom_addresses.H | awk '{ print "{\42" $2 "\42,", $2, "}," }' - // grep MCS_PORT02 chips/p9/common/include/p9_mc_scom_addresses.H | awk '{ print "{\42" $2 "\42,", $2, "}," }' - // grep MCS_PORT13 chips/p9/common/include/p9_mc_scom_addresses.H | awk '{ print "{\42" $2 "\42,", $2, "}," }' - static const std::vector< std::pair<char const*, uint64_t> > l_mcs_registers = - { - {"MCS_MCFGP", MCS_MCFGP }, - {"MCS_MCFGPA", MCS_MCFGPA }, - {"MCS_MCFGPM", MCS_MCFGPM }, - {"MCS_MCFGPMA", MCS_MCFGPMA }, - {"MCS_MCFIR", MCS_MCFIR }, - {"MCS_MCFIR_AND", MCS_MCFIR_AND }, - {"MCS_MCFIR_OR", MCS_MCFIR_OR }, - {"MCS_MCFIRACT0", MCS_MCFIRACT0 }, - {"MCS_MCFIRACT1", MCS_MCFIRACT1 }, - {"MCS_MCFIRMASK", MCS_MCFIRMASK }, - {"MCS_MCFIRMASK_AND", MCS_MCFIRMASK_AND }, - {"MCS_MCFIRMASK_OR", MCS_MCFIRMASK_OR }, - {"MCS_MCLFSR", MCS_MCLFSR }, - {"MCS_MCMODE0", MCS_MCMODE0 }, - {"MCS_MCMODE1", MCS_MCMODE1 }, - {"MCS_MCMODE2", MCS_MCMODE2 }, - {"MCS_MCPERF1", MCS_MCPERF1 }, - {"MCS_MCSYNC", MCS_MCSYNC }, - {"MCS_MCTO", MCS_MCTO }, - {"MCS_MCWATCNTL", MCS_MCWATCNTL }, - }; - - for (const auto& r : l_mcs_registers) - { - fapi2::buffer<uint64_t> l_data; - FAPI_TRY( mss::getScom(i_target, r.second, l_data) ); - FAPI_DBG("dump %s: 0x%016lx 0x%016lx", r.first, r.second, l_data); - } - - for (const auto& p : find_targets<TARGET_TYPE_MCA>(i_target)) - { - for (const auto r : l_mba_registers) - { - fapi2::buffer<uint64_t> l_data; - FAPI_TRY( mss::getScom(p, r.second, l_data) ); - FAPI_DBG("dump %s: 0x%016lx 0x%016lx", r.first, r.second, l_data); - } - } - -fapi_try_exit: - return fapi2::current_err; + return fapi2::FAPI2_RC_SUCCESS; } namespace mc @@ -162,7 +68,6 @@ fapi2::ReturnCode thermal_throttle_scominit (const fapi2::Target<fapi2::TARGET_T FAPI_TRY(mss::getScom(i_target, MCA_MBA_FARB3Q, l_data)); uint32_t l_throttle_per_port = 0; - FAPI_TRY( mss::mrw_safemode_mem_throttled_n_commands_per_port( l_throttle_per_port) ); l_data.insertFromRight<MCA_MBA_FARB3Q_CFG_NM_N_PER_SLOT, MCA_MBA_FARB3Q_CFG_NM_N_PER_SLOT_LEN>(l_throttle_per_port); @@ -172,8 +77,8 @@ fapi2::ReturnCode thermal_throttle_scominit (const fapi2::Target<fapi2::TARGET_T l_data.clearBit<MCA_MBA_FARB3Q_CFG_NM_CHANGE_AFTER_SYNC>(); FAPI_TRY( mss::putScom(i_target, MCA_MBA_FARB3Q, l_data) ); - } + { fapi2::buffer<uint64_t> l_data; uint32_t l_throttle_per_slot = 0; @@ -185,9 +90,11 @@ fapi2::ReturnCode thermal_throttle_scominit (const fapi2::Target<fapi2::TARGET_T l_data.insertFromRight<MCA_MBA_FARB4Q_EMERGENCY_N, MCA_MBA_FARB4Q_EMERGENCY_N_LEN>(l_throttle_per_slot); FAPI_TRY( mss::putScom(i_target, MCA_MBA_FARB4Q, l_data) ); } + fapi_try_exit: return fapi2::current_err; } + /// /// @brief Disable emergency mode throttle for thermal_init /// @param[in] i_target the MCS target @@ -197,11 +104,15 @@ fapi_try_exit: fapi2::ReturnCode disable_emergency_throttle (const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target) { fapi2::buffer<uint64_t> l_data; + FAPI_TRY( mss::getScom(i_target, MCS_MCMODE0, l_data)); l_data.clearBit<MCS_MCMODE0_ENABLE_EMER_THROTTLE>(); FAPI_TRY( mss::putScom(i_target, MCS_MCMODE0, l_data)); + fapi_try_exit: return fapi2::current_err; } + } // namespace mc + } //close namespace mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.H b/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.H index fe907b38d..6cfce40b1 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.H @@ -162,6 +162,22 @@ fapi2::ReturnCode thermal_throttle_scominit (const fapi2::Target<fapi2::TARGET_T fapi2::ReturnCode disable_emergency_throttle (const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target); /// +/// @brief Perform initializations of the MC performance registers +/// @note Some of these bits are taken care of in the scom initfiles +/// @param[in] i_target the target which has the MCA to map +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode setup_perf2_register(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target); + +/// +/// @brief Calculate the value of the MC perf2 register. +/// @param[in] i_target the target which has the MCA to map +/// @param[out] o_value the perf2 value for the MCA +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode calculate_perf2(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint64_t& o_value); + +/// /// @brief Perform initializations of the MC translation /// @tparam P the fapi2::TargetType of the port /// @tparam TT the mcTraits associated with P @@ -170,6 +186,9 @@ fapi2::ReturnCode disable_emergency_throttle (const fapi2::Target<fapi2::TARGET_ /// template< fapi2::TargetType P, typename TT = mcTraits<P> > fapi2::ReturnCode setup_xlate_map(const fapi2::Target<P>& i_target); + } //mc + } //mss + #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/perf_reg.C b/src/import/chips/p9/procedures/hwp/memory/lib/mc/perf_reg.C index 5dc751967..12f295209 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/perf_reg.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/perf_reg.C @@ -16,3 +16,158 @@ /* deposited with the U.S. Copyright Office. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file perf_reg.C +/// @brief Subroutines to manipulate the memory controller performance registers +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> + +#include <p9_mc_scom_addresses.H> +#include <p9_mc_scom_addresses_fld.H> + +#include <lib/mss_attribute_accessors.H> + +#include <lib/mc/mc.H> +#include <lib/utils/scom.H> +#include <lib/dimm/kind.H> +#include <lib/utils/find.H> + +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_DIMM; + +namespace mss +{ + +namespace mc +{ + +/// +/// @brief Perform initializations of the MC performance registers +/// @note Some of these bits are taken care of in the scom initfiles +/// @param[in] i_target the target which has the MCA to map +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode setup_perf2_register(const fapi2::Target<TARGET_TYPE_MCA>& i_target) +{ + fapi2::buffer<uint64_t> l_data; + + // Get the values we need to put in the register + uint64_t l_value; + FAPI_TRY( calculate_perf2(i_target, l_value) ); + + // Setup the registers + FAPI_TRY( mss::getScom(i_target, MCS_0_PORT02_MCPERF2, l_data) ); + + // Per S. Powell 7/16, setup these registers but don't enable the function yet. So enable bits are + // intentionally not set + l_data.insertFromRight<MCS_PORT02_MCPERF2_REFRESH_BLOCK_CONFIG, + MCS_PORT02_MCPERF2_REFRESH_BLOCK_CONFIG_LEN>(l_value); + + FAPI_TRY( mss::putScom(i_target, MCS_0_PORT02_MCPERF2, l_data) ); + +fapi_try_exit: + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Calculate the value of the MC perf2 register. +/// @param[in] i_target the target which has the MCA to map +/// @param[out] o_value the perf2 value for the MCA +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode calculate_perf2(const fapi2::Target<TARGET_TYPE_MCA>& i_target, uint64_t& o_value) +{ + // + // From Senor Powell 7/16 + // if (slots=1, masters=1) + // MCPERF2_Refresh_Block_Config=0b000 + // if (slots=1, masters=2) + // MCPERF2_Refresh_Block_Config=0b001 + // if (slots=1, masters=4) + // MCPERF2_Refresh_Block_Config=0b100 + // if (slots=2, masters=1) + // MCPERF2_Refresh_Block_Config=0b010 + // if (slots=2, masters=2) + // MCPERF2_Refresh_Block_Config=0b011 + // if (slots=2, masters=4) + // MCPERF2_Refresh_Block_Config=0b100 + // + // if slot0 is 2 masters and slot1 is 1 master, just choose the 2 slot, 2 masters setting. + // (i.e., choose the max(mranks_dimm1, mranks_dimm2) + + constexpr uint64_t l_refresh_values[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = + { + {0b000, 0b001, 0, 0b100}, // Skip the ol' 3 rank DIMM + {0b010, 0b011, 0, 0b100} + }; + + FAPI_INF("Calculating perf2 register for MCA%d (%d)", mss::pos(i_target), mss::index(i_target)); + + // Find the DIMM on this port with the most master ranks. + // That's how we know which element in the table to use. + // uint8_t so I can use it to read from an attribute directly + + uint8_t l_mrank_index = 0; + uint8_t l_master_ranks_zero = 0; + uint8_t l_master_ranks_one = 0; + + fapi2::buffer<uint64_t> l_data; + + const auto l_dimm = mss::find_targets<TARGET_TYPE_DIMM>(i_target); + const auto l_slot_index = l_dimm.size() - 1; + + switch(l_dimm.size()) + { + // No DIMM, nothing to do + case 0: + return fapi2::FAPI2_RC_SUCCESS; + break; + + // One DIMM, we've got the slots of fun + case 1: + FAPI_TRY( mss::eff_num_master_ranks_per_dimm(l_dimm[0], l_mrank_index) ); + --l_mrank_index; + FAPI_INF("1 DIMM mranks: D0[%d] index %d", l_mrank_index + 1, l_mrank_index); + break; + + // Two DIMM, find the max of the master ranks + case 2: + { + FAPI_TRY( mss::eff_num_master_ranks_per_dimm(l_dimm[0], l_master_ranks_zero) ); + FAPI_TRY( mss::eff_num_master_ranks_per_dimm(l_dimm[1], l_master_ranks_one) ); + + l_mrank_index = std::max(l_master_ranks_zero, l_master_ranks_one) - 1; + FAPI_INF("2 DIMM mranks: D0[%d] D1[%d] index %d", l_master_ranks_zero, l_master_ranks_one, l_mrank_index); + } + break; + + default: + // We have a bug - no way to get more than 2 DIMM in a dual-drop system + FAPI_ERR("seeing %d DIMM on %s", l_dimm.size(), mss::c_str(i_target)); + fapi2::Assert(false); + break; + }; + + FAPI_INF("Refresh Block Config: %u ([%d][%d] populated slots: %d, max mranks: %d)", + l_refresh_values[l_slot_index][l_mrank_index], + l_slot_index, l_mrank_index, + l_slot_index + 1, l_mrank_index + 1); + + o_value = l_refresh_values[l_slot_index][l_mrank_index]; + +fapi_try_exit: + return fapi2::current_err; +} + +} // namespace + +} // namespace + diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C b/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C index 2cddbadcf..d9aeab99b 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C @@ -52,13 +52,13 @@ namespace mss namespace mc { - +/// /// @brief Perform initializations of the MC translation /// @tparm P the fapi2::TargetType of the port /// @tparm TT the typename of the traits /// @param[in] i_target, the target which has the MCA to map /// @return FAPI2_RC_SUCCESS iff ok - +/// template<> fapi2::ReturnCode setup_xlate_map(const fapi2::Target<TARGET_TYPE_MCA>& i_target) { 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 4722e9f2b..5d75691ac 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 @@ -48,8 +48,6 @@ enum sizes DEFAULT_POLL_LIMIT = 10, ///< the number of poll attempts in the event we can't calculate another MAX_NUM_IMP = 4, ///< number of impedances valid per slew type MAX_NUM_CAL_SLEW_RATES = 4, ///< 3V/ns, 4V/ns, 5V/ns, 6V/n - MAX_SLEW_VALUE = 15, ///< 4 bit value - MAX_SUPPORTED_FREQUENCIES = 1, ///< Number of supported frequencies. Right now it's only 2400 BYTES_PER_GB = 1000000000, ///< Multiplier to go from GB to B T_PER_MT = 1000000, ///< Multiplier to go from MT/s to T/s |