summaryrefslogtreecommitdiffstats
path: root/src/import/chips
diff options
context:
space:
mode:
authorLuke Mulkey <lwmulkey@us.ibm.com>2017-02-02 11:38:38 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-07-26 00:29:10 -0400
commit7d245fb021ff8a6df7e44482b000ce7cf5c2919c (patch)
tree781d3ee4de98f33f07238bc60495b9e15f098b89 /src/import/chips
parent5afd9a14f2299a8acf43fa462f46dd382aecef1f (diff)
downloadtalos-hostboot-7d245fb021ff8a6df7e44482b000ce7cf5c2919c.tar.gz
talos-hostboot-7d245fb021ff8a6df7e44482b000ce7cf5c2919c.zip
Eff_config, volt, freq for p9c
Change-Id: I2a22441507fdb886acb46f61c0d58f852192f78a Original-Change-Id: I13fe2c0b91c0ae5b1c7ee37445775af566638c40 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35841 Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com> Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43539 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips')
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H29
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.C1
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.mk1
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.mk1
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.C402
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.H58
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.mk30
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk1
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.C2678
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.H395
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.mk33
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.C300
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.H62
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.mk30
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.C170
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.H61
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.mk30
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.C658
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.H70
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.mk30
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.C481
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.H62
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.mk31
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.C125
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.H56
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.mk30
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.C747
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.H54
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.mk31
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.mk1
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.C362
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.H54
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.mk31
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.C305
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.mk29
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.C307
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.mk29
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.C311
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.mk29
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.C286
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.mk29
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.C304
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.mk29
43 files changed, 8749 insertions, 14 deletions
diff --git a/src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H b/src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H
index 720f49e56..6b6c65f66 100644
--- a/src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H
+++ b/src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H
@@ -35,6 +35,7 @@
#ifndef DIMMCONSTS_H_
#define DIMMCONSTS_H_
+//TODO:RTC171671 : add namespace to consts
enum consts : size_t
{
MAX_PORTS_PER_MBA = 2, ///< Maximum number of ports on an MBA
@@ -45,7 +46,7 @@ enum consts : size_t
NUM_RANK_GROUPS = 4, ///< Maximum number of rank groups
MAX_RANKS_PER_PORT = 8, ///< Maximum number of ranks on a port
DIMM_DQ_RANK_BITMAP_SIZE = 10, ///< Size in bytes of the Bad DQ bitmap for a rank.
-
+ NUM_MCS_PER_PROC = 8, ///< Number of MCS instances per proc
// This is the number of bits in DIMM_DQ_RANK_BITMAP_SIZE.
DIMM_DQ_NUM_DQS = DIMM_DQ_RANK_BITMAP_SIZE * 8, ///< Number of DQs (data query pins).
@@ -80,21 +81,29 @@ enum consts : size_t
enum mrs : size_t
{
- MRS0_BA = 0,
- MRS1_BA = 1,
- MRS2_BA = 2,
- MRS3_BA = 3,
- MRS4_BA = 4,
- MRS5_BA = 5,
- MRS6_BA = 6,
- INVALID = 255,
+ MRS0_BA = 0, ///< MRS0 Bank Address
+ MRS1_BA = 1, ///< MRS1 Bank Address
+ MRS2_BA = 2, ///< MRS2 Bank Address
+ MRS3_BA = 3, ///< MRS3 Bank Address
+ MRS4_BA = 4, ///< MRS4 Bank Address
+ MRS5_BA = 5, ///< MRS5 Bank Address
+ MRS6_BA = 6, ///< MRS6 Bank Address
+ INVALID = 255, ///< INVALID
+};
+
+enum dimm_types : size_t
+{
+ CDIMM = 0, ///< Centaur DIMM
+ RDIMM = 1, ///< Registered Dimm
+ UDIMM = 2, ///< Unregistered Dimm
+ LRDIMM = 3, ///< Load Reduced Dimm
};
enum mss_ccs_status_query_result
{
MSS_STAT_QUERY_PASS = 1,
MSS_STAT_QUERY_IN_PROGRESS = 2,
- MSS_STAT_QUERY_FAIL = 3
+ MSS_STAT_QUERY_FAIL = 3,
};
enum mss_ccs_data_pattern
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.C
index 92b8eaff3..2cea0356f 100644
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.C
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.C
@@ -538,6 +538,7 @@ extern "C"
return fapi2::current_err;
}
+ ///
/// @brief FW Team HWP that accesses the Bad DQ Bitmap.
/// It accesses the raw data from DIMM SPD and does
/// any necessary processing to turn it into a
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.mk
index 6535d8ba3..40664e911 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.mk
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapAccessHwp.mk
@@ -28,6 +28,5 @@
PROCEDURE=p9c_dimmBadDqBitmapAccessHwp
$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
-#lib$(PROCEDURE)_DEPLIBS+=mss
$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.mk
index 851f0593c..3812fc82d 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.mk
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_dimmBadDqBitmapFuncs.mk
@@ -28,6 +28,5 @@
PROCEDURE=p9c_dimmBadDqBitmapFuncs
$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
-#lib$(PROCEDURE)_DEPLIBS+=mss
$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.C
new file mode 100644
index 000000000..352057ba3
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.C
@@ -0,0 +1,402 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+
+/// @file p9c_mss_bulk_pwr_throttles.C
+/// @brief Sets the throttle attributes based on a power limit for the dimms on the channel pair
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Mike Pardeik <pardeik@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+///
+
+// DESCRIPTION:
+// The purpose of this procedure is to set the throttle attributes based on a
+// power limit for the dimms on the channel pair
+// At the end, output attributes will be updated with throttle values that will
+// have dimms at or below the limit
+// NOTE: ISDIMMs and CDIMMs are handled differently
+// ISDIMMs use a power per DIMM for the thermal power limit from the MRW
+// CDIMM will use power per CDIMM (power for all virtual dimms) for the
+// thermal power limit from the MRW
+// Plan is to have ISDIMM use the per-slot throttles (thermal throttles) or
+// per-mba throttles (power throttles), and CDIMM to use the per-chip throttles
+// Note that throttle_n_per_mba takes on different meanings depending on how
+// cfg_nm_per_slot_enabled is set
+// Can be slot0/slot1 OR slot0/MBA throttling
+// Note that throttle_n_per_chip takes on different meaning depending on how
+// cfg_count_other_mba_dis is set
+// Can be per-chip OR per-mba throttling
+// These inits here are done in mss_scominit
+// ISDIMM: These registers need to be setup to these values, will be able to
+// do per slot or per MBA throttling
+// cfg_nm_per_slot_enabled = 1
+// cfg_count_other_mba_dis = 1
+// CDIMM: These registers need to be setup to these values, will be able to
+// do per mba or per chip throttling
+// cfg_nm_per_slot_enabled = 0
+// cfg_count_other_mba_dis = 0
+
+//------------------------------------------------------------------------------
+// My Includes
+//------------------------------------------------------------------------------
+#include <p9c_mss_bulk_pwr_throttles.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <dimmConsts.H>
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include <fapi2.H>
+
+extern "C" {
+ /// @brief mss_bulk_pwr_throttles(): This function determines the throttle values power limit for the dimms on the channel pair
+ /// @param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> & i_target_mba: MBA Target<fapi2::TARGET_TYPE_MBA> passed in
+ /// @return fapi2::ReturnCode
+ fapi2::ReturnCode p9c_mss_bulk_pwr_throttles(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+ {
+ FAPI_INF("*** Running mss_bulk_pwr_throttles ***");
+ float l_idle_util = 0; // in percent
+ float l_min_util = 1; // in percent
+ // These are the constants to use for ISDIMM power/throttle support
+ // Note that these are hardcoded and ISDIMMs will not use power curves
+ // No Throttling if available power is >= ISDIMM_MAX_DIMM_POWER
+ // Throttle when ISDIMM_MIN_DIMM_POWER <= available power <= ATTR_MSS_MEM_WATT_TARGET
+ // Throttle value will be maximum throttle * ISDIMM_MEMORY_THROTTLE_PERCENT
+ constexpr uint32_t ISDIMM_MAX_DIMM_POWER = 1200; // cW, max ISDIMM power for no throttling
+ constexpr uint32_t ISDIMM_MIN_DIMM_POWER = 800; // cW, min ISDIMM power for throttling
+ constexpr uint8_t ISDIMM_MEMORY_THROTTLE_PERCENT =
+ 65; // percent, throttle impact when limit is between min and max power. A value of 0 would be for no throttle impact.
+
+ uint32_t l_total_power_slope_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_total_power_int_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_dimm_ranks_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_port = 0;
+ uint8_t l_dimm = 0;
+ float l_dimm_power_array_idle[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ float l_dimm_power_array_max[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ float l_channel_power_array_idle[MAX_PORTS_PER_MBA] = {0};
+ float l_max_util = 0;
+ float l_channel_power_array_max[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_power_curve_percent_uplift = 0;
+ uint8_t l_power_curve_percent_uplift_idle = 0;
+ uint32_t l_max_dram_databus_util = 0;
+ uint8_t l_num_mba_with_dimms = 0;
+ uint8_t l_custom_dimm = 0;
+ uint32_t l_throttle_d = 0;
+ float l_channel_pair_power_idle = 0;
+ float l_channel_pair_power_max = 0;
+ uint32_t l_channel_pair_watt_target = 0;
+ float l_utilization = 0;
+ uint32_t l_number_of_dimms = 0;
+ float l_channel_power_slope = 0;
+ float l_channel_power_intercept = 0;
+ uint32_t l_throttle_n_per_mba = 0;
+ uint32_t l_throttle_n_per_chip = 0;
+ uint32_t l_channel_pair_power = 0;
+ uint32_t l_runtime_throttle_n_per_mba = 0;
+ uint32_t l_runtime_throttle_n_per_chip = 0;
+ uint8_t l_dram_gen = 0;
+
+ // get input attributes
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target_mba, l_custom_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_MAX_DRAM_DATABUS_UTIL,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_max_dram_databus_util));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_MEM_THROTTLE_DENOMINATOR, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_throttle_d));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_MEM_WATT_TARGET,
+ i_target_mba, l_channel_pair_watt_target));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_MBA,
+ i_target_mba, l_runtime_throttle_n_per_mba));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_CHIP,
+ i_target_mba, l_runtime_throttle_n_per_chip));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN,
+ i_target_mba, l_dram_gen));
+
+ // other attributes for custom dimms to get
+ if (l_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_power_curve_percent_uplift));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT_IDLE,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_power_curve_percent_uplift_idle));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_SLOPE,
+ i_target_mba, l_total_power_slope_array));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_INT,
+ i_target_mba, l_total_power_int_array));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM,
+ i_target_mba, l_dimm_ranks_array));
+ }
+
+ // Maximum theoretical data bus utilization (percent of max) (for ceiling)
+ // Comes from MRW value in c% - convert to %
+ l_max_util = (float) l_max_dram_databus_util / 100;
+
+ // determine the dimm power
+ // For custom dimms, use the VPD power curve data
+ if (l_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ // get number of mba's with dimms
+ // Get Centaur target for the given MBA
+ const auto l_target_chip = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ // Get MBA targets from the parent chip centaur
+ const auto l_target_mba_array = l_target_chip.getChildren<fapi2::TARGET_TYPE_MBA>();
+ l_num_mba_with_dimms = 0;
+
+ for (const auto& l_mba : l_target_mba_array)
+ {
+ const auto l_target_dimm_array = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ if (l_target_dimm_array.size() > 0)
+ {
+ l_num_mba_with_dimms++;
+ }
+ }
+
+ // add up the power from all dimms for this MBA (across both channels)
+ // for IDLE (utilization=0) and maximum utilization
+ l_channel_pair_power_idle = 0;
+ l_channel_pair_power_max = 0;
+
+ for (l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ l_channel_power_array_idle[l_port] = 0;
+ l_channel_power_array_max[l_port] = 0;
+
+ for (l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++)
+ {
+ // default dimm power is zero (used for dimms that are not physically present)
+ l_dimm_power_array_idle[l_port][l_dimm] = 0;
+ l_dimm_power_array_max[l_port][l_dimm] = 0;
+
+ // See if there are any ranks present on the dimm (configured or deconfigured)
+ if (l_dimm_ranks_array[l_port][l_dimm] > 0)
+ {
+ l_dimm_power_array_idle[l_port][l_dimm] = l_dimm_power_array_idle[l_port][l_dimm] +
+ (l_idle_util / 100 * l_total_power_slope_array[l_port][l_dimm]) + l_total_power_int_array[l_port][l_dimm];
+ l_dimm_power_array_max[l_port][l_dimm] = l_dimm_power_array_max[l_port][l_dimm] + (l_max_util / 100 *
+ l_total_power_slope_array[l_port][l_dimm]) + l_total_power_int_array[l_port][l_dimm];
+ }
+
+ // Include any system uplift here too
+ if (l_dimm_power_array_idle[l_port][l_dimm] > 0)
+ {
+ l_dimm_power_array_idle[l_port][l_dimm] =
+ l_dimm_power_array_idle[l_port][l_dimm] *
+ (1 + (float)l_power_curve_percent_uplift_idle / 100);
+ }
+
+ if (l_dimm_power_array_max[l_port][l_dimm] > 0)
+ {
+ l_dimm_power_array_max[l_port][l_dimm] =
+ l_dimm_power_array_max[l_port][l_dimm] *
+ (1 + (float)l_power_curve_percent_uplift / 100);
+ }
+
+ // calculate channel power by adding up the power of each dimm
+ l_channel_power_array_idle[l_port] = l_channel_power_array_idle[l_port] + l_dimm_power_array_idle[l_port][l_dimm];
+ l_channel_power_array_max[l_port] = l_channel_power_array_max[l_port] + l_dimm_power_array_max[l_port][l_dimm];
+ FAPI_DBG("[P%d:D%d][CH Util %4.2f/%4.2f][Slope:Int %d:%d][UpliftPercent idle/max %d/%d)][Power min/max %4.2f/%4.2f cW]",
+ l_port, l_dimm, l_idle_util, l_max_util, l_total_power_slope_array[l_port][l_dimm],
+ l_total_power_int_array[l_port][l_dimm],
+ l_power_curve_percent_uplift_idle, l_power_curve_percent_uplift, l_dimm_power_array_idle[l_port][l_dimm],
+ l_dimm_power_array_max[l_port][l_dimm]);
+ }
+
+ FAPI_DBG("[P%d][CH Util %4.2f/%4.2f][Power %4.2f/%4.2f cW]", l_port, l_min_util, l_max_util,
+ l_channel_power_array_idle[l_port], l_channel_power_array_max[l_port]);
+ l_channel_pair_power_idle = l_channel_pair_power_idle + l_channel_power_array_idle[l_port];
+ l_channel_pair_power_max = l_channel_pair_power_max + l_channel_power_array_max[l_port];
+ }
+
+ // calculate the slope/intercept values from power values just calculated above
+ l_channel_power_slope = (l_channel_pair_power_max - l_channel_pair_power_idle) / ( (l_max_util / 100) -
+ (l_idle_util / 100) );
+ l_channel_power_intercept = l_channel_pair_power_idle;
+
+ // calculate the utilization needed to be under power limit
+ l_utilization = 0;
+
+ if (l_channel_pair_watt_target > l_channel_power_intercept)
+ {
+ l_utilization = (l_channel_pair_watt_target - l_channel_power_intercept) / l_channel_power_slope * 100;
+
+ if (l_utilization > l_max_util)
+ {
+ l_utilization = l_max_util;
+ }
+ }
+
+ // Calculate the NperChip and NperMBA Throttles
+ l_throttle_n_per_chip = int((l_utilization / 100 * l_throttle_d / 4) * l_num_mba_with_dimms);
+
+ if (l_throttle_n_per_chip > (l_max_util / 100 * l_throttle_d / 4) )
+ {
+ l_throttle_n_per_mba = int((l_max_util / 100 * l_throttle_d / 4));
+ }
+ else
+ {
+ l_throttle_n_per_mba = l_throttle_n_per_chip;
+ }
+
+ // Calculate the channel power at the utilization determined
+ l_channel_pair_power = int(l_utilization / 100 * l_channel_power_slope + l_channel_power_intercept);
+
+ FAPI_DBG("[Channel Pair Power min/max %4.2f/%4.2f cW][Slope/Intercept %4.2f/%4.2f cW][Utilization Percent %4.2f, Power %d cW]",
+ l_channel_pair_power_idle, l_channel_pair_power_max, l_channel_power_slope, l_channel_power_intercept, l_utilization,
+ l_channel_pair_power);
+ }
+
+ // for non custom dimms, use hardcoded values
+ // If power limit is at or above max power, use unthrottled settings
+ // If between min and max power, use a static throttle point
+ // If below min power, return an error
+ else
+ {
+ // get number of dimms attached to this mba
+ const auto l_target_dimm_array = i_target_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+ l_number_of_dimms = l_target_dimm_array.size();
+
+ // ISDIMMs, set to a value of one since throttles are handled on a per MBA basis
+ l_num_mba_with_dimms = 1;
+
+ // MBA Power Limit is higher than dimm power, run unthrottled
+ if (l_channel_pair_watt_target >= (ISDIMM_MAX_DIMM_POWER * l_number_of_dimms))
+ {
+ l_utilization = l_max_util;
+ l_channel_pair_power = ISDIMM_MAX_DIMM_POWER * l_number_of_dimms;
+ }
+ else if (l_channel_pair_watt_target >= (ISDIMM_MIN_DIMM_POWER * l_number_of_dimms))
+ {
+ if (ISDIMM_MEMORY_THROTTLE_PERCENT > 99)
+ {
+ l_utilization = l_min_util;
+ }
+ else
+ {
+ l_utilization = l_max_util * (1 - (float)ISDIMM_MEMORY_THROTTLE_PERCENT / 100);
+ }
+
+ l_channel_pair_power = ISDIMM_MIN_DIMM_POWER * l_number_of_dimms;
+ }
+ else
+ {
+ // error case, available power less than allocated minimum dimm power
+ l_utilization = 0;
+ l_channel_pair_power = ISDIMM_MIN_DIMM_POWER * l_number_of_dimms;
+ }
+
+ l_throttle_n_per_mba = int(l_utilization / 100 * l_throttle_d / 4);
+ l_throttle_n_per_chip = l_throttle_n_per_mba;
+
+ FAPI_DBG("[Power/DIMM min/max %d/%d cW][Utilization Percent %4.2f][Number of DIMMs %d]", ISDIMM_MIN_DIMM_POWER,
+ ISDIMM_MAX_DIMM_POWER, l_utilization, l_number_of_dimms);
+
+ }
+
+ // adjust the throttles to minimum utilization if needed
+ if (l_utilization < l_min_util)
+ {
+ l_throttle_n_per_mba = int(l_min_util / 100 * l_throttle_d / 4);
+ l_throttle_n_per_chip = l_throttle_n_per_mba * l_num_mba_with_dimms;
+ }
+
+ // ensure that N throttle values are not zero, if so set to lowest values possible
+ if ( (l_throttle_n_per_mba == 0) || (l_throttle_n_per_chip == 0))
+ {
+ l_throttle_n_per_mba = 1;
+ l_throttle_n_per_chip = l_throttle_n_per_mba * l_num_mba_with_dimms;
+ }
+
+ // for better custom dimm performance for DDR4, set the per mba throttle to the per chip throttle
+ // Not planning on doing this for DDR3
+ if ( (l_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ && (l_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES) )
+ {
+ l_throttle_n_per_mba = l_throttle_n_per_chip;
+ }
+
+ // adjust the throttles to the MRW thermal limit throttles (ie. thermal/power limit less than available power)
+ if ( (l_throttle_n_per_mba > l_runtime_throttle_n_per_mba) ||
+ (l_throttle_n_per_chip > l_runtime_throttle_n_per_chip) )
+ {
+ FAPI_DBG("Throttles [%d/%d/%d] will be limited by power/thermal limit [%d/%d/%d].", l_throttle_n_per_mba,
+ l_throttle_n_per_chip, l_throttle_d, l_runtime_throttle_n_per_mba, l_runtime_throttle_n_per_chip, l_throttle_d);
+
+ if (l_throttle_n_per_mba > l_runtime_throttle_n_per_mba)
+ {
+ l_throttle_n_per_mba = l_runtime_throttle_n_per_mba;
+ }
+
+ if (l_throttle_n_per_chip > l_runtime_throttle_n_per_chip)
+ {
+ l_throttle_n_per_chip = l_runtime_throttle_n_per_chip;
+ }
+
+ }
+
+ // Calculate out the utilization at the final throttle settings
+ l_utilization = (float)l_throttle_n_per_chip * 4 / l_throttle_d / l_num_mba_with_dimms * 100;
+
+ // Calculate out the utilization at this new utilization setting for custom dimms
+ // does not matter for non custom dimms since those do not use power curves
+ if (l_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ l_channel_pair_power = int(l_utilization / 100 * l_channel_power_slope + l_channel_power_intercept);
+ }
+
+ FAPI_INF("[Available Channel Pair Power %d cW][UTIL %4.2f][Channel Pair Power %d cW]", l_channel_pair_watt_target,
+ l_utilization, l_channel_pair_power);
+ FAPI_INF("[Throttles %d/%d/%d]", l_throttle_n_per_mba, l_throttle_n_per_chip, l_throttle_d);
+
+ // Update output attributes
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA,
+ i_target_mba, l_throttle_n_per_mba));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP,
+ i_target_mba, l_throttle_n_per_chip));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_MEM_THROTTLE_DENOMINATOR,
+ i_target_mba, l_throttle_d));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_CHANNEL_PAIR_MAXPOWER,
+ i_target_mba, l_channel_pair_power));
+
+ // Check to see if there is not enough available power at l_min_util or higher
+ if (l_channel_pair_power > l_channel_pair_watt_target)
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_NOT_ENOUGH_AVAILABLE_DIMM_POWER().
+ set_PAIR_POWER(l_channel_pair_power).
+ set_PAIR_WATT_TARGET(l_channel_pair_watt_target).
+ set_MEM_MBA(i_target_mba),
+ "Not enough available memory power [Channel Pair Power %d/%d cW]", l_channel_pair_power, l_channel_pair_watt_target);
+ }
+
+ FAPI_INF("*** mss_bulk_pwr_throttles COMPLETE ***");
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+} //end extern C
+
+
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.H
new file mode 100644
index 000000000..ed67849b3
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.H
@@ -0,0 +1,58 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/// @file p9c_mss_bulk_pwr_throttles.H
+/// @brief Sets the throttle attributes based on a power limit for the dimms on the channel pair
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Mike Pardeik <pardeik@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+///
+
+#ifndef MSS_BULK_PWR_THROTTLES_H_
+#define MSS_BULK_PWR_THROTTLES_H_
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include <fapi2.H>
+
+typedef fapi2::ReturnCode (*p9c_mss_bulk_pwr_throttles_FP_t)
+(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>&
+);
+
+extern "C"
+{
+ /// @brief mss_bulk_pwr_throttles procedure. Set dimm and channel throttle attributes based on available centaur mba port power
+ /// @param[in] i_target_mba Reference to centaur mba target
+ /// @return ReturnCode
+ fapi2::ReturnCode p9c_mss_bulk_pwr_throttles(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+} // extern "C"
+
+#endif // MSS_BULK_PWR_THROTTLES_H_
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.mk
new file mode 100755
index 000000000..47a033c32
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.mk
@@ -0,0 +1,30 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_bulk_pwr_throttles.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+
+PROCEDURE=p9c_mss_bulk_pwr_throttles
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk
index 3b16d530f..16fdf0ced 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk
@@ -30,5 +30,4 @@ OBJS+=p9c_dimmBadDqBitmapFuncs.o
OBJS+=p9c_mss_unmask_errors.o
OBJS+=p9c_mss_slew.o
$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
-#lib$(PROCEDURE)_DEPLIBS+=mss
$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.C
new file mode 100644
index 000000000..bef0bebf0
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.C
@@ -0,0 +1,2678 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// @file p9c_mss_eff_config.C
+/// @brief Takes in spd and configures effective attrs
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Anuwat Saetow <asaetow@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+//------------------------------------------------------------------------------
+// My Includes
+//------------------------------------------------------------------------------
+#include <p9c_mss_eff_config.H>
+#include <p9c_mss_eff_pre_config.H>
+#include <p9c_mss_eff_config_rank_group.H>
+#include <p9c_mss_eff_config_shmoo.H>
+#include <generic/memory/lib/utils/c_str.H>
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+constexpr uint32_t MSS_EFF_EMPTY = 0;
+constexpr uint32_t MSS_EFF_VALID = 255;
+constexpr uint32_t TWO_MHZ = 2000000;
+
+extern "C"
+{
+ ///
+ /// @brief calc_timing_in_clk(): This function calculates tXX in clocks
+ /// @param[in] i_mtb_in_ps: Medium timebase in picoseconds
+ /// @param[in] i_ftb_in_fs: Fundamental timebase in femtoseconds
+ /// @param[in] i_unit: tXX value we are trying to calculate
+ /// @param[in] i_offset: Fine timebase offset
+ /// @param[in] i_mss_freq: Memory Frequency
+ /// @return l_timing_in_clk
+ ///
+ uint32_t calc_timing_in_clk(const uint32_t i_mtb_in_ps, const uint32_t i_ftb_in_fs,
+ const uint32_t i_unit, uint8_t i_offset, const uint32_t i_mss_freq)
+ {
+ uint64_t l_timing;
+ uint32_t l_timing_in_clk;
+ uint32_t l_tCK_in_ps;
+ // perform calculations
+ l_tCK_in_ps = TWO_MHZ / i_mss_freq;
+
+ if ( i_offset >= 128 )
+ {
+ i_offset = 256 - i_offset;
+ l_timing = (i_unit * i_mtb_in_ps) - (i_offset * i_ftb_in_fs);
+ }
+ else
+ {
+ l_timing = (i_unit * i_mtb_in_ps) + (i_offset * i_ftb_in_fs);
+ }
+
+ // ceiling()
+ l_timing_in_clk = l_timing / l_tCK_in_ps;
+
+ // check l_timing
+ if ( (l_timing_in_clk * l_tCK_in_ps) < l_timing )
+ {
+ l_timing_in_clk += 1;
+ }
+
+ return l_timing_in_clk;
+ } // end calc_timing_in_clk()
+
+ ///
+ /// @brief mss_eff_config_read_spd_data(): This function reads DIMM SPD data
+ /// @param[in] fapi2::Target<fapi2::TARGET_TYPE_DIMM> i_target_dimm: target dimm
+ /// @param[out] mss_eff_config_spd_data *o_spd_data: Pointer to mss_eff configuration spd data structure
+ /// @param[in] uint8_t i_port: current mba port
+ /// @param[in] uint8_t i_dimm: current mba dimm
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_read_spd_data(const fapi2::Target<fapi2::TARGET_TYPE_DIMM> i_target_dimm,
+ mss_eff_config_spd_data* o_spd_data,
+ const uint8_t i_port, const uint8_t i_dimm)
+ {
+
+ uint8_t l_spd_tb_mtb_ddr4, l_spd_tb_ftb_ddr4 = 0;
+ // Grab DIMM/SPD data.
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_DRAM_DEVICE_TYPE, i_target_dimm,
+ o_spd_data->dram_device_type[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_DEVICE_TYPE, i_target_dimm,
+ o_spd_data->sdram_device_type[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_DEVICE_TYPE_SIGNAL_LOADING, i_target_dimm,
+ o_spd_data->sdram_device_type_signal_loading[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_DIE_COUNT, i_target_dimm,
+ o_spd_data->sdram_die_count[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_TYPE, i_target_dimm,
+ o_spd_data->module_type[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_CUSTOM, i_target_dimm,
+ o_spd_data->custom[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_BANKS, i_target_dimm,
+ o_spd_data->sdram_banks[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_DENSITY, i_target_dimm,
+ o_spd_data->sdram_density[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_ROWS, i_target_dimm,
+ o_spd_data->sdram_rows[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_COLUMNS, i_target_dimm,
+ o_spd_data->sdram_columns[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_NUM_RANKS, i_target_dimm,
+ o_spd_data->num_ranks[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_DRAM_WIDTH, i_target_dimm,
+ o_spd_data->dram_width[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_MEMORY_BUS_WIDTH, i_target_dimm,
+ o_spd_data->module_memory_bus_width[i_port][i_dimm]));
+
+ if (o_spd_data->dram_device_type[i_port][i_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ // DDR3 only
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_FTB_DIVIDEND, i_target_dimm,
+ o_spd_data->ftb_dividend[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_FTB_DIVISOR, i_target_dimm,
+ o_spd_data->ftb_divisor[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MTB_DIVIDEND, i_target_dimm,
+ o_spd_data->mtb_dividend[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MTB_DIVISOR, i_target_dimm,
+ o_spd_data->mtb_divisor[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRRDMIN, i_target_dimm,
+ o_spd_data->trrdmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRFCMIN, i_target_dimm,
+ o_spd_data->trfcmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TWTRMIN, i_target_dimm,
+ o_spd_data->twtrmin[i_port][i_dimm]));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TWRMIN, i_target_dimm,
+ o_spd_data->twrmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRTPMIN, i_target_dimm,
+ o_spd_data->trtpmin[i_port][i_dimm]));
+
+ }
+ else if (o_spd_data->dram_device_type[i_port][i_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ // DDR4 only
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TIMEBASE_MTB_DDR4, i_target_dimm, l_spd_tb_mtb_ddr4));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TIMEBASE_FTB_DDR4, i_target_dimm, l_spd_tb_ftb_ddr4));
+
+ // AST HERE: !If DDR4 spec changes to include other values, this section needs to be updated!
+ FAPI_ASSERT((l_spd_tb_mtb_ddr4 == 0) && (l_spd_tb_ftb_ddr4 == 0),
+ fapi2::CEN_MSS_EFF_CONFIG_INVALID_DDR4_SPD_TB(),
+ "Invalid DDR4 MTB/FTB Timebase received from SPD attribute on %s!", mss::c_str(i_target_dimm));
+
+ // for 1000fs = 1ps = 1000 * 1 / 1
+ o_spd_data->ftb_dividend[i_port][i_dimm] = 1;
+ o_spd_data->ftb_divisor[i_port][i_dimm] = 1;
+ // for 125ps = 1000 * 1 / 8
+ o_spd_data->mtb_dividend[i_port][i_dimm] = 1;
+ o_spd_data->mtb_divisor[i_port][i_dimm] = 8;
+
+ // not available in ddr4 spd, these are replacements. need to double check
+ // 15 ns for all speeds
+ o_spd_data->twrmin[i_port][i_dimm] = 15000 / (
+ (o_spd_data->mtb_dividend[i_port][i_dimm] * 1000) /
+ o_spd_data->mtb_divisor[i_port][i_dimm]);
+
+ // 7.5ns = 7500ps; work backwards to figure out value. no FTB
+ o_spd_data->trtpmin[i_port][i_dimm] = 7500 / (
+ (o_spd_data->mtb_dividend[i_port][i_dimm] * 1000) /
+ o_spd_data->mtb_divisor[i_port][i_dimm]);
+
+ // 3 trfc values, 1x, 2x, 4x
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRFC1MIN_DDR4, i_target_dimm, o_spd_data->trfc1min[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRFC2MIN_DDR4, i_target_dimm, o_spd_data->trfc2min[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRFC4MIN_DDR4, i_target_dimm, o_spd_data->trfc4min[i_port][i_dimm]));
+
+ // ddr4 has 's' (short; different bank group) and
+ // 'l' (long; same bank group) values
+ // tRRD needs to be used by Yuen's mba initfile...
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRRDSMIN_DDR4, i_target_dimm,
+ o_spd_data->trrdsmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRRDLMIN_DDR4, i_target_dimm,
+ o_spd_data->trrdlmin[i_port][i_dimm]));
+
+ // tccdl
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TCCDLMIN_DDR4, i_target_dimm,
+ o_spd_data->tccdlmin[i_port][i_dimm]));
+
+ // should be constant based on MTB and FTB after calculations
+ o_spd_data->twtrsmin[i_port][i_dimm] = 2500 / ( // 2.5 ns
+ (o_spd_data->mtb_dividend[i_port][i_dimm] * 1000) /
+ o_spd_data->mtb_divisor[i_port][i_dimm]);
+ o_spd_data->twtrlmin[i_port][i_dimm] = 7500 / ( // 7.5 ns
+ (o_spd_data->mtb_dividend[i_port][i_dimm] * 1000) /
+ o_spd_data->mtb_divisor[i_port][i_dimm]);
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_SPD_DRAM_GEN(),
+ "Incompatable SPD DRAM generation on %s!", mss::c_str(i_target_dimm));
+ }
+
+ // Common for DDR3 and DDR4
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRCDMIN, i_target_dimm,
+ o_spd_data->trcdmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRPMIN, i_target_dimm,
+ o_spd_data->trpmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRASMIN, i_target_dimm,
+ o_spd_data->trasmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TRCMIN, i_target_dimm,
+ o_spd_data->trcmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TFAWMIN, i_target_dimm,
+ o_spd_data->tfawmin[i_port][i_dimm]));
+
+
+ // Allows feature checking
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_OPTIONAL_FEATURES, i_target_dimm,
+ o_spd_data->sdram_optional_features[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_THERMAL_AND_REFRESH_OPTIONS, i_target_dimm,
+ o_spd_data->sdram_thermal_and_refresh_options[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_THERMAL_SENSOR, i_target_dimm,
+ o_spd_data->module_thermal_sensor[i_port][i_dimm]));
+
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_FINE_OFFSET_TCKMIN, i_target_dimm,
+ o_spd_data->fine_offset_tckmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_FINE_OFFSET_TAAMIN, i_target_dimm,
+ o_spd_data->fine_offset_taamin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_FINE_OFFSET_TRCDMIN, i_target_dimm,
+ o_spd_data->fine_offset_trcdmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_FINE_OFFSET_TRPMIN, i_target_dimm,
+ o_spd_data->fine_offset_trpmin[i_port][i_dimm]));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_FINE_OFFSET_TRCMIN, i_target_dimm,
+ o_spd_data->fine_offset_trcmin[i_port][i_dimm]));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DIMM_RCD_CNTL_WORD_0_15, // Needed for RDIMM.
+ i_target_dimm,
+ o_spd_data->rdimm_rcd_cntl_word_0_15[i_port][i_dimm]));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_VERSION, i_target_dimm,
+ o_spd_data->vpd_version[i_port][i_dimm]));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ } // end of mss_eff_config_read_spd_data()
+
+ ///
+ /// @brief mss_eff_config_get_spd_data(): This function sets gathers the DIMM info then uses mss_eff_config_read_spd_data()
+ /// @param[in] i_target_mba: the fapi2 target
+ /// @param[in,out] i_mss_eff_config_data: Pointer to mss_eff_config_data variable structure
+ /// @param[out] o_spd_data: Pointer to mss_eff configuration spd data structure
+ /// @param[in] i_atts: Pointer to mss_eff config attribute structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_get_spd_data(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_data* i_mss_eff_config_data,
+ mss_eff_config_spd_data* o_spd_data,
+ mss_eff_config_atts* i_atts)
+ {
+ uint8_t l_cur_mba_port = 0;
+ uint8_t l_cur_mba_dimm = 0;
+
+ // Grab all DIMM/SPD data.
+ // initialize vpd_version
+ for(l_cur_mba_port = 0; l_cur_mba_port < MAX_PORTS_PER_MBA ; l_cur_mba_port++)
+ for(l_cur_mba_dimm = 0; l_cur_mba_dimm < MAX_DIMM_PER_PORT ; l_cur_mba_dimm++)
+ {
+ o_spd_data->vpd_version[l_cur_mba_port][l_cur_mba_dimm] = 0xFFFFFFFF;
+ }
+
+ const auto l_target_dimm_array = i_target_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ // call mss_eff_config_read_spd_data()
+ for (const auto l_dimm : l_target_dimm_array)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_PORT, l_dimm, l_cur_mba_port), "Error retrieving ATTR_MBA_PORT");
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_DIMM, l_dimm, l_cur_mba_dimm), "Error retrieving ATTR_MBA_DIMM");
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array
+ [l_cur_mba_port][l_cur_mba_dimm] = MSS_EFF_VALID;
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FUNCTIONAL,
+ l_dimm,
+ i_mss_eff_config_data->dimm_functional), "Error retrieving functional fapi2 attribute");
+
+ (i_mss_eff_config_data->dimm_functional ==
+ fapi2::ENUM_ATTR_FUNCTIONAL_FUNCTIONAL)
+ ? i_mss_eff_config_data->dimm_functional = 1
+ : i_mss_eff_config_data->dimm_functional = 0;
+ i_atts->dimm_functional_vector |=
+ i_mss_eff_config_data->dimm_functional
+ << ((4 * (1 - (l_cur_mba_port))) + (4 - (l_cur_mba_dimm)) - 1);
+
+ FAPI_TRY(mss_eff_config_read_spd_data(l_dimm,
+ o_spd_data, l_cur_mba_port, l_cur_mba_dimm), "Error reading spd data from caller");
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ } // end of mss_eff_config_get_spd_data()
+
+ ///
+ /// @brief mss_eff_config_verify_plug_rules(): This function verifies DIMM plug rules based on which dimms are present
+ /// @param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> &i_target_mba: the fapi2 target
+ /// @param[in] mss_eff_config_data *i_mss_eff_config_data: Pointer to mss_eff_config_data variable structure
+ /// @param[in] mss_eff_config_atts *i_atts: Pointer to mss_eff configuration attributes structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_verify_plug_rules(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_data* i_mss_eff_config_data,
+ mss_eff_config_atts* i_atts)
+ {
+ // Identify/Verify DIMM plug rule
+ if (
+ (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[0][0] == MSS_EFF_EMPTY)
+ &&
+ (
+ (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[0][1] == MSS_EFF_VALID)
+ ||
+ (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[1][0] == MSS_EFF_VALID)
+ ||
+ (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[1][1] == MSS_EFF_VALID)
+ )
+ )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_MISMATCH_EMPTY().
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_0_0(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][0]).
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_0_1(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][1]).
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_1_0(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][0]).
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_1_1(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][1]),
+ "Plug rule violation on %s! Port 0 Dimm 0 not valid.\n \
+ [0][0]: %d\n [0][1]: %d\n [1][0]: %d\n [1][1]: %d\n",
+ mss::c_str(i_target_mba),
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][0],
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][1],
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][0],
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][1]);
+ }
+
+ if ( (
+ ((i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[0][0] == MSS_EFF_VALID)
+ && (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[1][0] == MSS_EFF_EMPTY))
+ ||
+ ((i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[0][1] == MSS_EFF_VALID)
+ && (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[1][1] == MSS_EFF_EMPTY))
+ ) && (i_mss_eff_config_data->allow_single_port == fapi2::ENUM_ATTR_CEN_MSS_ALLOW_SINGLE_PORT_FALSE) )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_MISMATCH_SIDE().
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_0_0(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][0]).
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_0_1(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][1]).
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_1_0(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][0]).
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_1_1(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][1]),
+ "Plug rule violation on %s! Single port not allowed..\n \
+ [0][0]: %d\n [0][1]: %d\n [1][0]: %d\n [1][1]: %d\n",
+ mss::c_str(i_target_mba),
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][0],
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][1],
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][0],
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][1]);
+
+
+ }
+
+ if ( (
+ (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[0][1] == MSS_EFF_VALID)
+ || (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[1][0] == MSS_EFF_VALID)
+ || (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[1][1] == MSS_EFF_VALID)
+ ) && (i_mss_eff_config_data->allow_single_port == fapi2::ENUM_ATTR_CEN_MSS_ALLOW_SINGLE_PORT_TRUE) )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_MISMATCH_TOP().
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_0_0(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][0]).
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_0_1(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][1]).
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_1_0(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][0]).
+ set_CUR_DIMM_SPD_VALID_U8ARRAY_1_1(i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][1]),
+ "Plug rule violation on %s! Port 0 Dimm 0 not valid.\n \
+ [0][0]: %d\n [0][1]: %d\n [1][0]: %d\n [1][1]: %d\n",
+ mss::c_str(i_target_mba),
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][0],
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[0][1],
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][0],
+ i_mss_eff_config_data->cur_dimm_spd_valid_u8array[1][1]);
+ }
+
+ if ((i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[0][0] == MSS_EFF_VALID)
+ && (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[0][1] == MSS_EFF_VALID))
+ {
+ i_atts->eff_num_drops_per_port
+ = fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_DUAL;
+ }
+ else if ((i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[0][0] == MSS_EFF_VALID)
+ && (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[0][1] == MSS_EFF_EMPTY))
+ {
+ i_atts->eff_num_drops_per_port
+ = fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_SINGLE;
+ }
+ else
+ {
+ i_atts->eff_num_drops_per_port
+ = fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_EMPTY;
+ }
+
+ // end Indetify/Verify DIMM plug rule
+ fapi_try_exit:
+ return fapi2::current_err;
+ } // end of mss_eff_config_verify_plug_rules()
+
+ ///
+ /// @brief mss_eff_config_verify_spd_data(): This function verifies DIMM SPD data
+ /// @param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> &i_target_mba: the fapi2 target
+ /// @param[in] mss_eff_config_atts *i_atts: Pointer to mss_eff configuration attributes structure
+ /// @param[in] mss_eff_config_spd_data *i_data: Pointer to mss_eff configuration spd data structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_verify_spd_data(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_atts* i_atts,
+ mss_eff_config_spd_data* i_data)
+ {
+ // Start Identify/Verify/Assigning values to attributes
+ // Identify/Verify DIMM compatability
+ if (
+ (i_data->dram_device_type[0][0]
+ != i_data->dram_device_type[1][0])
+ ||
+ (
+ (i_atts->eff_num_drops_per_port
+ == fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_DUAL)
+ &&
+ (
+ (i_data->dram_device_type[0][1]
+ != i_data->dram_device_type[1][1])
+ ||
+ (i_data->dram_device_type[0][0]
+ != i_data->dram_device_type[0][1])
+ )
+ )
+ )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_GEN().
+ set_DRAM_DEVICE_TYPE_0_0( i_data->dram_device_type[0][0]).
+ set_DRAM_DEVICE_TYPE_0_1( i_data->dram_device_type[0][1]).
+ set_DRAM_DEVICE_TYPE_1_0( i_data->dram_device_type[1][0]).
+ set_DRAM_DEVICE_TYPE_1_1( i_data->dram_device_type[1][1]),
+ "Incompatable DRAM generation on %s!",
+ mss::c_str(i_target_mba));
+ }
+
+ if (
+ (i_data->module_type[0][0]
+ != i_data->module_type[1][0])
+ ||
+ (
+ (i_atts->eff_num_drops_per_port
+ == fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_DUAL)
+ &&
+ (
+ (i_data->module_type[0][1]
+ != i_data->module_type[1][1])
+ ||
+ (i_data->module_type[0][0]
+ != i_data->module_type[0][1])
+ )
+ )
+ )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DIMM_TYPE().
+ set_MODULE_TYPE_0_0(i_data->module_type[0][0]).
+ set_MODULE_TYPE_0_1(i_data->module_type[0][1]).
+ set_MODULE_TYPE_1_0(i_data->module_type[1][0]).
+ set_MODULE_TYPE_1_1(i_data->module_type[1][1]),
+ "Incompatable DIMM type on %s!", mss::c_str(i_target_mba));
+ }
+
+ if (
+ (i_data->num_ranks[0][0]
+ != i_data->num_ranks[1][0])
+ ||
+ (
+ (i_atts->eff_num_drops_per_port
+ == fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_DUAL)
+ &&
+ (
+ (i_data->num_ranks[0][1]
+ != i_data->num_ranks[1][1])
+ ||
+ (i_data->num_ranks[0][0]
+ != i_data->num_ranks[0][1])
+ )
+ )
+ )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DIMM_RANKS().
+ set_NUM_RANKS_0_0(i_data->num_ranks[0][0]).
+ set_NUM_RANKS_0_1(i_data->num_ranks[0][1]).
+ set_NUM_RANKS_1_0(i_data->num_ranks[1][0]).
+ set_NUM_RANKS_1_1(i_data->num_ranks[1][1]),
+ "Incompatable DIMM ranks on %s!", mss::c_str(i_target_mba));
+ }
+
+ if (
+ (i_data->sdram_banks[0][0]
+ != i_data->sdram_banks[1][0])
+ ||
+ (
+ (i_atts->eff_num_drops_per_port
+ == fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_DUAL)
+ &&
+ (
+ (i_data->sdram_banks[0][1]
+ != i_data->sdram_banks[1][1])
+ ||
+ (i_data->sdram_banks[0][0]
+ != i_data->sdram_banks[0][1])
+ )
+ )
+ )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DIMM_BANKS().
+ set_SDRAM_BANKS_0_0(i_data->sdram_banks[0][0]).
+ set_SDRAM_BANKS_0_1(i_data->sdram_banks[0][1]).
+ set_SDRAM_BANKS_1_0(i_data->sdram_banks[1][0]).
+ set_SDRAM_BANKS_1_1(i_data->sdram_banks[1][1]),
+ "Incompatable DIMM banks on %s!", mss::c_str(i_target_mba));
+ }
+
+ if (
+ (i_data->sdram_rows[0][0]
+ != i_data->sdram_rows[1][0])
+ ||
+ (
+ (i_atts->eff_num_drops_per_port
+ == fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_DUAL)
+ &&
+ (
+ (i_data->sdram_rows[0][1]
+ != i_data->sdram_rows[1][1])
+ ||
+ (i_data->sdram_rows[0][0]
+ != i_data->sdram_rows[0][1])
+ )
+ )
+ )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DIMM_ROWS().
+ set_SDRAM_ROWS_0_0( i_data->sdram_rows[0][0]).
+ set_SDRAM_ROWS_0_1(i_data->sdram_rows[0][1]).
+ set_SDRAM_ROWS_1_0(i_data->sdram_rows[1][0]).
+ set_SDRAM_ROWS_1_1(i_data->sdram_rows[1][1]),
+ "Incompatable DIMM rows on %s!", mss::c_str(i_target_mba));
+ }
+
+ if (
+ (i_data->sdram_columns[0][0]
+ != i_data->sdram_columns[1][0])
+ ||
+ (
+ (i_atts->eff_num_drops_per_port
+ == fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_DUAL)
+ &&
+ (
+ (i_data->sdram_columns[0][1]
+ != i_data->sdram_columns[1][1])
+ ||
+ (i_data->sdram_columns[0][0]
+ != i_data->sdram_columns[0][1])
+ )
+ )
+ )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DIMM_COLUMNS().
+ set_SDRAM_COLS_0_0(i_data->sdram_columns[0][0]).
+ set_SDRAM_COLS_0_1(i_data->sdram_columns[0][1]).
+ set_SDRAM_COLS_1_0(i_data->sdram_columns[1][0]).
+ set_SDRAM_COLS_1_1(i_data->sdram_columns[1][1]),
+ "Incompatable DIMM cols on %s!", mss::c_str(i_target_mba));
+ }
+
+ if (
+ (i_data->module_memory_bus_width[0][0]
+ != i_data->module_memory_bus_width[1][0])
+ ||
+ (
+ (i_atts->eff_num_drops_per_port
+ == fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_DUAL)
+ &&
+ (
+ (i_data->module_memory_bus_width[0][1]
+ != i_data->module_memory_bus_width[1][1])
+ ||
+ (i_data->module_memory_bus_width[0][0]
+ != i_data->module_memory_bus_width[0][1])
+ )
+ )
+ )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_BUS_WIDTH().
+ set_BUS_WIDTH_0_0( i_data->module_memory_bus_width[0][0]).
+ set_BUS_WIDTH_0_1( i_data->module_memory_bus_width[0][1]).
+ set_BUS_WIDTH_1_0( i_data->module_memory_bus_width[1][0]).
+ set_BUS_WIDTH_1_1( i_data->module_memory_bus_width[1][1]),
+ "Incompatable DRAM primary bus width on %s!",
+ mss::c_str(i_target_mba));
+ }
+
+ // ATTR_SPD_MODULE_MEMORY_BUS_WIDTH, SPD byte8[4:3], only 64bit with ECC extension is allowed
+ if ( i_data->module_memory_bus_width[0][0] !=
+ fapi2::ENUM_ATTR_CEN_SPD_MODULE_MEMORY_BUS_WIDTH_WE64 )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_UNSUPPORTED_MODULE_MEMORY_BUS_WIDTH().
+ set_MODULE_MEMORY_BUS_WIDTH( i_data->module_memory_bus_width[0][0]),
+ "Unsupported DRAM bus width on %s!",
+ mss::c_str(i_target_mba));
+ }
+
+ if (
+ (i_data->dram_width[0][0]
+ != i_data->dram_width[1][0])
+ ||
+ (
+ (i_atts->eff_num_drops_per_port
+ == fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_DUAL)
+ &&
+ (
+ (i_data->dram_width[0][1]
+ != i_data->dram_width[1][1])
+ ||
+ (i_data->dram_width[0][0]
+ != i_data->dram_width[0][1])
+ )
+ )
+ )
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_WIDTH().
+ set_DRAM_WIDTH_0_0(i_data->dram_width[0][0]).
+ set_DRAM_WIDTH_0_1(i_data->dram_width[0][1]).
+ set_DRAM_WIDTH_1_0(i_data->dram_width[1][0]).
+ set_DRAM_WIDTH_1_1(i_data->dram_width[1][1]),
+ "Incompatable DRAM width on %s!", mss::c_str(i_target_mba));
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ } // end of mss_eff_config_verify_spd_data()
+
+ ///
+ /// @brief mss_eff_config_setup_eff_atts(): This function sets up the effective configuration attributes
+ /// @param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> &i_target_mba: the fapi2 target
+ /// @param[in] mss_eff_config_data *i_mss_eff_config_data: Pointer to mss_eff_config_data variable structure
+ /// @param[in] mss_eff_config_spd_data *i_data: Pointer to mss_eff configuration spd data structure
+ /// @param[in,out] mss_eff_config_atts *o_atts: Pointer to mss_eff configuration attributes structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_setup_eff_atts(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_data* i_mss_eff_config_data,
+ mss_eff_config_spd_data* i_data,
+ mss_eff_config_atts* o_atts)
+ {
+ uint8_t l_vpd_dram_address_mirroring[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_mss_dram_2n_mode_enable = 0;
+ uint8_t l_attr_vpd_dram_wrddr4_vref[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_mss_power_control_requested = 0;
+ uint32_t l_rdimm_rcd_ibt[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_rdimm_rcd_output_timing[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_die_count = 1;
+ uint8_t l_ranks_3d_tsv = 0;
+ uint8_t l_allow_port_size = 1;
+ const uint8_t l_min_delay_clocks = 4;
+ uint32_t l_max_delay = 0; // in ps
+ uint8_t l_speed_idx = 0;
+ uint8_t l_width_idx = 0;
+ const uint64_t l_rcd_hardcode_mask = 0xDFFFFFFFF2FFFFFFLL;
+ uint64_t l_mss_freq_mask = 0xFFFFFFFFFF8FFFFFLL;
+ uint64_t l_mss_volt_mask = 0xFFFFFFFFFFFCFFFFLL;
+ uint64_t l_rcd_ibt_mask = 0xFFBFFFFF8FFFFFFFLL;
+ uint64_t l_rcd_output_timing_mask = 0xFFDFFFFFFFFFFFFFLL;
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRAM_ADDRESS_MIRRORING, i_target_mba, l_vpd_dram_address_mirroring));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRAM_2N_MODE_ENABLED, i_target_mba, l_mss_dram_2n_mode_enable));
+ // DDR4 Vref
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRAM_WRDDR4_VREF, i_target_mba, l_attr_vpd_dram_wrddr4_vref));
+ // Transfer powerdown request from system attr to DRAM attr
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_POWER_CONTROL_REQUESTED, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_mss_power_control_requested));
+
+ if ( l_mss_power_control_requested == fapi2::ENUM_ATTR_CEN_MRW_POWER_CONTROL_REQUESTED_FASTEXIT)
+ {
+ o_atts->eff_dram_dll_ppd = fapi2::ENUM_ATTR_CEN_EFF_DRAM_DLL_PPD_FASTEXIT;
+ }
+ else
+ {
+ o_atts->eff_dram_dll_ppd =
+ fapi2::ENUM_ATTR_CEN_EFF_DRAM_DLL_PPD_SLOWEXIT; // if "OFF" default to SLOWEXIT, FASTEXIT settings in mba_def.initfile are causing fails. Workaround to use SLOWEXIT.
+ }
+
+ o_atts->eff_dram_dll_reset = fapi2::ENUM_ATTR_CEN_EFF_DRAM_DLL_RESET_YES; // Always reset DLL at start of IPL.
+ o_atts->eff_dram_srt = fapi2::ENUM_ATTR_CEN_EFF_DRAM_SRT_EXTEND; // Always use extended operating temp range.
+ o_atts->mss_cal_step_enable = 0xFF; // Always run all cal steps
+
+ // array init
+ for(uint8_t i = 0; i < MAX_PORTS_PER_MBA; i++)
+ {
+ for(uint8_t j = 0; j < MAX_DIMM_PER_PORT; j++)
+ {
+ // i <-> MAX_PORTS_PER_MBA, j <-> MAX_DIMM_PER_PORT
+ o_atts->eff_stack_type[i][j] = 0;
+ o_atts->eff_ibm_type[i][j] = 0;
+ }
+ }
+
+ // Assigning values to attributes
+//------------------------------------------------------------------------------
+ o_atts->eff_schmoo_wr_eye_min_margin = 70;
+ o_atts->eff_schmoo_rd_eye_min_margin = 70;
+ o_atts->eff_schmoo_dqs_clk_min_margin = 140;
+ o_atts->eff_schmoo_rd_gate_min_margin = 100;
+ o_atts->eff_schmoo_addr_cmd_min_margin = 140;
+
+//------------------------------------------------------------------------------
+ switch(i_data->dram_device_type[0][0])
+ {
+ case fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3:
+ o_atts->eff_dram_gen = fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR3;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4:
+ o_atts->eff_dram_gen = fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4;
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_DRAM_DEVICE_ERROR().
+ set_DRAM_DEVICE_TYPE(i_data->dram_device_type[0][0]),
+ "Unknown DRAM type on %s!", mss::c_str(i_target_mba));
+ }
+
+//------------------------------------------------------------------------------
+ switch(i_data->module_type[0][0])
+ {
+ // Removed CDIMM as a valid EFF_DIMM_TYPE.
+ //case fapi2::ENUM_ATTR_CEN_SPD_MODULE_TYPE_CDIMM:
+ // o_atts->eff_dimm_type = fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_CDIMM;
+ // FAPI_INF("WARNING: ATTR_SPD_MODULE_TYPE_CDIMM is obsolete. Check your VPD for correct definition on %s!", mss::c_str(i_target_mba));
+ // break;
+ case fapi2::ENUM_ATTR_CEN_SPD_MODULE_TYPE_RDIMM:
+ o_atts->eff_dimm_type = fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_MODULE_TYPE_UDIMM:
+ o_atts->eff_dimm_type = fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_UDIMM;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_MODULE_TYPE_LRDIMM:
+ o_atts->eff_dimm_type = fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM;
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_MOD_TYPE_ERROR().
+ set_MOD_TYPE(i_data->module_type[0][0]),
+ "Unknown DIMM type on %s!", mss::c_str(i_target_mba));
+ }
+
+//------------------------------------------------------------------------------
+ if ( o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM )
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DIMM_RCD_IBT, i_target_mba, l_rdimm_rcd_ibt));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DIMM_RCD_OUTPUT_TIMING, i_target_mba, l_rdimm_rcd_output_timing));
+
+ }
+
+//------------------------------------------------------------------------------
+ if(i_data->custom[0][0] == fapi2::ENUM_ATTR_CEN_SPD_CUSTOM_YES)
+ {
+ o_atts->eff_custom_dimm = fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES;
+ }
+ else
+ {
+ o_atts->eff_custom_dimm = fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_NO;
+ }
+
+//------------------------------------------------------------------------------
+ switch(i_data->sdram_banks[0][0])
+ {
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_BANKS_B4:
+ o_atts->eff_dram_banks = 4; // DDR4 only
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_BANKS_B8:
+ o_atts->eff_dram_banks = 8;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_BANKS_B16:
+ o_atts->eff_dram_banks = 16;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_BANKS_B32:
+ o_atts->eff_dram_banks = 32;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_BANKS_B64:
+ o_atts->eff_dram_banks = 64;
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_SDRAM_BANK_ERROR().
+ set_SDRAM_BANKS(i_data->sdram_banks[0][0]),
+ "Unknown DRAM banks on %s!", mss::c_str(i_target_mba));
+ }
+
+//------------------------------------------------------------------------------
+ switch (i_data->sdram_rows[0][0])
+ {
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_ROWS_R12:
+ o_atts->eff_dram_rows = 12;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_ROWS_R13:
+ o_atts->eff_dram_rows = 13;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_ROWS_R14:
+ o_atts->eff_dram_rows = 14;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_ROWS_R15:
+ o_atts->eff_dram_rows = 15;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_ROWS_R16:
+ o_atts->eff_dram_rows = 16;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_ROWS_R17:
+ o_atts->eff_dram_rows = 17;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_ROWS_R18:
+ o_atts->eff_dram_rows = 18;
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_SDRAM_ROWS_ERROR().
+ set_SDRAM_ROWS(i_data->sdram_rows[0][0]),
+ "Unknown DRAM rows on %s!", mss::c_str(i_target_mba));
+ }
+
+//------------------------------------------------------------------------------
+ switch (i_data->sdram_columns[0][0])
+ {
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_COLUMNS_C9:
+ o_atts->eff_dram_cols = 9;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_COLUMNS_C10:
+ o_atts->eff_dram_cols = 10;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_COLUMNS_C11:
+ o_atts->eff_dram_cols = 11;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_SPD_SDRAM_COLUMNS_C12:
+ o_atts->eff_dram_cols = 12;
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_SDRAM_COLS_ERROR().
+ set_SDRAM_COLS(i_data->sdram_columns[0][0]),
+ "Unknown DRAM cols on %s!", mss::c_str(i_target_mba));
+ }
+
+//------------------------------------------------------------------------------
+ if (i_data->dram_width[0][0]
+ == fapi2::ENUM_ATTR_CEN_SPD_DRAM_WIDTH_W4)
+ {
+ o_atts->eff_dram_width = fapi2::ENUM_ATTR_CEN_EFF_DRAM_WIDTH_X4;
+ o_atts->eff_dram_tdqs = fapi2::ENUM_ATTR_CEN_EFF_DRAM_TDQS_DISABLE;
+ }
+ else if (i_data->dram_width[0][0]
+ == fapi2::ENUM_ATTR_CEN_SPD_DRAM_WIDTH_W8)
+ {
+ o_atts->eff_dram_width = fapi2::ENUM_ATTR_CEN_EFF_DRAM_WIDTH_X8;
+
+ // NOTE: TDQS enable MR1(A11) is only avaliable for X8 in DDR3
+ // TDQS disabled for X8 DDR3 CDIMM, enable for ISDIMM
+ if ( o_atts->eff_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_NO )
+ {
+ o_atts->eff_dram_tdqs = fapi2::ENUM_ATTR_CEN_EFF_DRAM_TDQS_ENABLE;
+ }
+ else
+ {
+ o_atts->eff_dram_tdqs = fapi2::ENUM_ATTR_CEN_EFF_DRAM_TDQS_DISABLE;
+ }
+ }
+ else if (i_data->dram_width[0][0]
+ == fapi2::ENUM_ATTR_CEN_SPD_DRAM_WIDTH_W16)
+ {
+ o_atts->eff_dram_width = fapi2::ENUM_ATTR_CEN_EFF_DRAM_WIDTH_X16;
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_DRAM_WIDTH_16_ERROR(),
+ "Unsupported DRAM width x16 on %s!",
+ mss::c_str(i_target_mba));
+ }
+ else if (i_data->dram_width[0][0]
+ == fapi2::ENUM_ATTR_CEN_SPD_DRAM_WIDTH_W32)
+ {
+ o_atts->eff_dram_width = fapi2::ENUM_ATTR_CEN_EFF_DRAM_WIDTH_X32;
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_DRAM_WIDTH_32_ERROR(),
+ "Unsupported DRAM width x32 on %s!",
+ mss::c_str(i_target_mba));
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_DRAM_WIDTH_ERROR(),
+ "Unknown DRAM width on %s!", mss::c_str(i_target_mba));
+ }
+
+//------------------------------------------------------------------------------
+ o_atts->eff_dram_density = 16;
+
+ if (i_mss_eff_config_data->allow_single_port == fapi2::ENUM_ATTR_CEN_MSS_ALLOW_SINGLE_PORT_FALSE)
+ {
+ l_allow_port_size = MAX_PORTS_PER_MBA;
+ }
+
+ for (uint8_t l_cur_mba_port = 0; l_cur_mba_port < l_allow_port_size; l_cur_mba_port += 1)
+ {
+ for (uint8_t l_cur_mba_dimm = 0; l_cur_mba_dimm <
+ o_atts->eff_num_drops_per_port; l_cur_mba_dimm += 1)
+ {
+ if (i_data->sdram_density[l_cur_mba_port]
+ [l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DENSITY_D16GB)
+ {
+ i_mss_eff_config_data->cur_dram_density = 16;
+ }
+ else if (i_data->sdram_density[l_cur_mba_port]
+ [l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DENSITY_D8GB)
+ {
+ i_mss_eff_config_data->cur_dram_density = 8;
+ }
+ else if (i_data->sdram_density[l_cur_mba_port]
+ [l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DENSITY_D4GB)
+ {
+ i_mss_eff_config_data->cur_dram_density = 4;
+ }
+ else if (i_data->sdram_density[l_cur_mba_port]
+ [l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DENSITY_D2GB)
+ {
+ i_mss_eff_config_data->cur_dram_density = 2;
+ }
+ else if (i_data->sdram_density[l_cur_mba_port]
+ [l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DENSITY_D1GB)
+ {
+ i_mss_eff_config_data->cur_dram_density = 1;
+ }
+ else
+ {
+ i_mss_eff_config_data->cur_dram_density = 1;
+ FAPI_ASSERT(i_mss_eff_config_data->allow_single_port != fapi2::ENUM_ATTR_CEN_MSS_ALLOW_SINGLE_PORT_FALSE,
+ fapi2::CEN_MSS_EFF_CONFIG_DRAM_DENSITY_ERR().
+ set_SDRAM_DENSITY(i_data->sdram_density[l_cur_mba_port][l_cur_mba_dimm]),
+ "Unsupported DRAM density on %s!",
+ mss::c_str(i_target_mba));
+ }
+
+//------------------------------------------------------------------------------
+ if (o_atts->eff_dram_density >
+ i_mss_eff_config_data->cur_dram_density)
+ {
+ o_atts->eff_dram_density =
+ i_mss_eff_config_data->cur_dram_density;
+ }
+
+//------------------------------------------------------------------------------
+ // Identify/Verify DIMM voltage compatability
+ // See mss_volt.C
+//------------------------------------------------------------------------------
+ // Identify/Assign minimum timing
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm] =
+ (i_data->mtb_dividend[l_cur_mba_port]
+ [l_cur_mba_dimm] * 1000)
+ /
+ i_data->mtb_divisor[l_cur_mba_port]
+ [l_cur_mba_dimm];
+//------------------------------------------------------------------------------
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm] =
+ (i_data->ftb_dividend[l_cur_mba_port]
+ [l_cur_mba_dimm] * 1000)
+ /
+ i_data->ftb_divisor[l_cur_mba_port]
+ [l_cur_mba_dimm];
+//------------------------------------------------------------------------------
+ // Calculate CL
+ // See mss_freq.C
+ // call calc_timing_in_clk()
+ i_mss_eff_config_data->dram_wr = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->twrmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+
+ );
+
+ if (i_mss_eff_config_data->dram_wr > o_atts->eff_dram_wr)
+ {
+ o_atts->eff_dram_wr = i_mss_eff_config_data->dram_wr;
+ }
+
+//------------------------------------------------------------------------------
+ // call calc_timing_in_clk()
+ i_mss_eff_config_data->dram_trcd = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->trcdmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->fine_offset_trcdmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->mss_freq
+ );
+
+ if (i_mss_eff_config_data->dram_trcd >
+ o_atts->eff_dram_trcd)
+ {
+ o_atts->eff_dram_trcd =
+ i_mss_eff_config_data->dram_trcd;
+ }
+
+//------------------------------------------------------------------------------
+ if (i_data->dram_device_type[0][0] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ // DDR3
+ i_mss_eff_config_data->dram_trrd = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->trrdmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+
+ if (i_mss_eff_config_data->dram_trrd >
+ o_atts->eff_dram_trrd)
+ {
+ o_atts->eff_dram_trrd =
+ i_mss_eff_config_data->dram_trrd;
+ }
+ }
+ else if (i_data->dram_device_type[0][0] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ // DDR4
+ FAPI_INF("DDR4 Check: spd tRRDs=0x%x, tRRDl=0x%x, mtb=%i, ftb=%i, width=%i",
+ i_data->trrdsmin[l_cur_mba_port][l_cur_mba_dimm],
+ i_data->trrdlmin[l_cur_mba_port][l_cur_mba_dimm],
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port][l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port][l_cur_mba_dimm],
+ o_atts->eff_dram_width);
+ // bool is_2K_page = 0;
+
+ // get the spd min trrd in clocks
+ i_mss_eff_config_data->dram_trrd = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port][l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port][l_cur_mba_dimm],
+ i_data->trrdsmin[l_cur_mba_port][l_cur_mba_dimm],
+ 0, // need to put in the trrdsmin_ftb here...
+ i_mss_eff_config_data->mss_freq
+ );
+
+ // trrdsmin from SPD is absolute min of DIMM.
+ // need to know page size, then use 6ns for (2k page) otherwise 5ns
+
+ FAPI_INF("DDR4 Check: i_tRRD_s(nCK) = %i", i_mss_eff_config_data->dram_trrd);
+ FAPI_INF("Attribute o_eff_dram_trrd = %i", o_atts->eff_dram_trrd);
+ // need a table here for other speeds/page sizes
+
+ // trrd_s = 2K page @ 1600, max(4nCK,6ns) since min nCK=1.25ns, const 6ns
+ // 1/2 or 1K page @ 1600, max(4nCK, 5ns)
+
+ // 1600 1866 2133 2400 (data rate)
+ // 6, 5.3, 5.3, 5.3 ns for 2k page size (x16)
+ // 5, 4.2, 3.7, 3.3 ns for 0.5k or 1k page size (x8)
+ // !! NOTE !! NOT supporting 2k page size (with check for width above should cause error out).
+
+ if (i_mss_eff_config_data->mss_freq < 1733) // 1600
+ {
+ l_max_delay = 5000; // in ps
+ }
+ else if (i_mss_eff_config_data->mss_freq < 2000) // 1866
+ {
+ l_max_delay = 4200; // in ps
+ }
+ else if (i_mss_eff_config_data->mss_freq < 2267) // 2133
+ {
+ l_max_delay = 3700; // in ps
+ }
+ else // if (i_mss_eff_config_data->mss_freq < 2533) // 2400
+ {
+ l_max_delay = 3300; // in ps
+ }
+
+ uint8_t l_max_delay_clocks = calc_timing_in_clk
+ (1, 0, l_max_delay, 0, i_mss_eff_config_data->mss_freq);
+
+ // find max between l_min_delay_clocks, l_max_delay_clocks and dev_min
+
+ if (l_min_delay_clocks > l_max_delay_clocks)
+ {
+ l_max_delay_clocks = l_min_delay_clocks;
+ }
+
+ if (i_mss_eff_config_data->dram_trrd > l_max_delay_clocks)
+ {
+ l_max_delay_clocks = i_mss_eff_config_data->dram_trrd;
+ }
+
+ if (l_max_delay_clocks > o_atts->eff_dram_trrd)
+ {
+ o_atts->eff_dram_trrd = l_max_delay_clocks;
+ }
+
+//---------------------------------------------------------------------------------------
+// trrd_l = max(4nCK,7.5ns)
+ // 1600 1866 2133 2400 (data rate)
+ // 7.5 6.4, 6.4, 6.4 ns for 2k page size (x16)
+ // 6, 5.3, 5.3, 4.9 ns for 0.5k or 1k page size (x8)
+ // !! NOTE !! NOT supporting 2k page size (with check for width above should cause error out).
+ i_mss_eff_config_data->dram_trrdl = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port][l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port][l_cur_mba_dimm],
+ i_data->trrdlmin[l_cur_mba_port][l_cur_mba_dimm],
+ 0, // need to put in the trrdlmin_ftb here...
+ i_mss_eff_config_data->mss_freq
+ );
+
+ // condense this later with the if/else above...
+ if (i_mss_eff_config_data->mss_freq < 1733) // 1600
+ {
+ l_max_delay = 6000; // in ps
+ }
+ else if (i_mss_eff_config_data->mss_freq < 2000) // 1866
+ {
+ l_max_delay = 5300; // in ps
+ }
+ else if (i_mss_eff_config_data->mss_freq < 2267) // 2133
+ {
+ l_max_delay = 5300; // in ps
+ }
+ else // if (i_mss_eff_config_data->mss_freq < 2533) // 2400
+ {
+ l_max_delay = 4900; // in ps
+ }
+
+ l_max_delay_clocks = calc_timing_in_clk
+ (1, 0, l_max_delay, 0, i_mss_eff_config_data->mss_freq);
+
+ if (l_max_delay_clocks > o_atts->eff_dram_trrdl)
+ {
+ o_atts->eff_dram_trrdl = l_max_delay_clocks;
+ }
+ else if (i_mss_eff_config_data->dram_trrdl > o_atts->eff_dram_trrdl)
+ {
+ o_atts->eff_dram_trrdl = i_mss_eff_config_data->dram_trrdl;
+ }
+
+ FAPI_INF("DDR4 tRRDs = %i, tRRDl = %i", o_atts->eff_dram_trrd, o_atts->eff_dram_trrdl);
+
+ // DDR4 Vref DQ Train
+ for (uint8_t l_cur_mba_rank = 0; l_cur_mba_rank < MAX_RANKS_PER_DIMM; l_cur_mba_rank += 1)
+ {
+ o_atts->eff_vref_dq_train_enable[l_cur_mba_port][l_cur_mba_dimm][l_cur_mba_rank] =
+ fapi2::ENUM_ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE_DISABLE;
+
+ //VREF DQ range is set to 1 -> range 2
+ if (l_attr_vpd_dram_wrddr4_vref[l_cur_mba_port] & 0x40)
+ {
+ o_atts->eff_vref_dq_train_range[l_cur_mba_port][l_cur_mba_dimm][l_cur_mba_rank] =
+ fapi2::ENUM_ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE_RANGE2;
+ }
+ else
+ {
+ o_atts->eff_vref_dq_train_range[l_cur_mba_port][l_cur_mba_dimm][l_cur_mba_rank] =
+ fapi2::ENUM_ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE_RANGE1;
+ }
+
+ o_atts->eff_vref_dq_train_value[l_cur_mba_port][l_cur_mba_dimm][l_cur_mba_rank] =
+ l_attr_vpd_dram_wrddr4_vref[l_cur_mba_port] & 0x3f;
+ }
+
+ // DDR4 controls/features
+ o_atts->eff_cs_cmd_latency = fapi2::ENUM_ATTR_CEN_EFF_CS_CMD_LATENCY_DISABLE;
+ o_atts->eff_mpr_page = 0;
+ o_atts->eff_mpr_page = 0;
+ o_atts->eff_dram_lpasr = fapi2::ENUM_ATTR_CEN_EFF_DRAM_LPASR_MANUAL_NORMAL;
+ o_atts->eff_geardown_mode = fapi2::ENUM_ATTR_CEN_EFF_GEARDOWN_MODE_HALF;
+ o_atts->eff_per_dram_access = fapi2::ENUM_ATTR_CEN_EFF_PER_DRAM_ACCESS_DISABLE;
+ o_atts->eff_temp_readout = fapi2::ENUM_ATTR_CEN_EFF_TEMP_READOUT_DISABLE;
+
+ //Preet --- ISDIMM based System = 4X Refresh and CDIMMs - Normal as per warren
+ if((o_atts->eff_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ && (o_atts->eff_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4))
+ {
+ o_atts->eff_fine_refresh_mode = fapi2::ENUM_ATTR_CEN_EFF_FINE_REFRESH_MODE_NORMAL;
+ }
+ else
+ {
+ o_atts->eff_fine_refresh_mode = fapi2::ENUM_ATTR_CEN_EFF_FINE_REFRESH_MODE_NORMAL;
+ }
+
+ o_atts->eff_mpr_rd_format = fapi2::ENUM_ATTR_CEN_EFF_MPR_RD_FORMAT_SERIAL;
+ o_atts->eff_max_powerdown_mode = fapi2::ENUM_ATTR_CEN_EFF_MAX_POWERDOWN_MODE_DISABLE;
+ o_atts->eff_temp_ref_range = fapi2::ENUM_ATTR_CEN_EFF_TEMP_REF_RANGE_NORMAL;
+ o_atts->eff_temp_ref_mode = fapi2::ENUM_ATTR_CEN_EFF_TEMP_REF_MODE_DISABLE;
+ o_atts->eff_int_vref_mon = fapi2::ENUM_ATTR_CEN_EFF_INT_VREF_MON_DISABLE;
+ o_atts->eff_self_ref_abort = fapi2::ENUM_ATTR_CEN_EFF_SELF_REF_ABORT_DISABLE;
+ o_atts->eff_rd_preamble_train = fapi2::ENUM_ATTR_CEN_EFF_RD_PREAMBLE_TRAIN_DISABLE;
+ o_atts->eff_rd_preamble = fapi2::ENUM_ATTR_CEN_EFF_RD_PREAMBLE_1NCLK;
+ o_atts->eff_wr_preamble = fapi2::ENUM_ATTR_CEN_EFF_WR_PREAMBLE_1NCLK;
+ o_atts->eff_odt_input_buff = fapi2::ENUM_ATTR_CEN_EFF_ODT_INPUT_BUFF_ACTIVATED;
+ o_atts->eff_data_mask = fapi2::ENUM_ATTR_CEN_EFF_DATA_MASK_DISABLE;
+ o_atts->eff_write_dbi = fapi2::ENUM_ATTR_CEN_EFF_WRITE_DBI_DISABLE;
+ o_atts->eff_read_dbi = fapi2::ENUM_ATTR_CEN_EFF_READ_DBI_DISABLE;
+ o_atts->eff_ca_parity = fapi2::ENUM_ATTR_CEN_EFF_CA_PARITY_DISABLE;
+ o_atts->eff_ca_parity_latency = fapi2::ENUM_ATTR_CEN_EFF_CA_PARITY_LATENCY_DISABLE;
+ o_atts->eff_ca_parity_error_status = fapi2::ENUM_ATTR_CEN_EFF_CA_PARITY_ERROR_STATUS_CLEAR;
+ o_atts->eff_write_crc = (fapi2::ENUM_ATTR_CEN_EFF_WRITE_CRC_DISABLE);
+ o_atts->eff_crc_wr_latency = fapi2::ENUM_ATTR_CEN_EFF_CRC_WR_LATENCY_4NCK;
+ o_atts->eff_crc_error_clear = fapi2::ENUM_ATTR_CEN_EFF_CRC_ERROR_CLEAR_CLEAR;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_GEN().
+ set_DRAM_DEVICE_TYPE_0_0(i_data->dram_device_type[0][0]).
+ set_DRAM_DEVICE_TYPE_0_1(i_data->dram_device_type[0][1]).
+ set_DRAM_DEVICE_TYPE_1_0(i_data->dram_device_type[1][0]).
+ set_DRAM_DEVICE_TYPE_1_1(i_data->dram_device_type[1][1]),
+ "Incompatable DRAM generation on %s!", mss::c_str(i_target_mba));
+ }
+
+//------------------------------------------------------------------------------
+ if (i_data->dram_device_type[0][0] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+
+ //Fixed DDR4 tCCD_L = 5ck @1600Mbps and ignore SPD completely per Warren Maule.
+ //Note: This is to always be in sync with mba_def.initfile since it's not using attributes for tCCD.
+ //Note: Currently mba_def.initfile v1.83 has DDR4 tCCD_S = 4ck and tCCD_L = 5ck @1600Mbps&1866Mbps, 6ck @2133Mbps&2400Mbps. If that ever changes mss_eff_config.C will also need to change to match.
+ if ((i_mss_eff_config_data->mss_freq == 1600) || (i_mss_eff_config_data->mss_freq == 1866))
+ {
+ o_atts->eff_dram_tccdl = 5;
+ }
+ else if ((i_mss_eff_config_data->mss_freq == 2133) || (i_mss_eff_config_data->mss_freq == 2400))
+ {
+ o_atts->eff_dram_tccdl = 6;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_MSS_FREQ().
+ set_FREQ_VAL(i_mss_eff_config_data->mss_freq),
+ "Invalid ATTR_MSS_FREQ = %d on %s!", i_mss_eff_config_data->mss_freq, mss::c_str(i_target_mba));
+ }
+
+ }
+
+ i_mss_eff_config_data->dram_trp = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->trpmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->fine_offset_trpmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->mss_freq
+ );
+
+ if (i_mss_eff_config_data->dram_trp > o_atts->eff_dram_trp)
+ {
+ o_atts->eff_dram_trp = i_mss_eff_config_data->dram_trp;
+ }
+
+ if (i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ i_mss_eff_config_data->dram_twtr = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->twtrmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+
+ if (i_mss_eff_config_data->dram_twtr > o_atts->eff_dram_twtr)
+ {
+ o_atts->eff_dram_twtr = i_mss_eff_config_data->dram_twtr;
+ }
+ }
+ else if (i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ i_mss_eff_config_data->dram_twtr = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->twtrsmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+ o_atts->eff_dram_twtr = i_mss_eff_config_data->dram_twtr;
+
+ i_mss_eff_config_data->dram_twtrl = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->twtrlmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+
+ if (i_mss_eff_config_data->dram_twtrl < 4)
+ {
+ o_atts->eff_dram_twtrl = 4;
+ }
+ else
+ {
+ o_atts->eff_dram_twtrl = i_mss_eff_config_data->dram_twtrl;
+ }
+
+ FAPI_INF("DDR4 twtrs = %i, twtrl = %i", o_atts->eff_dram_twtr, o_atts->eff_dram_twtrl);
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_GEN().
+ set_DRAM_DEVICE_TYPE_0_0(i_data->dram_device_type[0][0]).
+ set_DRAM_DEVICE_TYPE_0_1(i_data->dram_device_type[0][1]).
+ set_DRAM_DEVICE_TYPE_1_0(i_data->dram_device_type[1][0]).
+ set_DRAM_DEVICE_TYPE_1_1(i_data->dram_device_type[1][1]),
+ "Incompatable DRAM generation on %s!", mss::c_str(i_target_mba));
+ }
+
+ i_mss_eff_config_data->dram_trtp = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->trtpmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+
+ if (i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ if (i_mss_eff_config_data->dram_trtp > o_atts->eff_dram_trtp)
+ {
+ o_atts->eff_dram_trtp = i_mss_eff_config_data->dram_trtp;
+ }
+ }
+ else if (i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ if (i_mss_eff_config_data->dram_trtp < 4)
+ {
+ o_atts->eff_dram_trtp = 4;
+ }
+ else
+ {
+ o_atts->eff_dram_trtp = i_mss_eff_config_data->dram_trtp;
+ }
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_GEN().
+ set_DRAM_DEVICE_TYPE_0_0(i_data->dram_device_type[0][0]).
+ set_DRAM_DEVICE_TYPE_0_1(i_data->dram_device_type[0][1]).
+ set_DRAM_DEVICE_TYPE_1_0(i_data->dram_device_type[1][0]).
+ set_DRAM_DEVICE_TYPE_1_1(i_data->dram_device_type[1][1]),
+ "Incompatable DRAM generation on %s!", mss::c_str(i_target_mba));
+ }
+
+ i_mss_eff_config_data->dram_tras = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->trasmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+
+ if (i_mss_eff_config_data->dram_tras >
+ o_atts->eff_dram_tras_u32)
+ {
+ o_atts->eff_dram_tras_u32 =
+ i_mss_eff_config_data->dram_tras;
+ }
+
+ i_mss_eff_config_data->dram_trc = (calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->trcmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->fine_offset_trcmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->mss_freq
+ ));
+
+ if (i_mss_eff_config_data->dram_trc >
+ o_atts->eff_dram_trc_u32)
+ {
+ o_atts->eff_dram_trc_u32 =
+ i_mss_eff_config_data->dram_trc;
+ }
+
+ if (i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ i_mss_eff_config_data->dram_trfc = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->trfcmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+
+ if (i_mss_eff_config_data->dram_trfc >
+ o_atts->eff_dram_trfc)
+ {
+ o_atts->eff_dram_trfc =
+ i_mss_eff_config_data->dram_trfc;
+ }
+ }
+ else if (i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ i_mss_eff_config_data->dram_trfc = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->trfc1min[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+ FAPI_INF("DDR4 Check: spd trfc = 0x%x (%i clks), o_attr=0x%x",
+ i_data->trfc1min[l_cur_mba_port][l_cur_mba_dimm],
+ i_mss_eff_config_data->dram_trfc,
+ o_atts->eff_dram_trfc
+ );
+
+ if (i_mss_eff_config_data->dram_trfc >
+ o_atts->eff_dram_trfc)
+ {
+ o_atts->eff_dram_trfc =
+ i_mss_eff_config_data->dram_trfc;
+ }
+
+ // AST HERE: Need DDR4 attributes for other refresh rates, 2x, 4x if we want to support those modes
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_GEN().
+ set_DRAM_DEVICE_TYPE_0_0(i_data->dram_device_type[0][0]).
+ set_DRAM_DEVICE_TYPE_0_1(i_data->dram_device_type[0][1]).
+ set_DRAM_DEVICE_TYPE_1_0(i_data->dram_device_type[1][0]).
+ set_DRAM_DEVICE_TYPE_1_1(i_data->dram_device_type[1][1]),
+ "Incompatable DRAM generation on %s!", mss::c_str(i_target_mba));
+ }
+
+ if (i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ i_mss_eff_config_data->dram_tfaw = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ i_data->tfawmin[l_cur_mba_port]
+ [l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+
+ if (i_mss_eff_config_data->dram_tfaw >
+ o_atts->eff_dram_tfaw_u32)
+ {
+ o_atts->eff_dram_tfaw_u32 =
+ i_mss_eff_config_data->dram_tfaw;
+ }
+ }
+ else if (i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ i_mss_eff_config_data->dram_tfaw = calc_timing_in_clk
+ (
+ i_mss_eff_config_data->mtb_in_ps_u32array[l_cur_mba_port][l_cur_mba_dimm],
+ i_mss_eff_config_data->ftb_in_fs_u32array[l_cur_mba_port][l_cur_mba_dimm],
+ i_data->tfawmin[l_cur_mba_port][l_cur_mba_dimm],
+ 0,
+ i_mss_eff_config_data->mss_freq
+ );
+ FAPI_DBG("DDR4 Check: SPD=0x%x, i_tFAWmin (nCK) = %i",
+ i_data->tfawmin[l_cur_mba_port][l_cur_mba_dimm], i_mss_eff_config_data->dram_tfaw);
+
+ // example x8, 1600, min= 25ns => 25/1.25 = 20 clocks
+ const uint8_t min_clks [][6] = // width, data rate
+ {
+ // NOTE: 2666 and 3200 are TBD, using guess values
+ // 1600 1866 2133 2400 2666 3200
+ { 16, 16, 16, 16, 16, 16}, // x4 (page size = 1/2K)
+ { 20, 22, 23, 26, 29, 32} // x8 (page size = 1K)
+ //{ xx, xx, xx, xx, TBD, TBD}, // x16(page size = 2K)
+ };
+
+
+ if (i_data->dram_width[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_WIDTH_W4)
+ {
+ l_width_idx = 0;
+ }
+ else //(i_data->dram_width[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_WIDTH_W8)
+ {
+ l_width_idx = 1;
+ }
+
+ //else (i_data->dram_width == fapi2::ENUM_ATTR_CEN_SPD_DRAM_WIDTH_W16)
+
+
+ if (i_mss_eff_config_data->mss_freq < 1733) // 1600
+ {
+ l_speed_idx = 0; // 1.25ns
+ }
+ else if (i_mss_eff_config_data->mss_freq < 2000) // 1866
+ {
+ l_speed_idx = 1; // 1.0718ns
+ }
+ else if (i_mss_eff_config_data->mss_freq < 2267) // 2133
+ {
+ l_speed_idx = 2; // 0.9376ns
+ }
+ else // if (i_mss_eff_config_data->mss_freq < 2533) // 2400
+ {
+ l_speed_idx = 3; // 0.8333ns
+ }
+
+ if (o_atts->eff_dram_tfaw_u32 < min_clks[l_width_idx][l_speed_idx])
+ {
+ o_atts->eff_dram_tfaw_u32 = min_clks[l_width_idx][l_speed_idx];
+ }
+
+ if (o_atts->eff_dram_tfaw_u32 == 16) // due to logic bug above
+ {
+ o_atts->eff_dram_tfaw_u32 = 15;
+ FAPI_INF("setting tFAW to 15 due to bug");
+ }
+
+ FAPI_DBG("Attribute o_eff_dram_tfaw = %i", o_atts->eff_dram_tfaw_u32);
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_GEN().
+ set_DRAM_DEVICE_TYPE_0_0(i_data->dram_device_type[0][0]).
+ set_DRAM_DEVICE_TYPE_0_1(i_data->dram_device_type[0][1]).
+ set_DRAM_DEVICE_TYPE_1_0(i_data->dram_device_type[1][0]).
+ set_DRAM_DEVICE_TYPE_1_1(i_data->dram_device_type[1][1]),
+ "Incompatable DRAM generation on %s!", mss::c_str(i_target_mba));
+ }
+ } // inner for loop
+ } // outter for loop
+
+ // Calculate CWL
+ if (i_data->dram_device_type[0][0] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ if ((TWO_MHZ / i_mss_eff_config_data->mss_freq) >= 2500)
+ {
+ o_atts->eff_dram_cwl = 5;
+ }
+ else if ((TWO_MHZ / i_mss_eff_config_data->mss_freq) >= 1875)
+ {
+ o_atts->eff_dram_cwl = 6;
+ }
+ else if ((TWO_MHZ / i_mss_eff_config_data->mss_freq) >= 1500)
+ {
+ o_atts->eff_dram_cwl = 7;
+ }
+ else if ((TWO_MHZ / i_mss_eff_config_data->mss_freq) >= 1250)
+ {
+ o_atts->eff_dram_cwl = 8;
+ }
+ else if ((TWO_MHZ / i_mss_eff_config_data->mss_freq) >= 1070)
+ {
+ o_atts->eff_dram_cwl = 9;
+ }
+ else if ((TWO_MHZ / i_mss_eff_config_data->mss_freq) >= 935)
+ {
+ o_atts->eff_dram_cwl = 10;
+ }
+ else if ((TWO_MHZ / i_mss_eff_config_data->mss_freq) >= 833)
+ {
+ o_atts->eff_dram_cwl = 11;
+ }
+ else if ((TWO_MHZ / i_mss_eff_config_data->mss_freq) >= 750)
+ {
+ o_atts->eff_dram_cwl = 12;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_CWL_CALC_ERR().
+ set_CWL_VAL((TWO_MHZ / i_mss_eff_config_data->mss_freq)),
+ "Error calculating CWL");
+ }
+ }
+ else if (i_data->dram_device_type[0][0] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ // 1st set only
+ // need to look at this again...
+ if (i_mss_eff_config_data->mss_freq <= (1600 * 1.05)) // 1600
+ {
+ o_atts->eff_dram_cwl = 9;
+ }
+ else if (i_mss_eff_config_data->mss_freq <= (1866 * 1.05)) // 1866
+ {
+ o_atts->eff_dram_cwl = 10;
+ }
+ else if (i_mss_eff_config_data->mss_freq <= (2133 * 1.05)) // 2133
+ {
+ o_atts->eff_dram_cwl = 11;
+ }
+ else if (i_mss_eff_config_data->mss_freq <= (2400 * 1.05)) // 2400
+ {
+ o_atts->eff_dram_cwl = 12;
+ }
+ else if (i_mss_eff_config_data->mss_freq <= (2666 * 1.05)) // 2666
+ {
+ o_atts->eff_dram_cwl = 14;
+ }
+ else if (i_mss_eff_config_data->mss_freq <= (3200 * 1.05)) // 2666
+ {
+ o_atts->eff_dram_cwl = 16;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_CWL_CALC_ERR().
+ set_CWL_VAL(TWO_MHZ / i_mss_eff_config_data->mss_freq),
+ "Error calculating CWL");
+ }
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_GEN().
+ set_DRAM_DEVICE_TYPE_0_0(i_data->dram_device_type[0][0]).
+ set_DRAM_DEVICE_TYPE_0_1(i_data->dram_device_type[0][1]).
+ set_DRAM_DEVICE_TYPE_1_0(i_data->dram_device_type[1][0]).
+ set_DRAM_DEVICE_TYPE_1_1(i_data->dram_device_type[1][1]),
+ "Incompatable DRAM generation on %s!", mss::c_str(i_target_mba));
+ }
+
+ // Calculate ZQCAL Interval based on the following equation from Ken:
+ // 0.5
+ // ------------------------------ = 13.333ms
+ // (1.5 * 10) + (0.15 * 150)
+
+ o_atts->eff_zqcal_interval = ( 13333 *
+ i_mss_eff_config_data->mss_freq) / 2;
+ // Calculate MEMCAL Interval based on 1sec interval across all bits per DP18
+
+ o_atts->eff_memcal_interval = (62500 *
+ i_mss_eff_config_data->mss_freq) / 2;
+ // Calculate tRFI
+ o_atts->eff_dram_trfi = (3900 *
+ i_mss_eff_config_data->mss_freq) / 2000;
+ // Added 10% margin to TRFI per defect HW248225
+ o_atts->eff_dram_trfi = (o_atts->eff_dram_trfi * 9) / 10;
+
+ o_atts->eff_vpd_version = 0xFFFFFF; // set VPD version to a large number, searching for smallest
+
+ // the VPD version is 2 ASCI characters, so this is always later than that
+ // Assigning dependent values to attributes
+ for (uint8_t l_cur_mba_port = 0; l_cur_mba_port <
+ MAX_PORTS_PER_MBA; l_cur_mba_port += 1)
+ {
+ for (uint8_t l_cur_mba_dimm = 0; l_cur_mba_dimm <
+ MAX_DIMM_PER_PORT; l_cur_mba_dimm += 1)
+ {
+ if (i_mss_eff_config_data->
+ cur_dimm_spd_valid_u8array[l_cur_mba_port][l_cur_mba_dimm] == MSS_EFF_VALID)
+ {
+ if ( i_data->sdram_device_type[l_cur_mba_port][l_cur_mba_dimm] ==
+ fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DEVICE_TYPE_NON_STANDARD)
+ {
+ //Preet - Added 3TSV Type here
+ if (i_data->sdram_device_type_signal_loading[l_cur_mba_port][l_cur_mba_dimm] ==
+ fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DEVICE_TYPE_SIGNAL_LOADING_SINGLE_LOAD_STACK )
+ {
+ o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS;
+ }
+ else
+ {
+ o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_DDP_QDP;
+ }
+ }
+ else
+ {
+ o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_NONE;
+ }
+
+ if (o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ if (i_data->sdram_die_count[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DIE_COUNT_DIE2)
+ {
+ l_die_count = 2;
+ }
+ else if(i_data->sdram_die_count[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DIE_COUNT_DIE3)
+ {
+ l_die_count = 3;
+ }
+ else if(i_data->sdram_die_count[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DIE_COUNT_DIE4)
+ {
+ l_die_count = 4;
+ }
+ else if(i_data->sdram_die_count[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DIE_COUNT_DIE5)
+ {
+ l_die_count = 5;
+ }
+ else if(i_data->sdram_die_count[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DIE_COUNT_DIE6)
+ {
+ l_die_count = 6;
+ }
+ else if(i_data->sdram_die_count[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DIE_COUNT_DIE7)
+ {
+ l_die_count = 7;
+ }
+ else if(i_data->sdram_die_count[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DIE_COUNT_DIE8)
+ {
+ l_die_count = 8;
+ }
+
+ if (i_data->num_ranks[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_NUM_RANKS_R1)
+ {
+ l_ranks_3d_tsv = 1 * l_die_count;
+ }
+ else if (i_data->num_ranks[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_NUM_RANKS_R2)
+ {
+ l_ranks_3d_tsv = 2 * l_die_count;
+ }
+ else if (i_data->num_ranks[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_NUM_RANKS_R4)
+ {
+ l_ranks_3d_tsv = 4 * l_die_count;
+ }
+
+ o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] = l_ranks_3d_tsv;
+
+ } //end of 3d TSV
+ else //if Non-3D TSV
+ {
+ if (i_data->num_ranks[l_cur_mba_port]
+ [l_cur_mba_dimm] == 0x04) // for 8R LRDIMM since no ENUM defined yet for SPD of 8R
+ {
+ o_atts->eff_num_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm] = 8;
+ o_atts->eff_dimm_ranks_configed[l_cur_mba_port]
+ [l_cur_mba_dimm] = 0x80; // DD0/1: 1 master rank
+ }
+ else if (i_data->num_ranks[l_cur_mba_port]
+ [l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_NUM_RANKS_R4)
+ {
+ o_atts->eff_num_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm] = 4;
+ o_atts->eff_dimm_ranks_configed[l_cur_mba_port]
+ [l_cur_mba_dimm] = 0xF0;
+ }
+ else if (i_data->num_ranks[l_cur_mba_port]
+ [l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_NUM_RANKS_R2)
+ {
+ o_atts->eff_num_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm] = 2;
+ o_atts->eff_dimm_ranks_configed[l_cur_mba_port]
+ [l_cur_mba_dimm] = 0xC0;
+ }
+ else if (i_data->num_ranks[l_cur_mba_port]
+ [l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_NUM_RANKS_R1)
+ {
+ o_atts->eff_num_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm] = 1;
+ o_atts->eff_dimm_ranks_configed[l_cur_mba_port]
+ [l_cur_mba_dimm] = 0x80;
+ }
+ else
+ {
+ o_atts->eff_num_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm] = 0;
+ o_atts->eff_dimm_ranks_configed[l_cur_mba_port]
+ [l_cur_mba_dimm] = 0x00;
+ }
+ }
+
+ // AST HERE: Needed SPD byte33[7,1:0], for expanded IBM_TYPE
+ if ( o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM )
+ {
+ if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 1)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_1A;
+ }
+ else if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 2)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_1B;
+ }
+ else if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 4)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_1D;
+ }
+ else if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 8)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_3A;
+ }
+ else
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_UNDEFINED;
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_RDIMM_UNSUPPORTED_TYPE().
+ set_UNSUPPORTED_VAL(o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm]),
+ "Currently unsupported IBM_TYPE on %s!", mss::c_str(i_target_mba));
+ }
+ }
+ else if (( o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_UDIMM )
+ && ( o_atts->eff_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES ))
+ {
+ if (o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 2)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_2A;
+ }
+ else if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 4)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_2B;
+ }
+ else
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_UNDEFINED;
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_UDIMM_UNSUPPORTED_TYPE().
+ set_UNSUPPORTED_VAL(o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm]),
+ "Currently unsupported IBM_TYPE on %s!", mss::c_str(i_target_mba));
+ }
+ }
+ else
+ {
+ if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 1)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_1A;
+ }
+ else if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 2)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_1B;
+ }
+ else if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 4)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_1D;
+ }
+ else
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_UNDEFINED;
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_UDIMM_UNSUPPORTED_TYPE().
+ set_UNSUPPORTED_VAL(o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm]),
+ "Currently unsupported IBM_TYPE on %s!", mss::c_str(i_target_mba));
+ }
+ }
+ }
+ else if ( o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM )
+ {
+ if (o_atts->eff_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR3)
+ {
+ FAPI_INF("Will set LR atts after orig eff_config functions");
+ }
+ else if (o_atts->eff_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4) // need to update this later...
+ {
+ if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 4)
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_TYPE_5C;
+ }
+ else
+ {
+ FAPI_INF("Will set LR atts after orig eff_config functions");
+ }
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_GEN().
+ set_DRAM_DEVICE_TYPE_0_0(i_data->dram_device_type[0][0]).
+ set_DRAM_DEVICE_TYPE_0_1(i_data->dram_device_type[0][1]).
+ set_DRAM_DEVICE_TYPE_1_0(i_data->dram_device_type[1][0]).
+ set_DRAM_DEVICE_TYPE_1_1(i_data->dram_device_type[1][1]),
+ "Incompatable DRAM generation on %s!", mss::c_str(i_target_mba));
+ }
+ }
+ else
+ {
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_UNDEFINED;
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_DIMM_UNSUPPORTED_TYPE().
+ set_UNSUPPORTED_VAL(o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm]),
+ "Currently unsupported DIMM_TYPE on %s!", mss::c_str(i_target_mba));
+ }
+
+ // Support for new attribute ATTR_EFF_DRAM_ADDRESS_MIRRORING
+ if ( o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM )
+ {
+ if (o_atts->eff_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ {
+ // Assuming Byte136[7:0] right align based on dimm_spd_attributes.xml
+ // Mask for bit0 of Byte136 = 0x00000001
+ if ((i_data->addr_map_reg_to_dram[l_cur_mba_port][l_cur_mba_dimm] & 0x00000001) != 0)
+ {
+ if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 4)
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x05;
+ }
+ else if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 2)
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x04;
+ }
+ else
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x00;
+ }
+ }
+ else
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x00;
+ }
+ }
+ else
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x00;
+ }
+ }
+ else if (( o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_UDIMM )
+ && ( o_atts->eff_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES ))
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] =
+ l_vpd_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm];
+ }
+ else if ( o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM )
+ {
+ if (o_atts->eff_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ {
+ // Assuming Byte136[7:0]:Byte137[7:0] right align based on dimm_spd_attributes.xml
+ // Mask for bit0 of Byte136 = 0x00000100
+ if ((i_data->addr_map_reg_to_dram[l_cur_mba_port][l_cur_mba_dimm] & 0x00000001) != 0)
+ {
+ if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 4)
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x05;
+ }
+ else if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 2)
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x04;
+ }
+ else
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x00;
+ }
+ }
+ else
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x00;
+ }
+ }
+ else
+ {
+ // DDR3 LRDIMM not supported
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x00;
+ }
+ }
+ else
+ {
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x00;
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_DIMM_UNSUPPORTED_TYPE(),
+ "Currently unsupported DIMM_TYPE on %s!", mss::c_str(i_target_mba));
+ }
+ }
+ else
+ {
+ o_atts->eff_num_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm] = 0;
+ o_atts->eff_dimm_ranks_configed[l_cur_mba_port]
+ [l_cur_mba_dimm] = 0x00;
+ o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_NONE;
+ o_atts->eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi2::ENUM_ATTR_CEN_EFF_IBM_TYPE_UNDEFINED;
+ o_atts->eff_dram_address_mirroring[l_cur_mba_port][l_cur_mba_dimm] = 0x00;
+ }
+
+ if (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm] != 0)
+ {
+ o_atts->eff_dimm_size[l_cur_mba_port][l_cur_mba_dimm] =
+ (
+ (o_atts->eff_dram_density)
+ *
+ (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm])
+ *
+ 64
+ )
+ /
+ (
+ 8
+ *
+ (o_atts->eff_dram_width)
+ );
+ }
+ else
+ {
+ o_atts->eff_dimm_size[l_cur_mba_port]
+ [l_cur_mba_dimm] = 0;
+ }
+
+
+ if ( (o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM) &&
+ (i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] ==
+ fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3) &&
+ (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 8) )
+ {
+ o_atts->eff_num_master_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm] = 1;
+ }
+ else if ((i_data->dram_device_type[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ && (i_data->sdram_device_type_signal_loading[l_cur_mba_port][l_cur_mba_dimm] ==
+ fapi2::ENUM_ATTR_CEN_SPD_SDRAM_DEVICE_TYPE_SIGNAL_LOADING_SINGLE_LOAD_STACK))
+ {
+ if(i_data->num_ranks[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_NUM_RANKS_R1)
+ {
+ o_atts->eff_num_master_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] = 1;
+ o_atts->eff_dimm_ranks_configed[l_cur_mba_port][l_cur_mba_dimm] = 0x80;
+ }
+ else if(i_data->num_ranks[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_NUM_RANKS_R2)
+ {
+ o_atts->eff_num_master_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] = 2;
+ o_atts->eff_dimm_ranks_configed[l_cur_mba_port][l_cur_mba_dimm] = 0xC0;
+ }
+ else if(i_data->num_ranks[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_SPD_NUM_RANKS_R4)
+ {
+ o_atts->eff_num_master_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] = 4;
+ o_atts->eff_dimm_ranks_configed[l_cur_mba_port][l_cur_mba_dimm] = 0xF0;
+ }
+ }
+ else
+ {
+ // AST HERE: Needs SPD byte33[7,1:0],
+ // currently hard coded to no stacking
+ o_atts->eff_num_master_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm] =
+ o_atts->eff_num_ranks_per_dimm[l_cur_mba_port]
+ [l_cur_mba_dimm];
+ }
+
+ // Populate RCD_CNTL_WORD for RDIMM, add hardcode to RC0-DA4=0b0 RC9-DBA1-DBA0-DA4-DA3=0b00X0, merge in ATTR_VPD_DIMM_RCD_IBT ATTR_VPD_DIMM_RCD_OUTPUT_TIMING, and adjust in RC10 and RC11 for freq/voltage
+ if (( o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM )
+ && (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] != 0))
+ {
+
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ i_data->rdimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm];
+
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] & l_rcd_hardcode_mask;
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] & l_mss_freq_mask;
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] & l_mss_volt_mask;
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] & l_rcd_ibt_mask;
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] & l_rcd_output_timing_mask;
+
+ if ( i_mss_eff_config_data->mss_freq <= 933 ) // 800Mbps
+ {
+ l_mss_freq_mask = 0x0000000000000000LL;
+ }
+ else if ( i_mss_eff_config_data->mss_freq <= 1200 ) // 1066Mbps
+ {
+ l_mss_freq_mask = 0x0000000000100000LL;
+ }
+ else if ( i_mss_eff_config_data->mss_freq <= 1466 ) // 1333Mbps
+ {
+ l_mss_freq_mask = 0x0000000000200000LL;
+ }
+ else if ( i_mss_eff_config_data->mss_freq <= 1733 ) // 1600Mbps
+ {
+ l_mss_freq_mask = 0x0000000000300000LL;
+ }
+ else // 1866Mbps
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INVALID_RDIMM_FREQ().
+ set_INVALID_RDIMM_FREQ(i_mss_eff_config_data->mss_freq),
+ "Invalid RDIMM ATTR_MSS_FREQ = %d on %s!", i_mss_eff_config_data->mss_freq, mss::c_str(i_target_mba));
+ }
+
+ //1.5V DDR3 or 1.2V DDR4
+ if ( i_mss_eff_config_data->mss_volt >= 1420 || (o_atts->eff_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4
+ && i_mss_eff_config_data->mss_volt >= 1130 && i_mss_eff_config_data->mss_volt <= 1270)) // 1.5V
+ {
+ l_mss_volt_mask = 0x0000000000000000LL;
+ }
+ else if ( i_mss_eff_config_data->mss_volt >= 1270
+ && o_atts->eff_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR3) // 1.35V and DDR3
+ {
+ l_mss_volt_mask = 0x0000000000010000LL;
+ }
+ else // not valid DDR3 or DDR4 setting
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INVALID_RDIMM_VOLT().
+ set_INVALID_RDIMM_VOLT( i_mss_eff_config_data->mss_volt),
+ "Invalid RDIMM ATTR_MSS_VOLT = %d on %s!", i_mss_eff_config_data->mss_volt, mss::c_str(i_target_mba));
+ }
+
+ if ( l_rdimm_rcd_ibt[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_RCD_IBT_IBT_OFF )
+ {
+ l_rcd_ibt_mask = 0x0000000070000000LL;
+ }
+ else if ( l_rdimm_rcd_ibt[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_RCD_IBT_IBT_100 )
+ {
+ l_rcd_ibt_mask = 0x0000000000000000LL;
+ }
+ else if ( l_rdimm_rcd_ibt[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_RCD_IBT_IBT_150 )
+ {
+ l_rcd_ibt_mask = 0x0040000000000000LL;
+ }
+ else if ( l_rdimm_rcd_ibt[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_RCD_IBT_IBT_200 )
+ {
+ l_rcd_ibt_mask = 0x0000000020000000LL;
+ }
+ else if ( l_rdimm_rcd_ibt[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_RCD_IBT_IBT_300 )
+ {
+ l_rcd_ibt_mask = 0x0000000040000000LL;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INVALID_RDIMM_RCD_IBT().
+ set_INVALID_RDIMM_RCD_IBT_U32ARRAY_0_0(l_rdimm_rcd_ibt[0][0]).
+ set_INVALID_RDIMM_RCD_IBT_U32ARRAY_0_1(l_rdimm_rcd_ibt[0][1]).
+ set_INVALID_RDIMM_RCD_IBT_U32ARRAY_1_0(l_rdimm_rcd_ibt[1][0]).
+ set_INVALID_RDIMM_RCD_IBT_U32ARRAY_1_1(l_rdimm_rcd_ibt[1][1]),
+ "Invalid RDIMM_RCD_IBT = %d port %d dimm %d on %s!", l_rdimm_rcd_ibt[l_cur_mba_port][l_cur_mba_dimm], l_cur_mba_port,
+ l_cur_mba_dimm, mss::c_str(i_target_mba));
+ }
+
+ if ( l_rdimm_rcd_output_timing[l_cur_mba_port][l_cur_mba_dimm] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_RCD_OUTPUT_TIMING_1T )
+ {
+ l_rcd_output_timing_mask = 0x0000000000000000LL;
+ }
+ else if ( l_rdimm_rcd_output_timing[l_cur_mba_port][l_cur_mba_dimm] ==
+ fapi2::ENUM_ATTR_CEN_VPD_DIMM_RCD_OUTPUT_TIMING_3T )
+ {
+ l_rcd_output_timing_mask = 0x0020000000000000LL;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INVALID_RDIMM_RCD_OUTPUT_TIMING().
+ set_INVALID_RDIMM_RCD_OUTPUT_TIMING_U8ARRAY_0_0(l_rdimm_rcd_output_timing[0][0]).
+ set_INVALID_RDIMM_RCD_OUTPUT_TIMING_U8ARRAY_0_0(l_rdimm_rcd_output_timing[0][1]).
+ set_INVALID_RDIMM_RCD_OUTPUT_TIMING_U8ARRAY_0_0(l_rdimm_rcd_output_timing[1][0]).
+ set_INVALID_RDIMM_RCD_OUTPUT_TIMING_U8ARRAY_0_0(l_rdimm_rcd_output_timing[1][1]),
+ "Invalid RDIMM_RCD_OUTPUT_TIMING = %d port %d dimm %d on %s!",
+ l_rdimm_rcd_output_timing[l_cur_mba_port][l_cur_mba_dimm], l_cur_mba_port, l_cur_mba_dimm, mss::c_str(i_target_mba));
+ }
+
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] | l_mss_freq_mask;
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] | l_mss_volt_mask;
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] | l_rcd_ibt_mask;
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] =
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] | l_rcd_output_timing_mask;
+ }
+ else if ((o_atts->eff_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ && ( o_atts->eff_dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM )
+ && (o_atts->eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] != 0))
+ {
+ // AST HERE: Need to add DDR4 RDIMM support.
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] = 0x0000000000000000LL;
+ }
+ else
+ {
+ o_atts->eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm] = 0x0000000000000000LL;
+ }
+
+ if(o_atts->eff_vpd_version == 0xFFFFFF ||
+ i_data->vpd_version[l_cur_mba_port][l_cur_mba_dimm] < o_atts->eff_vpd_version ) // find the smallest VPD
+ {
+ o_atts->eff_vpd_version = i_data->vpd_version[l_cur_mba_port][l_cur_mba_dimm];
+ }
+ } // inner for loop
+ } // outer for loop
+
+
+ // Select EFF_DRAM_AL
+ if (i_data->dram_device_type[0][0] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ if ( l_mss_dram_2n_mode_enable == fapi2::ENUM_ATTR_CEN_VPD_DRAM_2N_MODE_ENABLED_TRUE )
+ {
+ o_atts->eff_dram_al = fapi2::ENUM_ATTR_CEN_EFF_DRAM_AL_CL_MINUS_2; // Always use AL = CL - 2 for 2N/2T mode
+ }
+ else
+ {
+ o_atts->eff_dram_al = fapi2::ENUM_ATTR_CEN_EFF_DRAM_AL_CL_MINUS_1; // Always use AL = CL - 1 for 1N/1T mode
+ }
+ }
+ else if (i_data->dram_device_type[0][0] == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ if ( o_atts->eff_stack_type[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS )
+ {
+ if ( l_mss_dram_2n_mode_enable == fapi2::ENUM_ATTR_CEN_VPD_DRAM_2N_MODE_ENABLED_TRUE )
+ {
+ o_atts->eff_dram_al = fapi2::ENUM_ATTR_CEN_EFF_DRAM_AL_CL_MINUS_3; // Always use AL = CL - 3 for 2N/2T mode
+ }
+ else
+ {
+ o_atts->eff_dram_al = fapi2::ENUM_ATTR_CEN_EFF_DRAM_AL_CL_MINUS_2; // Always use AL = CL - 2 for 1N/1T mode
+ }
+ }
+ else
+ {
+ if ( l_mss_dram_2n_mode_enable == fapi2::ENUM_ATTR_CEN_VPD_DRAM_2N_MODE_ENABLED_TRUE )
+ {
+ o_atts->eff_dram_al = fapi2::ENUM_ATTR_CEN_EFF_DRAM_AL_CL_MINUS_2; // Always use AL = CL - 2 for 2N/2T mode
+ }
+ else
+ {
+ o_atts->eff_dram_al = fapi2::ENUM_ATTR_CEN_EFF_DRAM_AL_CL_MINUS_1; // Always use AL = CL - 1 for 1N/1T mode
+ }
+ }
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_INCOMPATABLE_DRAM_GEN().
+ set_DRAM_DEVICE_TYPE_0_0(i_data->dram_device_type[0][0]).
+ set_DRAM_DEVICE_TYPE_0_1(i_data->dram_device_type[0][1]).
+ set_DRAM_DEVICE_TYPE_1_0(i_data->dram_device_type[1][0]).
+ set_DRAM_DEVICE_TYPE_1_1(i_data->dram_device_type[1][1]),
+ "Incompatable DRAM generation on %s!", mss::c_str(i_target_mba));
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ } // end mss_eff_config_setup_eff_atts()
+
+ ///
+ /// @brief mss_eff_config_write_eff_atts(): This function writes the effective configuration attributes
+ /// @param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> &i_target_mba: the fapi2 target
+ /// @param[in] const mss_eff_config_atts *i_atts: Pointer to mss_eff configuration attributes structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_write_eff_atts(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_atts* i_atts)
+ {
+ i_atts->eff_dram_tras = uint8_t (i_atts->eff_dram_tras_u32);
+ i_atts->eff_dram_trc = (uint8_t (i_atts->eff_dram_trc_u32));
+ i_atts->eff_dram_tfaw = uint8_t (i_atts->eff_dram_tfaw_u32);
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_ADDRESS_MIRRORING, i_target_mba,
+ i_atts->eff_dram_address_mirroring));
+
+ // Set attributes
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_RANKS_CONFIGED, i_target_mba,
+ i_atts->eff_dimm_ranks_configed));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_RCD_CNTL_WORD_0_15, i_target_mba,
+ i_atts->eff_dimm_rcd_cntl_word_0_15));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_SIZE, i_target_mba,
+ i_atts->eff_dimm_size));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_TYPE, i_target_mba,
+ i_atts->eff_dimm_type));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target_mba,
+ i_atts->eff_custom_dimm));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_AL, i_target_mba,
+ i_atts->eff_dram_al));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_ASR, i_target_mba,
+ i_atts->eff_dram_asr));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_BANKS, i_target_mba,
+ i_atts->eff_dram_banks));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_BL, i_target_mba,
+ i_atts->eff_dram_bl));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_COLS, i_target_mba,
+ i_atts->eff_dram_cols));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_CWL, i_target_mba,
+ i_atts->eff_dram_cwl));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_DENSITY, i_target_mba,
+ i_atts->eff_dram_density));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_DLL_ENABLE, i_target_mba,
+ i_atts->eff_dram_dll_enable));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_DLL_PPD, i_target_mba,
+ i_atts->eff_dram_dll_ppd));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_DLL_RESET, i_target_mba,
+ i_atts->eff_dram_dll_reset));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba,
+ i_atts->eff_dram_gen));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_OUTPUT_BUFFER, i_target_mba,
+ i_atts->eff_dram_output_buffer));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_PASR, i_target_mba,
+ i_atts->eff_dram_pasr));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_RBT, i_target_mba,
+ i_atts->eff_dram_rbt));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_ROWS, i_target_mba,
+ i_atts->eff_dram_rows));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_SRT, i_target_mba,
+ i_atts->eff_dram_srt));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TDQS, i_target_mba,
+ i_atts->eff_dram_tdqs));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TFAW, i_target_mba,
+ i_atts->eff_dram_tfaw));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TM, i_target_mba,
+ i_atts->eff_dram_tm));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TRAS, i_target_mba,
+ i_atts->eff_dram_tras));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TRC, i_target_mba,
+ i_atts->eff_dram_trc));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TRCD, i_target_mba,
+ i_atts->eff_dram_trcd));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TRFC, i_target_mba,
+ i_atts->eff_dram_trfc));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TRFI, i_target_mba,
+ i_atts->eff_dram_trfi));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TRP, i_target_mba,
+ i_atts->eff_dram_trp));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TRRD, i_target_mba,
+ i_atts->eff_dram_trrd));
+ // DDR4 only
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TRRD_L, i_target_mba,
+ i_atts->eff_dram_trrdl));
+ // DDR4 only
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_TCCD_L, i_target_mba,
+ i_atts->eff_dram_tccdl));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TCCD_L, i_target_mba,
+ i_atts->eff_dram_tccdl));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TRTP, i_target_mba,
+ i_atts->eff_dram_trtp));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TWTR, i_target_mba,
+ i_atts->eff_dram_twtr));
+ // DDR4 only
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TWTR_L, i_target_mba,
+ i_atts->eff_dram_twtrl));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target_mba,
+ i_atts->eff_dram_width));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_WR, i_target_mba,
+ i_atts->eff_dram_wr));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_WR_LVL_ENABLE, i_target_mba,
+ i_atts->eff_dram_wr_lvl_enable));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_IBM_TYPE, i_target_mba,
+ i_atts->eff_ibm_type));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_MEMCAL_INTERVAL, i_target_mba,
+ i_atts->eff_memcal_interval));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_MPR_LOC, i_target_mba,
+ i_atts->eff_mpr_loc));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_MPR_MODE, i_target_mba,
+ i_atts->eff_mpr_mode));
+
+ // AST HERE: Needs SPD byte33[6:4], currently hard coded to 0, removed for GA1
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_NUM_DIES_PER_PACKAGE, i_target_mba,
+ i_atts->eff_num_dies_per_package));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_NUM_DROPS_PER_PORT, i_target_mba,
+ i_atts->eff_num_drops_per_port));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target_mba,
+ i_atts->eff_num_master_ranks_per_dimm));
+
+ // AST HERE: Needs source data, currently hard coded to 0, removed for GA1
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_NUM_PACKAGES_PER_RANK, i_target_mba,
+ i_atts->eff_num_packages_per_rank));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba,
+ i_atts->eff_num_ranks_per_dimm));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_MODE, i_target_mba,
+ i_atts->eff_schmoo_mode));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_ADDR_MODE, i_target_mba,
+ i_atts->eff_schmoo_addr_mode));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_PARAM_VALID, i_target_mba,
+ i_atts->eff_schmoo_param_valid));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba,
+ i_atts->eff_schmoo_test_valid));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_WR_EYE_MIN_MARGIN, i_target_mba,
+ i_atts->eff_schmoo_wr_eye_min_margin));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_RD_EYE_MIN_MARGIN, i_target_mba,
+ i_atts->eff_schmoo_rd_eye_min_margin));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_DQS_CLK_MIN_MARGIN, i_target_mba,
+ i_atts->eff_schmoo_dqs_clk_min_margin));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_RD_GATE_MIN_MARGIN, i_target_mba,
+ i_atts->eff_schmoo_rd_gate_min_margin));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_ADDR_CMD_MIN_MARGIN, i_target_mba,
+ i_atts->eff_schmoo_addr_cmd_min_margin));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_RD_VREF_SCHMOO, i_target_mba,
+ i_atts->eff_cen_rd_vref_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_WR_VREF_SCHMOO, i_target_mba,
+ i_atts->eff_dram_wr_vref_schmoo));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_RCV_IMP_DQ_DQS_SCHMOO, i_target_mba,
+ i_atts->eff_cen_rcv_imp_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_SCHMOO, i_target_mba,
+ i_atts->eff_cen_drv_imp_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_CNTL_SCHMOO, i_target_mba,
+ i_atts->eff_cen_drv_imp_cntl_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_CLK_SCHMOO, i_target_mba,
+ i_atts->eff_cen_drv_imp_clk_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_SPCKE_SCHMOO, i_target_mba,
+ i_atts->eff_cen_drv_imp_spcke_schmoo));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS_SCHMOO, i_target_mba,
+ i_atts->eff_cen_slew_rate_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_CNTL_SCHMOO, i_target_mba,
+ i_atts->eff_cen_slew_rate_cntl_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_ADDR_SCHMOO, i_target_mba,
+ i_atts->eff_cen_slew_rate_addr_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_CLK_SCHMOO, i_target_mba,
+ i_atts->eff_cen_slew_rate_clk_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_SPCKE_SCHMOO, i_target_mba,
+ i_atts->eff_cen_slew_rate_spcke_schmoo));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target_mba,
+ i_atts->eff_stack_type));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_ZQCAL_INTERVAL, i_target_mba,
+ i_atts->eff_zqcal_interval));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR, i_target_mba,
+ i_atts->dimm_functional_vector));
+
+ // DDR4 Only
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target_mba, i_atts->eff_vref_dq_train_value));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE, i_target_mba, i_atts->eff_vref_dq_train_range));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, i_atts->eff_vref_dq_train_enable));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_MPR_PAGE, i_target_mba, i_atts->eff_mpr_page));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_LPASR, i_target_mba, i_atts->eff_dram_lpasr));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_GEARDOWN_MODE, i_target_mba, i_atts->eff_geardown_mode));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_PER_DRAM_ACCESS, i_target_mba, i_atts->eff_per_dram_access));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_TEMP_READOUT, i_target_mba, i_atts->eff_temp_readout));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_FINE_REFRESH_MODE, i_target_mba, i_atts->eff_fine_refresh_mode));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CRC_WR_LATENCY, i_target_mba, i_atts->eff_crc_wr_latency));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_MPR_RD_FORMAT, i_target_mba, i_atts->eff_mpr_rd_format));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_MAX_POWERDOWN_MODE, i_target_mba, i_atts->eff_max_powerdown_mode));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_TEMP_REF_RANGE, i_target_mba, i_atts->eff_temp_ref_range));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_TEMP_REF_MODE, i_target_mba, i_atts->eff_temp_ref_mode));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_INT_VREF_MON, i_target_mba, i_atts->eff_int_vref_mon));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SELF_REF_ABORT, i_target_mba, i_atts->eff_self_ref_abort));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_RD_PREAMBLE_TRAIN, i_target_mba, i_atts->eff_rd_preamble_train));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_RD_PREAMBLE, i_target_mba, i_atts->eff_rd_preamble));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_WR_PREAMBLE, i_target_mba, i_atts->eff_wr_preamble));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_ODT_INPUT_BUFF, i_target_mba, i_atts->eff_odt_input_buff));
+ //FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_RTT_PARK, i_target_mba, i_atts->eff_rtt_park));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DATA_MASK, i_target_mba, i_atts->eff_data_mask));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_WRITE_DBI, i_target_mba, i_atts->eff_write_dbi));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_READ_DBI, i_target_mba, i_atts->eff_read_dbi));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CA_PARITY, i_target_mba, i_atts->eff_ca_parity));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CA_PARITY_LATENCY, i_target_mba, i_atts->eff_ca_parity_latency));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CA_PARITY_ERROR_STATUS, i_target_mba,
+ i_atts->eff_ca_parity_error_status));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_WRITE_CRC, i_target_mba, i_atts->eff_write_crc));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CS_CMD_LATENCY, i_target_mba, i_atts->eff_cs_cmd_latency));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CRC_ERROR_CLEAR, i_target_mba, i_atts->eff_crc_error_clear));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC00, i_target_mba, i_atts->eff_dimm_ddr4_rc00));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC01, i_target_mba, i_atts->eff_dimm_ddr4_rc01));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC02, i_target_mba, i_atts->eff_dimm_ddr4_rc02));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC03, i_target_mba, i_atts->eff_dimm_ddr4_rc03));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC04, i_target_mba, i_atts->eff_dimm_ddr4_rc04));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC05, i_target_mba, i_atts->eff_dimm_ddr4_rc05));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC06_07, i_target_mba, i_atts->eff_dimm_ddr4_rc06_07));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC08, i_target_mba, i_atts->eff_dimm_ddr4_rc08));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC09, i_target_mba, i_atts->eff_dimm_ddr4_rc09));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC10, i_target_mba, i_atts->eff_dimm_ddr4_rc10));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC11, i_target_mba, i_atts->eff_dimm_ddr4_rc11));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC12, i_target_mba, i_atts->eff_dimm_ddr4_rc12));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC13, i_target_mba, i_atts->eff_dimm_ddr4_rc13));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC14, i_target_mba, i_atts->eff_dimm_ddr4_rc14));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC15, i_target_mba, i_atts->eff_dimm_ddr4_rc15));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_1x, i_target_mba, i_atts->eff_dimm_ddr4_rc_1x));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_2x, i_target_mba, i_atts->eff_dimm_ddr4_rc_2x));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_3x, i_target_mba, i_atts->eff_dimm_ddr4_rc_3x));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_4x, i_target_mba, i_atts->eff_dimm_ddr4_rc_4x));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_5x, i_target_mba, i_atts->eff_dimm_ddr4_rc_5x));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_6x, i_target_mba, i_atts->eff_dimm_ddr4_rc_6x));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_7x, i_target_mba, i_atts->eff_dimm_ddr4_rc_7x));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_8x, i_target_mba, i_atts->eff_dimm_ddr4_rc_8x));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_9x, i_target_mba, i_atts->eff_dimm_ddr4_rc_9x));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_Ax, i_target_mba, i_atts->eff_dimm_ddr4_rc_ax));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_DDR4_RC_Bx, i_target_mba, i_atts->eff_dimm_ddr4_rc_bx));
+
+ // Calibration switches
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_CAL_STEP_ENABLE, i_target_mba,
+ i_atts->mss_cal_step_enable));
+
+ // Make the final VPD version be a number and not ascii
+ i_atts->eff_vpd_version = ((i_atts->eff_vpd_version & 0x0f00) >> 4) |
+ ((i_atts->eff_vpd_version & 0x000f) >> 0);
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_EFF_VPD_VERSION, i_target_mba,
+ i_atts->eff_vpd_version));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief mss_eff_config(): read and verify spd data as well as configure effective attributes.
+ /// @param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba: the fapi2 target
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode p9c_mss_eff_config(const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba)
+ {
+ const auto l_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ // mss_eff_config_data_variable struct
+ mss_eff_config_data* l_mss_eff_config_data = new mss_eff_config_data();
+ // mss_eff_config_spd_data struct
+ mss_eff_config_spd_data* l_spd_data = new mss_eff_config_spd_data();
+ // mss_eff_config_atts struct
+ mss_eff_config_atts* l_atts = new mss_eff_config_atts();
+ /* End Variable Initialization */
+
+ FAPI_INF("STARTING mss_eff_config on %s \n",
+ mss::c_str(i_target_mba));
+
+ // Added call to mss_eff_pre_config() for Mike Pardeik (power/thermal).
+ FAPI_TRY(mss_eff_pre_config(i_target_mba));
+ // Grab allow single port data
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_ALLOW_SINGLE_PORT, i_target_mba,
+ l_mss_eff_config_data->allow_single_port));
+
+ if ( l_mss_eff_config_data->allow_single_port == fapi2::ENUM_ATTR_CEN_MSS_ALLOW_SINGLE_PORT_TRUE )
+ {
+ FAPI_INF("WARNING: allow_single_port = %d on %s.", l_mss_eff_config_data->allow_single_port,
+ mss::c_str(i_target_mba));
+ }
+
+ // Grab freq/volt data
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, l_mss_eff_config_data->mss_freq));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VOLT, l_target_centaur, l_mss_eff_config_data->mss_volt));
+
+ FAPI_ASSERT(l_mss_eff_config_data->mss_freq != 0,
+ fapi2::CEN_MSS_EFF_CONFIG_MSS_FREQ().
+ set_FREQ_VAL(l_mss_eff_config_data->mss_freq),
+ "Invalid ATTR_MSS_FREQ = %d on %s!",
+ l_mss_eff_config_data->mss_freq,
+ mss::c_str(i_target_mba));
+
+ FAPI_INF("mss_freq = %d, tCK_in_ps= %d on %s.",
+ l_mss_eff_config_data->mss_freq,
+ TWO_MHZ / l_mss_eff_config_data->mss_freq,
+ mss::c_str(l_target_centaur));
+
+ FAPI_INF("mss_volt = %d on %s.", l_mss_eff_config_data->mss_volt, mss::c_str(l_target_centaur));
+ /* Function calls */
+ // get SPD data
+ FAPI_TRY(mss_eff_config_get_spd_data( i_target_mba, l_mss_eff_config_data, l_spd_data, l_atts ));
+
+ // verify dimm plug rules
+ FAPI_TRY(mss_eff_config_verify_plug_rules( i_target_mba, l_mss_eff_config_data, l_atts ));
+
+ // verify SPD data
+ if(( l_atts->eff_num_drops_per_port
+ != fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_EMPTY )
+ && ( l_mss_eff_config_data->allow_single_port == fapi2::ENUM_ATTR_CEN_MSS_ALLOW_SINGLE_PORT_FALSE ))
+ {
+ FAPI_TRY(mss_eff_config_verify_spd_data( i_target_mba, l_atts, l_spd_data ));
+ }
+
+ // setup effective configuration attributes
+ FAPI_TRY(mss_eff_config_setup_eff_atts( i_target_mba, l_mss_eff_config_data, l_spd_data, l_atts ));
+
+ // write effective configuration attributes
+ FAPI_TRY(mss_eff_config_write_eff_atts( i_target_mba, l_atts ));
+
+ // Calls to sub-procedures
+ FAPI_TRY(mss_eff_config_rank_group(i_target_mba));
+
+ FAPI_TRY(mss_eff_config_shmoo(i_target_mba));
+
+ FAPI_INF("mss_eff_config on %s COMPLETE\n", mss::c_str(i_target_mba));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ } // end mss_eff_config()
+} // extern "C"
+
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.H
new file mode 100644
index 000000000..e9f5fc737
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.H
@@ -0,0 +1,395 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// @file p9c_mss_eff_config.H
+/// @brief Takes in spd and configures effective attrs
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Anuwat Saetow <asaetow@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+#ifndef MSS_EFF_CONFIG_H_
+#define MSS_EFF_CONFIG_H_
+
+//------------------------------------------------------------------------------
+// My Includes
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include <fapi2.H>
+#include <dimmConsts.H>
+
+typedef fapi2::ReturnCode (*p9c_mss_eff_config_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba);
+
+///
+/// @brief struct mss_eff_config_data
+/// @brief holds the the variables used in many function calls
+/// in mss_eff_config.C
+struct mss_eff_config_data
+{
+ uint8_t cur_dimm_spd_valid_u8array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t dimm_functional;
+ uint8_t allow_single_port;
+ uint8_t cur_dram_density;
+ uint32_t mss_freq;
+ uint32_t mss_volt;
+ uint32_t mtb_in_ps_u32array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t ftb_in_fs_u32array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t dram_tfaw;
+ uint32_t dram_tras;
+ uint32_t dram_trc;
+ uint8_t dram_trcd;
+ uint32_t dram_trfc;
+ uint8_t dram_trp;
+ uint8_t dram_trrd;
+ uint8_t dram_trtp;
+ uint8_t dram_twtr;
+ uint8_t dram_wr;
+ uint8_t dram_trrdl;
+ uint8_t dram_tccdl;
+ uint8_t dram_twtrl;
+
+};
+
+///
+/// @brief struct mss_eff_config_spd_data
+/// @brief holds the DIMM SPD data for an MBA
+struct mss_eff_config_spd_data
+{
+ uint8_t dram_device_type[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t sdram_device_type[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t sdram_device_type_signal_loading[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t sdram_die_count[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t module_type[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t custom[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t sdram_banks[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t sdram_density[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t sdram_rows[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t sdram_columns[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t num_ranks[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t dram_width[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t module_memory_bus_width[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t ftb_dividend[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t ftb_divisor[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t mtb_dividend[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t mtb_divisor[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t twrmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t trcdmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t trrdmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT]; // DDR3 only
+ uint8_t trpmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t trasmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t trcmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t trfcmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT]; // DDR3 only
+ uint8_t twtrmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT]; // DDR3 only
+ uint8_t trtpmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t tfawmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+
+
+ // DDR4 only
+ uint8_t sdram_bankgroups_ddr4[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t trrdsmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t trrdlmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t tccdlmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t trfc1min[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t trfc2min[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t trfc4min[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t twtrsmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t twtrlmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t addr_map_reg_to_dram[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT]; // Assuming right align based on dimm_spd_attributes.xml
+
+ // Not needed for GA1 CDIMM, will need to enable check for ISDIMM.
+ uint8_t sdram_optional_features[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t sdram_thermal_and_refresh_options[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t module_thermal_sensor[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+
+ uint8_t fine_offset_tckmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t fine_offset_taamin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t fine_offset_trcdmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t fine_offset_trpmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t fine_offset_trcmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ // DDR4 only
+ uint8_t fine_offset_tccdlmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t fine_offset_trrdlmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t fine_offset_trrdsmin[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t fine_offset_tckmax[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ // ATTR_SPD_MODULE_SPECIFIC_SECTION, Located in DDR3 SPD bytes 60d - 116d
+ uint64_t rdimm_rcd_cntl_word_0_15[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+
+ uint32_t vpd_version[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+};
+
+///
+/// @brief struct mss_eff_config_atts
+/// @brief holds the effective configuration attributes
+struct mss_eff_config_atts
+{
+ uint8_t eff_dimm_ranks_configed[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dram_address_mirroring[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ // Using SPD byte68,69:76, enabled in GA2 for full RDIMM support
+ uint64_t eff_dimm_rcd_cntl_word_0_15[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_size[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_type;
+ uint8_t eff_custom_dimm;
+ uint8_t eff_dram_al; // Based on 2N/2T or 1N/1T enable
+ uint8_t eff_dram_asr;
+ uint8_t eff_dram_bl;
+ uint8_t eff_dram_banks;
+ uint8_t eff_cs_cmd_latency;
+ uint8_t eff_dimm_ddr4_rc00[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc01[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc02[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc03[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc04[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc05[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc06_07[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc08[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc09[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc10[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc11[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc12[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc13[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc14[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc15[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_1x[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_2x[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_3x[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_4x[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_5x[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_6x[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_7x[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_8x[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_9x[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_ax[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dimm_ddr4_rc_bx[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_dram_cols;
+ uint8_t eff_dram_cwl;
+ uint8_t eff_dram_density;
+ uint8_t eff_dram_dll_enable;
+ uint8_t eff_dram_dll_ppd; // Check MRW, ATTR_MRW_POWER_CONTROL_REQUESTED attr
+ uint8_t eff_dram_dll_reset; // Always reset DLL at start of IPL.
+ uint8_t eff_dram_gen;
+ uint8_t eff_dram_output_buffer;
+ uint8_t eff_dram_pasr;
+ uint8_t eff_dram_rbt;
+ uint8_t eff_dram_rows;
+ uint8_t eff_dram_srt; // Always use extended operating temp range.
+ uint8_t eff_dram_tdqs;
+ uint8_t eff_dram_tfaw;
+ uint32_t eff_dram_tfaw_u32;
+ uint8_t eff_dram_tm;
+ uint8_t eff_dram_tras;
+ uint32_t eff_dram_tras_u32;
+ uint8_t eff_dram_trc;
+ uint32_t eff_dram_trc_u32;
+ uint8_t eff_dram_trcd;
+ uint32_t eff_dram_trfc;
+ uint32_t eff_dram_trfi;
+ uint8_t eff_dram_trp;
+ uint8_t eff_dram_trrd;
+ uint8_t eff_dram_trtp;
+ uint8_t eff_dram_twtr;
+ uint8_t eff_dram_width;
+ uint8_t eff_dram_wr;
+ uint8_t eff_dram_wr_lvl_enable;
+ uint8_t eff_ibm_type[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t eff_memcal_interval;
+ uint8_t eff_mpr_loc;
+ uint8_t eff_mpr_mode;
+
+ // AST HERE: Needs SPD DDR3 byte33[6:4], DDR4 byte6[6:4] currently hard coded to 0
+ uint8_t eff_num_dies_per_package[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+
+ uint8_t eff_num_drops_per_port;
+ uint8_t eff_num_master_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+
+ // AST HERE: Needs source data, currently hard coded to 0
+ uint8_t eff_num_packages_per_rank[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+
+ uint8_t eff_num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint8_t eff_schmoo_mode;
+ uint8_t eff_schmoo_addr_mode;
+ uint8_t eff_schmoo_wr_eye_min_margin;
+ uint8_t eff_schmoo_rd_eye_min_margin;
+ uint8_t eff_schmoo_dqs_clk_min_margin;
+ uint8_t eff_schmoo_rd_gate_min_margin;
+ uint8_t eff_schmoo_addr_cmd_min_margin;
+ uint32_t eff_cen_rd_vref_schmoo[MAX_PORTS_PER_MBA];
+ uint32_t eff_dram_wr_vref_schmoo[MAX_PORTS_PER_MBA];
+ uint32_t eff_cen_rcv_imp_dq_dqs_schmoo[MAX_PORTS_PER_MBA];
+ uint32_t eff_cen_drv_imp_dq_dqs_schmoo[MAX_PORTS_PER_MBA];
+ uint8_t eff_cen_drv_imp_cntl_schmoo[MAX_PORTS_PER_MBA];
+ uint8_t eff_cen_drv_imp_clk_schmoo[MAX_PORTS_PER_MBA];
+ uint8_t eff_cen_drv_imp_spcke_schmoo[MAX_PORTS_PER_MBA];
+ uint8_t eff_cen_slew_rate_dq_dqs_schmoo[MAX_PORTS_PER_MBA];
+ uint8_t eff_cen_slew_rate_cntl_schmoo[MAX_PORTS_PER_MBA];
+ uint8_t eff_cen_slew_rate_addr_schmoo[MAX_PORTS_PER_MBA];
+ uint8_t eff_cen_slew_rate_clk_schmoo[MAX_PORTS_PER_MBA];
+ uint8_t eff_cen_slew_rate_spcke_schmoo[MAX_PORTS_PER_MBA];
+
+ uint8_t eff_schmoo_param_valid;
+ uint8_t eff_schmoo_test_valid;
+ uint8_t eff_stack_type[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT];
+ uint32_t eff_zqcal_interval;
+ uint8_t dimm_functional_vector;
+ uint8_t mss_cal_step_enable; // Always run all cal steps
+ uint32_t eff_vpd_version;
+
+ // DDR4 attributes
+ uint8_t eff_dram_trrdl;
+ uint8_t eff_dram_tccdl;
+ //uint8_t eff_dram_tccds;
+ uint8_t eff_dram_twtrl;
+ uint8_t eff_vref_dq_train_value[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM];
+ uint8_t eff_vref_dq_train_range[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM];
+ uint8_t eff_vref_dq_train_enable[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM];
+ uint8_t eff_mpr_page;
+ uint8_t eff_dram_lpasr;
+ uint8_t eff_geardown_mode;
+ uint8_t eff_per_dram_access;
+ uint8_t eff_temp_readout;
+ uint8_t eff_fine_refresh_mode;
+ uint8_t eff_mpr_rd_format;
+ uint8_t eff_max_powerdown_mode;
+ uint8_t eff_temp_ref_range;
+ uint8_t eff_temp_ref_mode;
+ uint8_t eff_int_vref_mon;
+ uint8_t eff_self_ref_abort;
+ uint8_t eff_rd_preamble_train;
+ uint8_t eff_rd_preamble;
+ uint8_t eff_wr_preamble;
+ uint8_t eff_odt_input_buff;
+ uint8_t eff_data_mask;
+ uint8_t eff_write_dbi;
+ uint8_t eff_read_dbi;
+ uint8_t eff_ca_parity;
+ uint8_t eff_ca_parity_latency;
+ uint8_t eff_ca_parity_error_status;
+ // DDR4 CRC attributes
+ uint8_t eff_write_crc;
+ uint8_t eff_crc_wr_latency;
+ uint8_t eff_crc_error_clear;
+};
+
+
+extern "C" {
+
+ ///
+ /// @brief mss_eff_config(): read and verify spd data as well as configure effective attributes.
+ /// @param[in] i_target_mba: the fapi2 mba target
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode p9c_mss_eff_config(const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba);
+
+ ///
+ /// @brief mss_eff_config_get_spd_data(): This function sets gathers the DIMM info then uses mss_eff_config_read_spd_data()
+ /// @param[in] i_target_mba: the fapi2 target
+ /// @param[in] i_mss_eff_config_data: Pointer to mss_eff_config_data variable structure
+ /// @param[out] o_spd_data: Pointer to mss_eff configuration spd data structure
+ /// @param[in] i_atts: Pointer to the attribute data structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_get_spd_data(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_data* i_mss_eff_config_data,
+ mss_eff_config_spd_data* o_spd_data,
+ mss_eff_config_atts* i_atts);
+
+ ///
+ /// @brief mss_eff_config_read_spd_data(): This function reads DIMM SPD data
+ /// @param[in] i_target_dimm: target dimm
+ /// @param[in,out] o_spd_data: Pointer to mss_eff configuration spd data structure
+ /// @param[in] i_port: current mba port
+ /// @param[in] i_dimm: current mba dimm
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_read_spd_data(const fapi2::Target<fapi2::TARGET_TYPE_DIMM> i_target_dimm,
+ mss_eff_config_spd_data* o_spd_data,
+ const uint8_t i_port, const uint8_t i_dimm);
+
+ ///
+ /// @brief mss_eff_config_verify_plug_rules(): This function verifies DIMM plug rules based on which dimms are present
+ /// @param[in] i_target_mba: the fapi2 target
+ /// @param[in] i_mss_eff_config_data: Pointer to mss_eff_config_data variable structure
+ /// @param[in] i_atts: Pointer to mss_eff configuration attributes structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_verify_plug_rules(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_data* i_mss_eff_config_data,
+ mss_eff_config_atts* i_atts);
+
+ ///
+ /// @brief mss_eff_config_verify_spd_data(): This function verifies DIMM SPD data
+ /// @param[in] i_target_mba: the fapi2 target
+ /// @param[in] i_atts: Pointer to mss_eff configuration attributes structure
+ /// @param[in] i_data: Pointer to mss_eff configuration spd data structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_verify_spd_data(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_atts* i_atts,
+ mss_eff_config_spd_data* i_data);
+
+ ///
+ /// @brief mss_eff_config_setup_eff_atts(): This function sets up the effective configuration attributes
+ /// @param[in] i_target_mba: the fapi2 target
+ /// @param[in] i_mss_eff_config_data: Pointer to mss_eff_config_data variable structure
+ /// @param[in] i_data: Pointer to mss_eff configuration spd data structure
+ /// @param[out] o_atts: Pointer to mss_eff configuration attributes structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_setup_eff_atts(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_data* i_mss_eff_config_data,
+ mss_eff_config_spd_data* i_data,
+ mss_eff_config_atts* o_atts);
+
+
+ ///
+ /// @brief mss_eff_config_write_eff_atts(): This function writes the effective configuration attributes
+ /// @param[in] i_target_mba: the fapi2 target
+ /// @param[in] i_atts: Pointer to mss_eff configuration attributes structure
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_write_eff_atts(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ mss_eff_config_atts* i_atts);
+
+ ///
+ /// @brief calc_timing_in_clk(): This function calculates tXX in clocks
+ /// @param[in] i_mtb_in_ps: Medium timebase in picoseconds
+ /// @param[in] i_ftb_in_fs: Fundamental timebase in femtoseconds
+ /// @param[in] i_unit: tXX value we are trying to calculate
+ /// @param[in] i_offset: Fine timebase offset
+ /// @param[in] i_mss_freq: Memory Frequency
+ /// @return l_timing_in_clk
+ ///
+ uint32_t calc_timing_in_clk(const uint32_t i_mtb_in_ps, const uint32_t i_ftb_in_fs,
+ const uint32_t i_unit, uint8_t i_offset, const uint32_t i_mss_freq);
+
+
+
+} // extern "C"
+
+#endif // MSS_EFF_CONFIG_H
+
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.mk
new file mode 100755
index 000000000..11e03b8b5
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.mk
@@ -0,0 +1,33 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+PROCEDURE=p9c_mss_eff_config
+OBJS+=p9c_mss_eff_pre_config.o
+OBJS+=p9c_mss_eff_config_rank_group.o
+OBJS+=p9c_mss_eff_config_shmoo.o
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.C
new file mode 100644
index 000000000..a36af727b
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.C
@@ -0,0 +1,300 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/// @file p9c_mss_eff_config_rank_group.C
+/// @brief Takes in attributes and determines proper rank groupings that will be applied to the system
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Anuwat Saetow <asaetow@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+///
+
+
+// This procedure takes in attributes and determines proper rank groupings that will be apply to the system and used during draminit_training and draminit_training_adv. Each valid rank in the system will be assigned to one of twelve attributes below. Only the primary rank group will be calibrated and have values stored in the delay registers.
+// EFF_PRIMARY_RANK_GROUP0, EFF_PRIMARY_RANK_GROUP1, EFF_PRIMARY_RANK_GROUP2, EFF_PRIMARY_RANK_GROUP3
+// EFF_SECONDARY_RANK_GROUP0, EFF_SECONDARY_RANK_GROUP1, EFF_SECONDARY_RANK_GROUP2, EFF_SECONDARY_RANK_GROUP3
+// EFF_TERTIARY_RANK_GROUP0, EFF_TERTIARY_RANK_GROUP1, EFF_TERTIARY_RANK_GROUP2, EFF_TERTIARY_RANK_GROUP3
+// EFF_QUATERNARY_RANK_GROUP0, EFF_QUATERNARY_RANK_GROUP1, EFF_QUATERNARY_RANK_GROUP2, EFF_QUATERNARY_RANK_GROUP3
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <dimmConsts.H>
+
+extern "C" {
+
+ ///
+ /// @brief mss_eff_config_rank_group determines proper rank groupings
+ /// @param[in] i_target_mba
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_rank_group(const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba)
+ {
+ const char* const PROCEDURE_NAME = "mss_eff_config_rank_group";
+ FAPI_INF("*** Running %s on %s ... ***", PROCEDURE_NAME, mss::c_str(i_target_mba));
+
+ uint8_t num_ranks_per_dimm_u8array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_num_master_ranks[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t dram_gen_u8 = 0;
+ uint8_t dimm_type_u8 = 0;
+ uint8_t l_stack_type[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t primary_rank_group0_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t primary_rank_group1_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t primary_rank_group2_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t primary_rank_group3_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t secondary_rank_group0_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t secondary_rank_group1_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t secondary_rank_group2_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t secondary_rank_group3_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t tertiary_rank_group0_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t tertiary_rank_group1_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t tertiary_rank_group2_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t tertiary_rank_group3_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t quanternary_rank_group0_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t quanternary_rank_group1_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t quanternary_rank_group2_u8array[MAX_PORTS_PER_MBA] = {0};
+ uint8_t quanternary_rank_group3_u8array[MAX_PORTS_PER_MBA] = {0};
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba, num_ranks_per_dimm_u8array));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba, dram_gen_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DIMM_TYPE, i_target_mba, dimm_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target_mba, l_num_master_ranks));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target_mba, l_stack_type));
+
+ for (uint8_t cur_port = 0; cur_port < MAX_PORTS_PER_MBA; cur_port += 1)
+ {
+ if ((num_ranks_per_dimm_u8array[cur_port][0] > 0) && (num_ranks_per_dimm_u8array[cur_port][1] == 0)) //Single Drop
+ {
+ primary_rank_group0_u8array[cur_port] = 0;
+
+ if (num_ranks_per_dimm_u8array[cur_port][0] > 1)
+ {
+ primary_rank_group1_u8array[cur_port] = 1;
+ }
+ else
+ {
+ primary_rank_group1_u8array[cur_port] = INVALID;
+ }
+
+ if (num_ranks_per_dimm_u8array[cur_port][0] > 2)
+ {
+ primary_rank_group2_u8array[cur_port] = 2;
+ primary_rank_group3_u8array[cur_port] = 3;
+ }
+ else
+ {
+ primary_rank_group2_u8array[cur_port] = INVALID;
+ primary_rank_group3_u8array[cur_port] = INVALID;
+ }
+
+ secondary_rank_group0_u8array[cur_port] = INVALID;
+ secondary_rank_group1_u8array[cur_port] = INVALID;
+ secondary_rank_group2_u8array[cur_port] = INVALID;
+ secondary_rank_group3_u8array[cur_port] = INVALID;
+
+ //Preet Add 3TSV /2H Type - Single Drop Case
+ //ATTR_EFF_STACK_TYPE <enum>NONE = 0, DDP_QDP = 1, STACK_3DS = 2</enum>
+
+ if((l_num_master_ranks[cur_port][0] != 0) && (dram_gen_u8 == 2) && (l_stack_type[cur_port][0] == 2))
+ {
+ if(num_ranks_per_dimm_u8array[cur_port][0] == 2)
+ {
+ primary_rank_group0_u8array[cur_port] = 0;
+ primary_rank_group1_u8array[cur_port] = INVALID;
+ primary_rank_group2_u8array[cur_port] = INVALID;
+ primary_rank_group3_u8array[cur_port] = INVALID;
+ secondary_rank_group0_u8array[cur_port] = 1;
+ secondary_rank_group1_u8array[cur_port] = INVALID;
+ secondary_rank_group2_u8array[cur_port] = INVALID;
+ secondary_rank_group3_u8array[cur_port] = INVALID;
+ }
+
+ //if 4H
+ else if(num_ranks_per_dimm_u8array[cur_port][0] == 4)
+ {
+ primary_rank_group0_u8array[cur_port] = 0;
+ primary_rank_group1_u8array[cur_port] = INVALID;
+ primary_rank_group2_u8array[cur_port] = INVALID;
+ primary_rank_group3_u8array[cur_port] = INVALID;
+ secondary_rank_group0_u8array[cur_port] = 1;
+ secondary_rank_group1_u8array[cur_port] = INVALID;
+ secondary_rank_group2_u8array[cur_port] = INVALID;
+ secondary_rank_group3_u8array[cur_port] = INVALID;
+ tertiary_rank_group0_u8array[cur_port] = 2;
+ tertiary_rank_group1_u8array[cur_port] = INVALID;
+ tertiary_rank_group2_u8array[cur_port] = INVALID;
+ tertiary_rank_group3_u8array[cur_port] = INVALID;
+ quanternary_rank_group0_u8array[cur_port] = 3;
+ quanternary_rank_group1_u8array[cur_port] = INVALID;
+ quanternary_rank_group2_u8array[cur_port] = INVALID;
+ quanternary_rank_group3_u8array[cur_port] = INVALID;
+ }
+
+ //if 8H <Add Later if Required>
+ } //end of if 3DS Stack
+ }
+ else if ((num_ranks_per_dimm_u8array[cur_port][0] > 0) && (num_ranks_per_dimm_u8array[cur_port][1] > 0)) //Dual Drop
+ {
+ if (num_ranks_per_dimm_u8array[cur_port][0] != num_ranks_per_dimm_u8array[cur_port][1])
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_RANK_GROUP_NON_MATCH_RANKS(),
+ "Plug rule violation, num_ranks_per_dimm=%d[0],%d[1] on %s PORT%d!", num_ranks_per_dimm_u8array[cur_port][0],
+ num_ranks_per_dimm_u8array[cur_port][1], mss::c_str(i_target_mba), cur_port);
+ }
+
+ primary_rank_group0_u8array[cur_port] = 0;
+ primary_rank_group1_u8array[cur_port] = 4;
+ primary_rank_group2_u8array[cur_port] = INVALID;
+ primary_rank_group3_u8array[cur_port] = INVALID;
+ secondary_rank_group0_u8array[cur_port] = INVALID;
+ secondary_rank_group1_u8array[cur_port] = INVALID;
+ secondary_rank_group2_u8array[cur_port] = INVALID;
+ secondary_rank_group3_u8array[cur_port] = INVALID;
+
+ if (num_ranks_per_dimm_u8array[cur_port][0] == 2)
+ {
+ primary_rank_group2_u8array[cur_port] = 1;
+ primary_rank_group3_u8array[cur_port] = 5;
+ }
+ else if (num_ranks_per_dimm_u8array[cur_port][0] == 4)
+ {
+ primary_rank_group2_u8array[cur_port] = 2;
+ primary_rank_group3_u8array[cur_port] = 6;
+ secondary_rank_group0_u8array[cur_port] = 1;
+ secondary_rank_group1_u8array[cur_port] = 5;
+ secondary_rank_group2_u8array[cur_port] = 3;
+ secondary_rank_group3_u8array[cur_port] = 7;
+ }
+ else if (num_ranks_per_dimm_u8array[cur_port][0] != 1)
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_RANK_GROUP_NUM_RANKS_NEQ1(),
+ "Plug rule violation, num_ranks_per_dimm=%d[0],%d[1] on %s PORT%d!", num_ranks_per_dimm_u8array[cur_port][0],
+ num_ranks_per_dimm_u8array[cur_port][1], mss::c_str(i_target_mba), cur_port);
+
+ }
+
+ //Preet Add 3TSV
+ if((l_num_master_ranks[cur_port][0] != 0) && (dram_gen_u8 == 2) && (l_stack_type[cur_port][0] == 2))
+ {
+ //2H Type - Dual Drop Case
+ if(num_ranks_per_dimm_u8array[cur_port][0] == 2)
+ {
+ primary_rank_group0_u8array[cur_port] = 0;
+ primary_rank_group1_u8array[cur_port] = 4;
+ primary_rank_group2_u8array[cur_port] = INVALID;
+ primary_rank_group3_u8array[cur_port] = INVALID;
+ secondary_rank_group0_u8array[cur_port] = INVALID;
+ secondary_rank_group1_u8array[cur_port] = INVALID;
+ secondary_rank_group2_u8array[cur_port] = INVALID;
+ secondary_rank_group3_u8array[cur_port] = INVALID;
+ }
+ //if 4H
+ else if(num_ranks_per_dimm_u8array[cur_port][0] == 4)
+ {
+ primary_rank_group0_u8array[cur_port] = 0;
+ primary_rank_group1_u8array[cur_port] = 4;
+ primary_rank_group2_u8array[cur_port] = INVALID;
+ primary_rank_group3_u8array[cur_port] = INVALID;
+ secondary_rank_group0_u8array[cur_port] = INVALID;
+ secondary_rank_group1_u8array[cur_port] = INVALID;
+ secondary_rank_group2_u8array[cur_port] = INVALID;
+ secondary_rank_group3_u8array[cur_port] = INVALID;
+ tertiary_rank_group0_u8array[cur_port] = INVALID;
+ tertiary_rank_group1_u8array[cur_port] = INVALID;
+ tertiary_rank_group2_u8array[cur_port] = INVALID;
+ tertiary_rank_group3_u8array[cur_port] = INVALID;
+ quanternary_rank_group0_u8array[cur_port] = INVALID;
+ quanternary_rank_group1_u8array[cur_port] = INVALID;
+ quanternary_rank_group2_u8array[cur_port] = INVALID;
+ quanternary_rank_group3_u8array[cur_port] = INVALID;
+ }
+
+ //if 8H <Add Later if Required>
+ } //end of if 3DS Stack
+ }
+ else if ((num_ranks_per_dimm_u8array[cur_port][0] == 0) && (num_ranks_per_dimm_u8array[cur_port][1] == 0))
+ {
+ primary_rank_group0_u8array[cur_port] = INVALID;
+ primary_rank_group1_u8array[cur_port] = INVALID;
+ primary_rank_group2_u8array[cur_port] = INVALID;
+ primary_rank_group3_u8array[cur_port] = INVALID;
+ secondary_rank_group0_u8array[cur_port] = INVALID;
+ secondary_rank_group1_u8array[cur_port] = INVALID;
+ secondary_rank_group2_u8array[cur_port] = INVALID;
+ secondary_rank_group3_u8array[cur_port] = INVALID;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_CONFIG_RANK_GROUP_NO_MATCH(),
+ "Plug rule violation, num_ranks_per_dimm=%d[0],%d[1] on %s PORT%d!", num_ranks_per_dimm_u8array[cur_port][0],
+ num_ranks_per_dimm_u8array[cur_port][1], mss::c_str(i_target_mba), cur_port);
+
+ }
+
+ tertiary_rank_group0_u8array[cur_port] = INVALID;
+ tertiary_rank_group1_u8array[cur_port] = INVALID;
+ tertiary_rank_group2_u8array[cur_port] = INVALID;
+ tertiary_rank_group3_u8array[cur_port] = INVALID;
+ quanternary_rank_group0_u8array[cur_port] = INVALID;
+ quanternary_rank_group1_u8array[cur_port] = INVALID;
+ quanternary_rank_group2_u8array[cur_port] = INVALID;
+ quanternary_rank_group3_u8array[cur_port] = INVALID;
+
+ FAPI_INF("P[%02d][%02d][%02d][%02d],S[%02d][%02d][%02d][%02d],T[%02d][%02d][%02d][%02d],Q[%02d][%02d][%02d][%02d] on %s PORT%d.",
+ primary_rank_group0_u8array[cur_port], primary_rank_group1_u8array[cur_port], primary_rank_group2_u8array[cur_port],
+ primary_rank_group3_u8array[cur_port], secondary_rank_group0_u8array[cur_port], secondary_rank_group1_u8array[cur_port],
+ secondary_rank_group2_u8array[cur_port], secondary_rank_group3_u8array[cur_port],
+ tertiary_rank_group0_u8array[cur_port], tertiary_rank_group1_u8array[cur_port], tertiary_rank_group2_u8array[cur_port],
+ tertiary_rank_group3_u8array[cur_port], quanternary_rank_group0_u8array[cur_port],
+ quanternary_rank_group1_u8array[cur_port], quanternary_rank_group2_u8array[cur_port],
+ quanternary_rank_group3_u8array[cur_port], mss::c_str(i_target_mba), cur_port);
+ } // For port
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_PRIMARY_RANK_GROUP0, i_target_mba, primary_rank_group0_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_PRIMARY_RANK_GROUP1, i_target_mba, primary_rank_group1_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_PRIMARY_RANK_GROUP2, i_target_mba, primary_rank_group2_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_PRIMARY_RANK_GROUP3, i_target_mba, primary_rank_group3_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SECONDARY_RANK_GROUP0, i_target_mba, secondary_rank_group0_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SECONDARY_RANK_GROUP1, i_target_mba, secondary_rank_group1_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SECONDARY_RANK_GROUP2, i_target_mba, secondary_rank_group2_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SECONDARY_RANK_GROUP3, i_target_mba, secondary_rank_group3_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_TERTIARY_RANK_GROUP0, i_target_mba, tertiary_rank_group0_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_TERTIARY_RANK_GROUP1, i_target_mba, tertiary_rank_group1_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_TERTIARY_RANK_GROUP2, i_target_mba, tertiary_rank_group2_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_TERTIARY_RANK_GROUP3, i_target_mba, tertiary_rank_group3_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_QUATERNARY_RANK_GROUP0, i_target_mba, quanternary_rank_group0_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_QUATERNARY_RANK_GROUP1, i_target_mba, quanternary_rank_group1_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_QUATERNARY_RANK_GROUP2, i_target_mba, quanternary_rank_group2_u8array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_QUATERNARY_RANK_GROUP3, i_target_mba, quanternary_rank_group3_u8array));
+
+ FAPI_INF("%s on %s COMPLETE", PROCEDURE_NAME, mss::c_str(i_target_mba));
+ fapi_try_exit:
+ return fapi2::current_err;
+ } //rank group
+} // extern "C"
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.H
new file mode 100644
index 000000000..29d9c46c7
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.H
@@ -0,0 +1,62 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/// @file p9c_mss_eff_config_rank_group.H
+/// @brief Takes in attributes and determines proper rank groupings that will be applied to the system
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Anuwat Saetow <asaetow@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+#ifndef MSS_EFF_CONFIG_RANK_GROUP_H_
+#define MSS_EFF_CONFIG_RANK_GROUP_H_
+
+//----------------------------------------------------------------------
+// My Includes
+//----------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include <fapi2.H>
+
+
+typedef fapi2::ReturnCode (*mss_eff_config_rank_group_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba);
+
+extern "C" {
+
+ ///
+ /// @brief mss_eff_config_rank_group determines proper rank groupings
+ /// @param[in] i_target_mba
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_rank_group(const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba);
+
+} // extern "C"
+
+#endif // MSS_EFF_CONFIG_RANK_GROUP_H_
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.mk
new file mode 100755
index 000000000..d2f164ba9
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.mk
@@ -0,0 +1,30 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_rank_group.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+
+PROCEDURE=p9c_mss_eff_config_rank_group
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.C
new file mode 100644
index 000000000..c6af770ee
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.C
@@ -0,0 +1,170 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/// @file p9c_mss_eff_config_shmoo.C
+/// @brief setup shmoo attrs
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include <fapi2.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <dimmConsts.H>
+
+extern "C" {
+ ///
+ /// @brief mss_eff_config_shmoo : Sets up shmoo attrs
+ /// @param[in] i_target_mba
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba)
+ {
+ uint32_t l_datapattern = 0; // mdb - type 8 is not valid per Saravanan's Sametime
+ uint32_t l_testtype = 37; // SIMPLE_FIX_RF
+ uint8_t l_addr_modes = 1;
+ uint8_t l_rank = 0;
+ uint64_t l_start_addr = 0;
+ uint64_t l_end_addr = 0;
+ uint8_t l_error_capture = 0;
+ uint64_t l_max_timeout = 0;
+ uint8_t l_print_port = 0;
+ uint8_t l_stop_on_error = 0;
+ uint32_t l_data_seed = 0;
+ uint8_t l_addr_inter = 0;
+ uint8_t l_addr_num_rows = 0;
+ uint8_t l_addr_num_cols = 0;
+ uint8_t l_addr_rank = 0;
+ uint8_t l_addr_bank = 0;
+ uint8_t l_addr_slave_rank_on = 0;
+ uint64_t l_adr_str_map = 0;
+ uint8_t l_addr_rand = 0;
+ uint8_t l_shmoo_mode = 0;
+ uint8_t l_shmoo_addr_mode = 3;
+ uint8_t l_shmoo_param_valid = 0;
+ uint8_t l_shmoo_test_valid = 0;
+ uint8_t l_wr_eye_min_margin = 0x46;
+ uint8_t l_rd_eye_min_margin = 0x46;
+ uint8_t l_dqs_clk_min_margin = 0x8c;
+ uint8_t l_rd_gate_min_margin = 0x64;
+ uint8_t l_adr_cmd_min_margin = 0x8c;
+ uint32_t l_cen_rd_vref_shmoo[MAX_PORTS_PER_MBA] = { 0x00000000, 0x00000000 };
+ uint32_t l_dram_wr_vref_schmoo[MAX_PORTS_PER_MBA] = { 0x00000000 , 0x00000000 };
+ uint32_t l_cen_rcv_imp_dq_dqs_schmoo[MAX_PORTS_PER_MBA] = { 0x00000000, 0x00000000 };
+ uint32_t l_cen_drv_imp_dq_dqs_schmoo[MAX_PORTS_PER_MBA] = { 0x00000000, 0x00000000 };
+ uint8_t l_cen_drv_imp_cntl_schmoo[MAX_PORTS_PER_MBA] = { 0x00, 0x00 };
+ uint8_t l_cen_drv_imp_clk_schmoo[MAX_PORTS_PER_MBA] = { 0x00, 0x00 };
+ uint8_t l_cen_drv_imp_spcke_schmoo[MAX_PORTS_PER_MBA] = { 0x00, 0x00 };
+ uint8_t l_cen_slew_rate_dq_dqs_schmoo[MAX_PORTS_PER_MBA] = { 0x00, 0x00 };
+ uint8_t l_cen_slew_rate_cntl_schmoo[MAX_PORTS_PER_MBA] = { 0x00, 0x00 };
+ uint8_t l_cen_slew_rate_addr_schmoo[MAX_PORTS_PER_MBA] = { 0x00, 0x00 };
+ uint8_t l_cen_slew_rate_clk_schmoo[MAX_PORTS_PER_MBA] = { 0x00, 0x00 };
+ uint8_t l_cen_slew_rate_spcke_schmoo[MAX_PORTS_PER_MBA] = { 0x00, 0x00 };
+ uint8_t l_mcb_print_disable = 0;
+ uint8_t l_mcb_data_en = 0;
+ uint8_t l_mcb_user_rank = 0;
+ uint8_t l_mcb_user_bank = 0;
+ uint8_t l_shmoo_mul_setup_call = 0;
+ uint32_t l_rand_seed_val = 0;
+ uint8_t l_rand_seed_type = 0x01;
+ uint32_t l_attr_eff_cen_rd_vref[MAX_PORTS_PER_MBA] = {0};
+ uint32_t l_attr_eff_dram_wr_vref[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_attr_eff_cen_rcv_imp_dq_dqs[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_attr_eff_cen_drv_imp_dq_dqs[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_attr_eff_cen_slew_rate_dq_dqs[MAX_PORTS_PER_MBA] = {0};
+
+
+ // get these attributes from the VPD but allow the code to override later
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_RD_VREF, i_target_mba, l_attr_eff_cen_rd_vref));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRAM_WR_VREF, i_target_mba, l_attr_eff_dram_wr_vref));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_RCV_IMP_DQ_DQS, i_target_mba, l_attr_eff_cen_rcv_imp_dq_dqs));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRV_IMP_DQ_DQS, i_target_mba, l_attr_eff_cen_drv_imp_dq_dqs));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_SLEW_RATE_DQ_DQS, i_target_mba, l_attr_eff_cen_slew_rate_dq_dqs));
+
+ // attriubtes that are needing to be copied from VPD into scratch pads
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_RD_VREF, i_target_mba, l_attr_eff_cen_rd_vref));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_WR_VREF, i_target_mba, l_attr_eff_dram_wr_vref));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_RCV_IMP_DQ_DQS, i_target_mba, l_attr_eff_cen_rcv_imp_dq_dqs));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS, i_target_mba, l_attr_eff_cen_drv_imp_dq_dqs));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS, i_target_mba, l_attr_eff_cen_slew_rate_dq_dqs));
+
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_PRINTING_DISABLE, i_target_mba, l_mcb_print_disable));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_DATA_ENABLE, i_target_mba, l_mcb_data_en));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_USER_RANK, i_target_mba, l_mcb_user_rank));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_USER_BANK, i_target_mba, l_mcb_user_bank));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_SCHMOO_MULTIPLE_SETUP_CALL, i_target_mba, l_shmoo_mul_setup_call));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_PATTERN, i_target_mba, l_datapattern));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_TEST_TYPE, i_target_mba, l_testtype));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_MODES, i_target_mba, l_addr_modes));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_RANK, i_target_mba, l_rank));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_START_ADDR, i_target_mba, l_start_addr));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_END_ADDR, i_target_mba, l_end_addr));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ERROR_CAPTURE, i_target_mba, l_error_capture));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_MAX_TIMEOUT, i_target_mba, l_max_timeout));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_PRINT_PORT, i_target_mba, l_print_port));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_STOP_ON_ERROR, i_target_mba, l_stop_on_error));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_DATA_SEED, i_target_mba, l_data_seed));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_INTER, i_target_mba, l_addr_inter));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_NUM_ROWS, i_target_mba, l_addr_num_rows));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_NUM_COLS, i_target_mba, l_addr_num_cols));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_RANK, i_target_mba, l_addr_rank));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_BANK, i_target_mba, l_addr_bank));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_SLAVE_RANK_ON, i_target_mba, l_addr_slave_rank_on));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_STR_MAP, i_target_mba, l_adr_str_map));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_RAND, i_target_mba, l_addr_rand));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_MODE, i_target_mba, l_shmoo_mode));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_ADDR_MODE, i_target_mba, l_shmoo_addr_mode));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_PARAM_VALID, i_target_mba, l_shmoo_param_valid));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, l_shmoo_test_valid));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_WR_EYE_MIN_MARGIN, i_target_mba, l_wr_eye_min_margin));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_RD_EYE_MIN_MARGIN, i_target_mba, l_rd_eye_min_margin));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_DQS_CLK_MIN_MARGIN, i_target_mba, l_dqs_clk_min_margin));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_RD_GATE_MIN_MARGIN, i_target_mba, l_rd_gate_min_margin));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_ADDR_CMD_MIN_MARGIN, i_target_mba, l_adr_cmd_min_margin));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_RD_VREF_SCHMOO, i_target_mba, l_cen_rd_vref_shmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_WR_VREF_SCHMOO, i_target_mba, l_dram_wr_vref_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_RCV_IMP_DQ_DQS_SCHMOO, i_target_mba, l_cen_rcv_imp_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_SCHMOO, i_target_mba, l_cen_drv_imp_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_CNTL_SCHMOO, i_target_mba, l_cen_drv_imp_cntl_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_CLK_SCHMOO, i_target_mba, l_cen_drv_imp_clk_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_SPCKE_SCHMOO, i_target_mba, l_cen_drv_imp_spcke_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS_SCHMOO, i_target_mba, l_cen_slew_rate_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_CNTL_SCHMOO, i_target_mba, l_cen_slew_rate_cntl_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_ADDR_SCHMOO, i_target_mba, l_cen_slew_rate_addr_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_CLK_SCHMOO, i_target_mba, l_cen_slew_rate_clk_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_SPCKE_SCHMOO, i_target_mba, l_cen_slew_rate_spcke_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_RANDOM_SEED_VALUE, i_target_mba, l_rand_seed_val));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_RANDOM_SEED_TYPE, i_target_mba, l_rand_seed_type));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+} // extern "C"
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.H
new file mode 100644
index 000000000..f821b1598
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.H
@@ -0,0 +1,61 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// @file p9c_mss_eff_config_shmoo.H
+/// @brief Takes in attributes and determines proper rank groupings that will be applied to the system
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+#ifndef MSS_EFF_CONFIG_SHMOO_H_
+#define MSS_EFF_CONFIG_SHMOO_H_
+
+//----------------------------------------------------------------------
+// My Includes
+//----------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include <fapi2.H>
+
+
+typedef fapi2::ReturnCode (*mss_eff_config_shmoo_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba);
+
+extern "C" {
+
+ ///
+ /// @brief Takes in attributes and determines proper rank groupings that will be applied to the system
+ /// @param[in] i_target_mba
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA> i_target_mba);
+
+} // extern "C"
+
+#endif // MSS_EFF_CONFIG_SHMOO_H_
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.mk
new file mode 100755
index 000000000..c674b4e33
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.mk
@@ -0,0 +1,30 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_shmoo.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+
+PROCEDURE=p9c_mss_eff_config_shmoo
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.C
new file mode 100644
index 000000000..87489fece
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.C
@@ -0,0 +1,658 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// @file p9c_mss_eff_config_thermal.C
+/// @brief set the default throttle and power attributes for dimms in a given system
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Mike Pardeik <pardeik@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+// attributes for dimms in a given system
+// -- The power attributes are the slope/intercept values. Note that these
+// values are in cW.
+// -- ISDIMM will calculate values based on various attributes
+// -- CDIMM will get values from VPD
+// -- The throttle attributes will setup values for IPL and runtime
+//
+//------------------------------------------------------------------------------
+// My Includes
+//------------------------------------------------------------------------------
+#include <p9c_mss_eff_config_thermal.H>
+#include <p9c_mss_bulk_pwr_throttles.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <dimmConsts.H>
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include <fapi2.H>
+
+// Only use values here (not any valid bits or flag bits)
+constexpr uint32_t CDIMM_POWER_SLOPE_DEFAULT = 0x0358;
+constexpr uint32_t CDIMM_POWER_INT_DEFAULT = 0x00CE;
+
+extern "C" {
+ ///
+ /// @brief mss_eff_config_thermal(): This function determines the
+ /// power curve and throttle attribute values to use
+ /// @param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> & i_target_mba: MBA Target<fapi2::TARGET_TYPE_MBA> passed in
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode p9c_mss_eff_config_thermal(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+ {
+
+ FAPI_INF("*** Running mss_eff_config_thermal on %s ***",
+ mss::c_str(i_target_mba));
+
+ FAPI_TRY(mss_eff_config_thermal_powercurve(i_target_mba));
+ FAPI_TRY(mss_eff_config_thermal_throttles(i_target_mba));
+
+
+ FAPI_INF("*** mss_eff_config_thermal COMPLETE on %s ***",
+ mss::c_str(i_target_mba));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief mss_eff_config_thermal_powercurve(): This function determines the
+ /// power curve attribute values to use
+ /// @param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> & i_target_mba: MBA Target<fapi2::TARGET_TYPE_MBA> passed in
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_thermal_powercurve(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+ {
+ FAPI_INF("*** Running mss_eff_config_thermal_powercurve on %s ***",
+ mss::c_str(i_target_mba));
+ uint8_t l_port = 0;
+ uint8_t l_dimm = 0;
+ uint8_t l_custom_dimm = 0;
+ uint8_t l_dimm_ranks_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_power_slope_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_power_int_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_power_slope2_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_power_int2_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_total_power_slope_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_total_power_int_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_total_power_slope2_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_total_power_int2_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_cdimm_master_power_slope = 0;
+ uint32_t l_cdimm_master_power_intercept = 0;
+ uint32_t l_cdimm_supplier_power_slope = 0;
+ uint32_t l_cdimm_supplier_power_intercept = 0;
+ uint32_t l_cdimm_master_total_power_slope = 0;
+ uint32_t l_cdimm_master_total_power_intercept = 0;
+ uint32_t l_cdimm_supplier_total_power_slope = 0;
+ uint32_t l_cdimm_supplier_total_power_intercept = 0;
+ uint8_t l_dram_gen = 0;
+ uint8_t l_logged_error_power_curve = 0;
+ uint8_t l_logged_error_total_power_curve = 0;
+
+ //------------------------------------------------------------------------------
+ // Get input attributes
+ //------------------------------------------------------------------------------
+
+ // Get Centaur target for the given MBA
+ const auto l_target_chip = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target_mba, l_custom_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM,
+ i_target_mba, l_dimm_ranks_array));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN,
+ i_target_mba, l_dram_gen));
+
+ // Only get power curve values for custom dimms to prevent errors
+ if (l_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ // These are the CDIMM power curve values for only VMEM (DDR3 and DDR4)
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_MASTER_POWER_SLOPE,
+ l_target_chip, l_cdimm_master_power_slope));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_MASTER_POWER_INTERCEPT,
+ l_target_chip, l_cdimm_master_power_intercept));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_SUPPLIER_POWER_SLOPE,
+ l_target_chip, l_cdimm_supplier_power_slope));
+
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_SUPPLIER_POWER_INTERCEPT,
+ l_target_chip, l_cdimm_supplier_power_intercept));
+
+
+ // These are for the total CDIMM power (VMEM+VPP for DDR4)
+ if (l_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ {
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_MASTER_TOTAL_POWER_SLOPE,
+ l_target_chip, l_cdimm_master_total_power_slope));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_MASTER_TOTAL_POWER_INTERCEPT,
+ l_target_chip, l_cdimm_master_total_power_intercept));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_SUPPLIER_TOTAL_POWER_SLOPE,
+ l_target_chip, l_cdimm_supplier_total_power_slope));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_SUPPLIER_TOTAL_POWER_INTERCEPT,
+ l_target_chip, l_cdimm_supplier_total_power_intercept));
+ }
+ else
+ {
+ // Set total power curve variables to the VMEM power curve variables for DDR3
+ l_cdimm_master_total_power_slope = l_cdimm_master_power_slope;
+ l_cdimm_master_total_power_intercept = l_cdimm_master_power_intercept;
+ l_cdimm_supplier_total_power_slope = l_cdimm_supplier_power_slope;
+ l_cdimm_supplier_total_power_intercept = l_cdimm_supplier_power_intercept;
+ }
+ }
+
+ // Power Curve Determination
+ // Iterate through the MBA ports to get power slope/intercept values
+ for (l_port = 0; l_port + MAX_PORTS_PER_MBA; l_port++)
+ {
+ // iterate through the dimms on each port again to determine power slope and
+ // intercept
+ for (l_dimm = 0; l_dimm + MAX_DIMM_PER_PORT; l_dimm++)
+ {
+ // initialize dimm entries to zero
+ l_power_slope_array[l_port][l_dimm] = 0;
+ l_power_int_array[l_port][l_dimm] = 0;
+ l_power_slope2_array[l_port][l_dimm] = 0;
+ l_power_int2_array[l_port][l_dimm] = 0;
+ l_total_power_slope_array[l_port][l_dimm] = 0;
+ l_total_power_int_array[l_port][l_dimm] = 0;
+ l_total_power_slope2_array[l_port][l_dimm] = 0;
+ l_total_power_int2_array[l_port][l_dimm] = 0;
+
+ // only update values for l_dimms that are physically present
+ if (l_dimm_ranks_array[l_port][l_dimm] > 0)
+ {
+ // CDIMM power slope/intercept will come from VPD
+ // Data in VPD needs to be the power per virtual dimm on the CDIMM
+ if (l_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ l_power_slope_array[l_port][l_dimm] =
+ l_cdimm_master_power_slope;
+ l_power_int_array[l_port][l_dimm] =
+ l_cdimm_master_power_intercept;
+ l_power_slope2_array[l_port][l_dimm] =
+ l_cdimm_supplier_power_slope;
+ l_power_int2_array[l_port][l_dimm] =
+ l_cdimm_supplier_power_intercept;
+ l_total_power_slope_array[l_port][l_dimm] =
+ l_cdimm_master_total_power_slope;
+ l_total_power_int_array[l_port][l_dimm] =
+ l_cdimm_master_total_power_intercept;
+ l_total_power_slope2_array[l_port][l_dimm] =
+ l_cdimm_supplier_total_power_slope;
+ l_total_power_int2_array[l_port][l_dimm] =
+ l_cdimm_supplier_total_power_intercept;
+
+ // check to see if VMEM power curve data is valid
+ if (
+ (((l_cdimm_master_power_slope & 0x8000) != 0) &&
+ ((l_cdimm_master_power_intercept & 0x8000) != 0))
+ &&
+ (((l_cdimm_supplier_power_slope & 0x8000) != 0) &&
+ ((l_cdimm_supplier_power_intercept & 0x8000) != 0))
+ )
+ {
+ l_power_slope_array[l_port][l_dimm] =
+ l_cdimm_master_power_slope & 0x1FFF;
+ l_power_int_array[l_port][l_dimm] =
+ l_cdimm_master_power_intercept & 0x1FFF;
+ l_power_slope2_array[l_port][l_dimm] =
+ l_cdimm_supplier_power_slope & 0x1FFF;
+ l_power_int2_array[l_port][l_dimm] =
+ l_cdimm_supplier_power_intercept & 0x1FFF;
+
+ // check to see if data is lab data
+ if (
+ (((l_cdimm_master_power_slope & 0x4000) == 0) ||
+ ((l_cdimm_master_power_intercept & 0x4000) == 0))
+ ||
+ (((l_cdimm_supplier_power_slope & 0x4000) == 0) ||
+ ((l_cdimm_supplier_power_intercept &
+ 0x4000) == 0))
+ )
+ {
+ FAPI_INF("WARNING: VMEM power curve data is lab data, not ship level data. Using data anyways.");
+ }
+
+ // check total power curve (VMEM+VPP) values for DDR4
+ if (l_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ {
+ if (
+ (((l_cdimm_master_total_power_slope & 0x8000) != 0) &&
+ ((l_cdimm_master_total_power_intercept & 0x8000) != 0))
+ &&
+ (((l_cdimm_supplier_total_power_slope & 0x8000) != 0) &&
+ ((l_cdimm_supplier_total_power_intercept & 0x8000) != 0))
+ )
+ {
+ l_total_power_slope_array[l_port][l_dimm] =
+ l_cdimm_master_total_power_slope & 0x1FFF;
+ l_total_power_int_array[l_port][l_dimm] =
+ l_cdimm_master_total_power_intercept & 0x1FFF;
+ l_total_power_slope2_array[l_port][l_dimm] =
+ l_cdimm_supplier_total_power_slope & 0x1FFF;
+ l_total_power_int2_array[l_port][l_dimm] =
+ l_cdimm_supplier_total_power_intercept & 0x1FFF;
+
+ // check to see if data is lab data
+ if (
+ (((l_cdimm_master_total_power_slope & 0x4000) == 0) ||
+ ((l_cdimm_master_total_power_intercept & 0x4000) == 0))
+ ||
+ (((l_cdimm_supplier_total_power_slope & 0x4000) == 0) ||
+ ((l_cdimm_supplier_total_power_intercept &
+ 0x4000) == 0))
+ )
+ {
+ FAPI_INF("WARNING: Total power curve data is lab data, not ship level data. Using data anyways.");
+ }
+ }
+ else
+ {
+ // Set to VMEM power curve values if total values are not valid and log an error
+ // early DDR4 CDIMMs will have the total power curve entries all zero (not valid)
+ l_total_power_slope_array[l_port][l_dimm] =
+ l_power_slope_array[l_port][l_dimm];
+ l_total_power_int_array[l_port][l_dimm] =
+ l_power_int_array[l_port][l_dimm];
+ l_total_power_slope2_array[l_port][l_dimm] =
+ l_power_slope2_array[l_port][l_dimm];
+ l_total_power_int2_array[l_port][l_dimm] =
+ l_power_int2_array[l_port][l_dimm];
+
+ // only log the error once per MBA, since all dimms will have the same power curve values
+ if (l_logged_error_total_power_curve == 0)
+ {
+ l_logged_error_total_power_curve = 1;
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_DIMM_POWER_CURVE_DATA_INVALID().
+ set_MEM_CHIP(l_target_chip).
+ set_FFDC_DATA_1(l_cdimm_master_power_slope).
+ set_FFDC_DATA_2(l_cdimm_master_power_intercept).
+ set_FFDC_DATA_3(l_cdimm_supplier_power_slope).
+ set_FFDC_DATA_4(l_cdimm_supplier_power_intercept),
+ "");
+ }
+ }
+ }
+ else
+ {
+ // Set total power curve values to VMEM power curve values for anything other than DDR4 (ie. DDR3)
+ l_total_power_slope_array[l_port][l_dimm] =
+ l_power_slope_array[l_port][l_dimm];
+ l_total_power_int_array[l_port][l_dimm] =
+ l_power_int_array[l_port][l_dimm];
+ l_total_power_slope2_array[l_port][l_dimm] =
+ l_power_slope2_array[l_port][l_dimm];
+ l_total_power_int2_array[l_port][l_dimm] =
+ l_power_int2_array[l_port][l_dimm];
+ }
+ }
+ else
+ {
+ // Set to default values and log an error if VMEM power curve values are not valid
+ l_power_slope_array[l_port][l_dimm] =
+ CDIMM_POWER_SLOPE_DEFAULT;
+ l_power_int_array[l_port][l_dimm] =
+ CDIMM_POWER_INT_DEFAULT;
+ l_power_slope2_array[l_port][l_dimm] =
+ CDIMM_POWER_SLOPE_DEFAULT;
+ l_power_int2_array[l_port][l_dimm] =
+ CDIMM_POWER_INT_DEFAULT;
+ l_total_power_slope_array[l_port][l_dimm] =
+ CDIMM_POWER_SLOPE_DEFAULT;
+ l_total_power_int_array[l_port][l_dimm] =
+ CDIMM_POWER_INT_DEFAULT;
+ l_total_power_slope2_array[l_port][l_dimm] =
+ CDIMM_POWER_SLOPE_DEFAULT;
+ l_total_power_int2_array[l_port][l_dimm] =
+ CDIMM_POWER_INT_DEFAULT;
+
+ // only log the error once per MBA, since all dimms will have the same power curve values
+ if (l_logged_error_power_curve == 0)
+ {
+ l_logged_error_power_curve = 1;
+
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_DIMM_POWER_CURVE_DATA_INVALID().
+ set_MEM_CHIP(l_target_chip).
+ set_FFDC_DATA_1(l_cdimm_master_power_slope).
+ set_FFDC_DATA_2(l_cdimm_master_power_intercept).
+ set_FFDC_DATA_3(l_cdimm_supplier_power_slope).
+ set_FFDC_DATA_4(l_cdimm_supplier_power_intercept),
+ "");
+ }
+ }
+
+ FAPI_DBG("CDIMM VMEM Power [P%d:D%d][SLOPE=%d:INT=%d cW][SLOPE2=%d:INT2=%d cW]", l_port, l_dimm,
+ l_power_slope_array[l_port][l_dimm], l_power_int_array[l_port][l_dimm], l_power_slope2_array[l_port][l_dimm],
+ l_power_int2_array[l_port][l_dimm]);
+ FAPI_DBG("CDIMM Total Power [P%d:D%d][VMEM SLOPE=%d:INT=%d cW][VMEM SLOPE2=%d:INT2=%d cW]", l_port, l_dimm,
+ l_total_power_slope_array[l_port][l_dimm], l_total_power_int_array[l_port][l_dimm],
+ l_total_power_slope2_array[l_port][l_dimm],
+ l_total_power_int2_array[l_port][l_dimm]);
+ }
+
+ // non custom dimms will no longer use power curves
+ // These will use a simplified approach of using throttle values for certain ranges of power
+ // in mss_bulk_pwr_throttles.
+ }
+ }
+ }
+
+ // write output attributes
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_POWER_SLOPE,
+ i_target_mba, l_power_slope_array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_POWER_INT, i_target_mba, l_power_int_array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_POWER_SLOPE2,
+ i_target_mba, l_power_slope2_array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_POWER_INT2,
+ i_target_mba, l_power_int2_array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_SLOPE,
+ i_target_mba, l_total_power_slope_array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_INT, i_target_mba, l_total_power_int_array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_SLOPE2,
+ i_target_mba, l_total_power_slope2_array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_INT2,
+ i_target_mba, l_total_power_int2_array));
+ FAPI_INF("*** mss_eff_config_thermal_powercurve COMPLETE on %s ***",
+ mss::c_str(i_target_mba));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief mss_eff_config_thermal_throttles(): This function determines the throttle attribute values to use
+ /// @l_param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> & i_target_mba: MBA Target<fapi2::TARGET_TYPE_MBA> passed in
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_thermal_throttles(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+ {
+
+ FAPI_INF("*** Running mss_eff_config_thermal_throttles on %s ***",
+ mss::c_str(i_target_mba));
+
+// variables used in this function
+ uint8_t l_custom_dimm = 0;
+ uint8_t l_num_dimms_on_port = 0;
+ uint32_t l_runtime_throttle_n_per_mba = 0;
+ uint32_t l_runtime_throttle_n_per_chip = 0;
+ uint32_t l_runtime_throttle_d = 0;
+ uint32_t l_dimm_thermal_power_limit = 0;
+ uint32_t l_channel_pair_thermal_power_limit = 0;
+ uint8_t l_num_mba_with_dimms = 0;
+ uint8_t l_mba_index = 0;
+ uint8_t l_ras_increment = 0;
+ uint8_t l_cas_increment = 0;
+ uint32_t l_max_dram_databus_util = 0;
+ uint32_t l_dimm_reg_power_limit_per_dimm_adj = 0;
+ uint32_t l_dimm_reg_power_limit_per_dimm = 0;
+ uint32_t l_dimm_reg_power_limit_per_dimm_ddr4 = 0;
+ uint8_t l_max_number_dimms_per_reg = 0;
+ uint8_t l_dimm_reg_power_limit_adj_enable = 0;
+ uint8_t l_reg_max_dimm_count = 0;
+ uint8_t l_dram_gen = 0;
+ uint32_t l_power_slope_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_power_int_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_total_power_slope_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint32_t l_total_power_int_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ float MAX_UTIL;
+ fapi2::ReturnCode rc;
+
+ // Get Centaur target for the given MBA
+ const auto l_target_chip = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target_mba, l_custom_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_DROPS_PER_PORT,
+ i_target_mba, l_num_dimms_on_port));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_THERMAL_MEMORY_POWER_LIMIT,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_dimm_thermal_power_limit));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_MEM_THROTTLE_DENOMINATOR, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_runtime_throttle_d));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_MAX_DRAM_DATABUS_UTIL,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_max_dram_databus_util));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_VMEM_REGULATOR_MEMORY_POWER_LIMIT_PER_DIMM,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_dimm_reg_power_limit_per_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_VMEM_REGULATOR_MEMORY_POWER_LIMIT_PER_DIMM_DDR4,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_dimm_reg_power_limit_per_dimm_ddr4));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_MAX_NUMBER_DIMMS_POSSIBLE_PER_VMEM_REGULATOR,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_max_number_dimms_per_reg));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_VMEM_REGULATOR_POWER_LIMIT_PER_DIMM_ADJ_ENABLE,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_dimm_reg_power_limit_adj_enable));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VMEM_REGULATOR_MAX_DIMM_COUNT,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_reg_max_dimm_count));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN,
+ i_target_mba, l_dram_gen));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_POWER_SLOPE,
+ i_target_mba, l_power_slope_array));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_POWER_INT,
+ i_target_mba, l_power_int_array));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_SLOPE,
+ i_target_mba, l_total_power_slope_array));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_INT,
+ i_target_mba, l_total_power_int_array));
+
+ // Get number of Centaur MBAs that have dimms present
+ // Custom dimms (CDIMMs) use mba/chip throttling, so count number of mbas that have dimms
+ if (l_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ const auto l_target_mba_array = l_target_chip.getChildren<fapi2::TARGET_TYPE_MBA>();
+ l_num_mba_with_dimms = 0;
+
+ for (l_mba_index = 0; l_mba_index + l_target_mba_array.size(); l_mba_index++)
+ {
+ const auto l_target_dimm_array = l_target_mba_array[l_mba_index].getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ if (l_target_dimm_array.size() > 0)
+ {
+ l_num_mba_with_dimms++;
+ }
+ }
+ }
+ // ISDIMM (non custom dimm) uses dimm/mba throttling, so set num_mba_with_dimms to 1
+ else
+ {
+ l_num_mba_with_dimms = 1;
+ }
+
+
+//------------------------------------------------------------------------------
+// Memory Throttle Determination
+//------------------------------------------------------------------------------
+
+// Determine memory throttle settings needed based on dimm thermal power limit
+
+//------------------------------------------------------------------------------
+// Determine the thermal power limit to use, which represents a single channel
+// pair power limit for the dimms on that channel pair (ie. power for all dimms
+// attached to one MBA). The procedure mss_bulk_power_throttles takes the
+// input of channel pair power to determine throttles.
+// CDIMM thermal power limit from MRW is per CDIMM, so divide by number of mbas
+// that have dimms to get channel pair power
+// CDIMM: Allow all commands to be directed toward one MBA to achieve the power
+// limit
+// This means that the power limit for a MBA channel pair must be the total
+// CDIMM power limit minus the idle power of the other MBAs logical dimms
+//------------------------------------------------------------------------------
+
+ // adjust the regulator power limit per dimm if enabled and use this if less than the thermal limit
+
+ // If DDR4, use DDR4 regulator power limit
+ if (l_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ {
+ l_dimm_reg_power_limit_per_dimm = l_dimm_reg_power_limit_per_dimm_ddr4;
+ }
+
+ // If reg power limit is zero, then set to thermal limit - needed for ISDIMM systems since some of these MRW attributes are not defined
+ if (l_dimm_reg_power_limit_per_dimm == 0)
+ {
+ l_dimm_reg_power_limit_per_dimm = l_dimm_thermal_power_limit;
+ }
+
+ l_dimm_reg_power_limit_per_dimm_adj = l_dimm_reg_power_limit_per_dimm;
+
+ if (l_dimm_reg_power_limit_adj_enable == fapi2::ENUM_ATTR_CEN_MRW_VMEM_REGULATOR_POWER_LIMIT_PER_DIMM_ADJ_ENABLE_TRUE)
+ {
+ // adjust reg power limit per cdimm only if l_reg_max_dimm_count>0 and l_reg_max_dimm_count<l_max_number_dimms_per_reg
+ if (
+ (l_reg_max_dimm_count > 0)
+ && (l_reg_max_dimm_count < l_max_number_dimms_per_reg)
+ )
+ {
+ l_dimm_reg_power_limit_per_dimm_adj =
+ l_dimm_reg_power_limit_per_dimm
+ * l_max_number_dimms_per_reg
+ / l_reg_max_dimm_count;
+ FAPI_INF("VMEM Regulator Power/DIMM Limit Adjustment from %d to %d cW (DIMMs under regulator %d/%d)",
+ l_dimm_reg_power_limit_per_dimm, l_dimm_reg_power_limit_per_dimm_adj, l_reg_max_dimm_count, l_max_number_dimms_per_reg);
+ }
+ }
+
+ // Use the smaller of the thermal limit and regulator power limit per dimm
+ if (l_dimm_reg_power_limit_per_dimm_adj < l_dimm_thermal_power_limit)
+ {
+ l_dimm_thermal_power_limit = l_dimm_reg_power_limit_per_dimm_adj;
+ }
+
+ // Adjust the thermal/power limit to represent the power for all dimms under an MBA
+ if (l_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ l_channel_pair_thermal_power_limit =
+ l_dimm_thermal_power_limit / l_num_mba_with_dimms;
+ }
+ // ISDIMMs thermal power limit from MRW is per DIMM, so multiply by number of dimms on channel to get channel power and multiply by 2 to get channel pair power
+ else
+ {
+ // ISDIMMs
+ l_channel_pair_thermal_power_limit =
+ l_dimm_thermal_power_limit * l_num_dimms_on_port * 2;
+ }
+
+ // Update the channel pair power limit attribute
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_MEM_WATT_TARGET,
+ i_target_mba, l_channel_pair_thermal_power_limit));
+
+
+
+
+
+ // Initialize the runtime throttle attributes to an unthrottled value for mss_bulk_pwr_throttles
+ // max utilization comes from MRW value in c% - convert to %
+ MAX_UTIL = (float) l_max_dram_databus_util / 100;
+ l_runtime_throttle_n_per_mba = (int)(l_runtime_throttle_d * (MAX_UTIL / 100) / 4);
+ l_runtime_throttle_n_per_chip = (int)(l_runtime_throttle_d * (MAX_UTIL / 100) / 4) *
+ l_num_mba_with_dimms;
+
+ // for better custom dimm performance for DDR4, set the per mba throttle to the per chip throttle
+ // Not planning on doing this for DDR3
+ if ( (l_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ && (l_custom_dimm == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES) )
+ {
+ l_runtime_throttle_n_per_mba = l_runtime_throttle_n_per_chip;
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_MBA,
+ i_target_mba, l_runtime_throttle_n_per_mba));
+
+
+
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_CHIP,
+ i_target_mba, l_runtime_throttle_n_per_chip));
+
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR,
+ i_target_mba, l_runtime_throttle_d));
+
+ FAPI_INF("Min Power/Thermal Limit per MBA %d cW. Unthrottled values [%d/%d/%d].", l_channel_pair_thermal_power_limit,
+ l_runtime_throttle_n_per_mba, l_runtime_throttle_n_per_chip, l_runtime_throttle_d);
+
+
+ // For DDR4, use the VMEM power to determine the runtime throttle settings that are based
+ // on a VMEM power limit (not a VMEM+VPP power limit which is to be used at runtime for tmgt)
+ // Need to temporarily override attributes for mss_bulk_pwr_throttles to use
+ // Needed to determines runtime memory throttle settings based on any VMEM power limits
+ if (l_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ {
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_SLOPE,
+ i_target_mba, l_power_slope_array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_INT, i_target_mba, l_power_int_array));
+ }
+
+ // Call the procedure function that takes a channel pair power limit and
+ // converts it to throttle values
+ FAPI_EXEC_HWP(rc, p9c_mss_bulk_pwr_throttles, i_target_mba);
+
+ // Reset the total power curve attributes back to the original values
+ if (l_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ {
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_SLOPE,
+ i_target_mba, l_total_power_slope_array));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_TOTAL_POWER_INT, i_target_mba, l_total_power_int_array));
+ }
+
+ // Read back in the updated throttle attribute values (these are now set to
+ // values that will give dimm/channel power underneath the thermal power limit)
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA,
+ i_target_mba, l_runtime_throttle_n_per_mba));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP,
+ i_target_mba, l_runtime_throttle_n_per_chip));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_MEM_THROTTLE_DENOMINATOR,
+ i_target_mba, l_runtime_throttle_d));
+
+ // Setup the RAS and CAS increments used in the throttling register
+ l_ras_increment = 0;
+ l_cas_increment = 1;
+
+ // update output attributes
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_MBA,
+ i_target_mba, l_runtime_throttle_n_per_mba));
+
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_CHIP,
+ i_target_mba, l_runtime_throttle_n_per_chip));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR,
+ i_target_mba, l_runtime_throttle_d));
+
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_THROTTLE_CONTROL_RAS_WEIGHT,
+ i_target_mba, l_ras_increment));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_THROTTLE_CONTROL_CAS_WEIGHT,
+ i_target_mba, l_cas_increment));
+
+ FAPI_INF("*** mss_eff_config_thermal_throttles COMPLETE on %s ***",
+ mss::c_str(i_target_mba));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+} //end extern C
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.H
new file mode 100644
index 000000000..9503e8474
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.H
@@ -0,0 +1,70 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// @file p9c_mss_eff_config_thermal.H
+/// @brief Header file for mss_eff_config_thermal
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Mike Pardeik <pardeik@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+#ifndef MSS_EFF_CONFIG_THERMAL_H_
+#define MSS_EFF_CONFIG_THERMAL_H_
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include <fapi2.H>
+
+typedef fapi2::ReturnCode (*p9c_mss_eff_config_thermal_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MBA>&);
+
+
+extern "C" {
+ ///
+ /// @brief mss_eff_config_thermal procedure. Sets up dimm power curve attributes and dimm and channel throttle attributes
+ /// @param[in] i_target_mba Reference to centaur mba target
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode p9c_mss_eff_config_thermal(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ /// @brief mss_eff_config_thermal_powercurve(): This function determines the
+ /// power curve attribute values to use
+ /// @param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> & i_target_mba: MBA Target<fapi2::TARGET_TYPE_MBA> passed in
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_thermal_powercurve(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ /// @brief mss_eff_config_thermal_throttles(): This function determines the throttle attribute values to use
+ /// @l_param[in] const fapi2::Target<fapi2::TARGET_TYPE_MBA> & i_target_mba: MBA Target<fapi2::TARGET_TYPE_MBA> passed in
+ /// @return fapi2::ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_config_thermal_throttles(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+} //extern C
+
+#endif // MSS_EFF_CONFIG_THERMAL_H_
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.mk
new file mode 100755
index 000000000..ddc74a2b9
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.mk
@@ -0,0 +1,30 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_config_thermal.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+
+PROCEDURE=p9c_mss_eff_config_thermal
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.C
new file mode 100644
index 000000000..bd25f80bc
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.C
@@ -0,0 +1,481 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// @file p9c_mss_eff_mb_interleave.C
+/// @brief checks the plugging rules for a centaur and works with interleaving within the centaur
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+#include <p9c_mss_eff_mb_interleave.H>
+#include <dimmConsts.H>
+#include <fapi2.H>
+
+extern "C" {
+
+ enum DECONFIG_TYPES { DECONFIG_PORT_1_SLOT_0_IS_EMPTY_PORT_0_SLOT_0_IS_NOT = 0,
+ DECONFIG_PORT_1_SLOT_0_IS_NOT_EQUAL_TO_PORT_0_SLOT_0_A = 1,
+ DECONFIG_PORT_1_SLOT_0_IS_NOT_EQUAL_TO_PORT_0_SLOT_0_B = 2,
+ DECONFIG_PORT_0_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_0_WAS_DECONFIGURED = 3,
+ DECONFIG_PORT_1_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_0_WAS_DECONFIGURED = 4,
+ DECONFIG_PORT_0_SLOT_1_DECONFIGURED_BECAUSE_PORT_1_SLOT_1_IS_NOT_EQUAL = 5,
+ DECONFIG_PORT_1_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_1_IS_NOT_EQAUL = 6,
+ DECONFIG_PORT_0_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_0_IS_NOT_EQUAL = 7,
+ DECONFIG_PORT_1_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_0_IS_NOT_EQUAL = 8,
+ DECONFIG_PORT_0_SLOT_1_DECONFIGURED_BECAUSE_PORT_1_SLOT_1_IS_NOT_VALID = 9,
+ DECONFIG_PORT_1_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_1_IS_NOT_VALID = 10,
+ DECONFIG_PORT_1_HAS_SOMETHING_BUT_PORT_0_SLOT_0_IS_EMPTY = 11,
+ DECONFIG_PORT_0_SLOT_1_HAS_SOMETHING_BUT_PORT_0_SLOT_0_IS_EMPTY = 12,
+ DECONFIG_SLOT_1_HAS_SOMETHING_BUT_PORT_0_SLOT_0_IS_EMPTY = 13,
+ DECONFIG_INTERLEAVE_MODE_CONTROL_IS_REQUIRED = 99
+ };
+
+
+ constexpr uint8_t MSS_MBA_ADDR_INTERLEAVE_BIT = 24; // From Eric Retter:
+ // the prefetch and cleaner assume that bit 24 is the interleave bit.
+ // We put other interleave options in for other settings that could be
+ // tried in performance testing
+
+ class mss_eff_mb_dimm
+ {
+ public:
+ uint8_t module_type;
+ uint8_t dram_gen;
+ uint8_t device_density;
+ uint8_t num_of_ranks;
+ uint8_t device_width;
+ uint8_t module_width;
+ uint8_t thermal_sensor;
+ uint8_t size;
+ fapi2::Target<fapi2::TARGET_TYPE_DIMM> mydimm_target;
+ bool valid;
+ uint8_t side;
+ uint8_t port;
+ uint8_t slot;
+
+ mss_eff_mb_dimm();
+ fapi2::ReturnCode load(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimms, uint32_t size);
+ bool is_valid();
+ fapi2::ReturnCode deconfig(uint8_t i_case);
+ bool operator!=(const mss_eff_mb_dimm&) const;
+ };
+
+ ///
+ /// @brief checks the plugging rules for a centaur and works with interleaving within the centaur
+ /// @param[in] i_cen_target
+ /// @return fapi2::returnCode
+ ///
+ fapi2::ReturnCode p9c_mss_eff_mb_interleave(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_cen_target)
+ {
+
+ mss_eff_mb_dimm l_dimm_array[MAX_MBA_PER_CEN][MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {}; // side, port, dimm
+ std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>> l_target_dimm_array[MAX_MBA_PER_CEN];
+ uint8_t l_mba = 0;
+ uint8_t l_cur_mba_port = 0;
+ uint8_t l_cur_mba_dimm = 0;
+ uint8_t l_side, l_port, l_slot = 0;
+ uint8_t l_hadadeconfig[MAX_MBA_PER_CEN] = {0};
+ uint8_t l_mss_derived_mba_cacheline_interleave_mode = 0;
+ uint8_t l_mss_mba_addr_interleave_bit = 0;
+ uint8_t l_mrw_mba_cacheline_interleave_mode_control = 0;
+ uint32_t l_size[MAX_MBA_PER_CEN] = {0};
+ uint8_t l_eff_dimm_size[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_attr_mrw_strict_mba_plug_rule_checking = 0;
+ uint8_t l_deconfig_0_0 = 0;
+
+
+ do
+ {
+ // first step, load up the dimms connected to this centaur
+ for(l_side = 0; l_side < MAX_MBA_PER_CEN; l_side++)
+ {
+ for(l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ for(l_slot = 0; l_slot < MAX_DIMM_PER_PORT; l_slot++)
+ {
+ l_dimm_array[l_side][l_port][l_slot].side = l_side;
+ l_dimm_array[l_side][l_port][l_slot].port = l_port;
+ l_dimm_array[l_side][l_port][l_slot].slot = l_slot;
+ }
+ }
+ }
+
+ const auto l_mba_chiplets = i_cen_target.getChildren<fapi2::TARGET_TYPE_MBA>();
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_STRICT_MBA_PLUG_RULE_CHECKING, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_attr_mrw_strict_mba_plug_rule_checking));
+
+ if(l_attr_mrw_strict_mba_plug_rule_checking == fapi2::ENUM_ATTR_CEN_MRW_STRICT_MBA_PLUG_RULE_CHECKING_TRUE)
+ {
+ for(const auto& mba_i : l_mba_chiplets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, mba_i, l_mba));
+ l_target_dimm_array[l_mba] = mba_i.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_target_dimm_array[l_mba])
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_PORT, l_dimm, l_cur_mba_port));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_DIMM, l_dimm, l_cur_mba_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DIMM_SIZE, mba_i, l_eff_dimm_size));
+
+ FAPI_INF("Loading up information about dimm for mba %d port %d dimm %d", l_mba, l_cur_mba_port, l_cur_mba_dimm);
+ FAPI_INF("DIMM size is eff_dimm_size[%d][%d] = %d", l_cur_mba_port, l_cur_mba_dimm,
+ l_eff_dimm_size[l_cur_mba_port][l_cur_mba_dimm]);
+
+ FAPI_TRY(l_dimm_array[l_mba][l_cur_mba_port][l_cur_mba_dimm].load(l_dimm,
+ l_eff_dimm_size[l_cur_mba_port][l_cur_mba_dimm]));
+ } // Each DIMM off this MBA
+ } // Each MBA
+
+ // - Logical DIMMs are considered to be identical if they have the following attributes in common: Module Type (RDIMM or LRDIMM),
+ // Architecture (DDR3 vs DDR4), Device Density, Number of Ranks, Device Width, Module Width, and Thermal Sensor.
+
+ // Plug Rule 4.1 - Logical DIMMs have to be plugged in pairs on either Port A & B or on Port C & D. Paired DIMMs must be identical.
+ // Plug Rule 4.2 - If there is a Logical DIMM plugged in Slot 1 then an identical DIMM must be plugged in Slot0
+
+ // Plug rules 4.1 and 4.2 define valid configurations which are:
+ // - DIMM type X populated in slot0 only, slot1 is not populated
+ // - DIMM type X populated in slot0 and slot1
+ for(l_side = 0; l_side < MAX_MBA_PER_CEN; l_side++)
+ {
+ l_hadadeconfig[l_side] = 0;
+
+ if(l_dimm_array[l_side][0][0].is_valid()) // there is a dimm on port 0, slot 0, this is a must
+ {
+ l_deconfig_0_0 = 0;
+
+ // case 0, you don't have a pair of dimms on port 0 and port 1, kill port0,0
+ if(! l_dimm_array[l_side][1][0].is_valid())
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.1 violated, Port 1 on Side %d slot 0 is empty Port 0 slot 0 is not", l_side);
+ FAPI_TRY(l_dimm_array[l_side][0][0].deconfig(DECONFIG_PORT_1_SLOT_0_IS_EMPTY_PORT_0_SLOT_0_IS_NOT));
+ l_hadadeconfig[l_side] = 1;
+ l_deconfig_0_0 = 1;
+ }
+
+ // case 1, you did not kill dimm 0,0, so now check that 0,0 == 1,0
+ if( l_deconfig_0_0 == 0 &&
+ ( l_dimm_array[l_side][0][0] != l_dimm_array[l_side][1][0]))
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.1 violated, Port 1 on Side %d slot 0 is not equal to Port 0 slot 0", l_side);
+ FAPI_TRY(l_dimm_array[l_side][0][0].deconfig(DECONFIG_PORT_1_SLOT_0_IS_NOT_EQUAL_TO_PORT_0_SLOT_0_A));
+ FAPI_TRY(l_dimm_array[l_side][1][0].deconfig(DECONFIG_PORT_1_SLOT_0_IS_NOT_EQUAL_TO_PORT_0_SLOT_0_B));
+ l_hadadeconfig[l_side] = 1;
+ l_deconfig_0_0 = 1;
+ }
+
+ // if dimm 0,0 is gone, then blow away any dimm 0,1 and 1,1
+ if(l_deconfig_0_0 )
+ {
+ if(l_dimm_array[l_side][0][1].is_valid())
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.1 violated, Port 0 on Side %d slot 1 deconfigured because Port 0 slot 0 was deconfigured",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][0][1].deconfig(
+ DECONFIG_PORT_0_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_0_WAS_DECONFIGURED));
+ l_hadadeconfig[l_side] = 1;
+ }
+
+ if(l_dimm_array[l_side][1][1].is_valid())
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.1 violated, Port 1 on Side %d slot 1 deconfigured because Port 0 slot 0 was deconfigured",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][1][1].deconfig(
+ DECONFIG_PORT_1_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_0_WAS_DECONFIGURED));
+ l_hadadeconfig[l_side] = 1;
+ }
+ }
+ else // you have 0,0, so check if there is a 0,1 and 1,1 and they are equal
+ {
+ // and 0,1 must equal 1,1, otherwise, get rid of 0,1 and 1,1
+ if(l_dimm_array[l_side][0][1].is_valid() && l_dimm_array[l_side][1][1].is_valid())
+ {
+ if(l_dimm_array[l_side][0][1] != l_dimm_array[l_side][1][1])
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.1 violated, Port 0 on Side %d slot 1 deconfigured because Port 1 slot 1 is not equal",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][0][1].deconfig(DECONFIG_PORT_0_SLOT_1_DECONFIGURED_BECAUSE_PORT_1_SLOT_1_IS_NOT_EQUAL));
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.1 violated, Port 1 on Side %d slot 1 deconfigured because Port 0 slot 1 is not eqaul",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][1][1].deconfig(DECONFIG_PORT_1_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_1_IS_NOT_EQAUL));
+ l_hadadeconfig[l_side] = 1;
+ }
+ else
+ {
+ if(l_dimm_array[l_side][0][0] != l_dimm_array[l_side][0][1])
+ {
+ FAPI_ERR("Deconfig Rule 4.2 :Plug Rule 4.2 violated, Port 0 on Side %d slot 1 deconfigured because Port 0 slot 0 is not equal",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][0][1].deconfig(DECONFIG_PORT_0_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_0_IS_NOT_EQUAL));
+ FAPI_ERR("Deconfig Rule 4.2 :Plug Rule 4.1 violated, Port 1 on Side %d slot 1 deconfigured because Port 0 slot 0 is not equal",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][1][1].deconfig(DECONFIG_PORT_1_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_0_IS_NOT_EQUAL));
+ l_hadadeconfig[l_side] = 1;
+ }
+ }
+ }
+ else
+ {
+ if(l_dimm_array[l_side][0][1].is_valid())
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.1 violated, Port 0 on Side %d slot 1 deconfigured because Port 1 slot 1 is not valid",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][0][1].deconfig(DECONFIG_PORT_0_SLOT_1_DECONFIGURED_BECAUSE_PORT_1_SLOT_1_IS_NOT_VALID));
+ }
+
+ if(l_dimm_array[l_side][1][1].is_valid())
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.1 violated, Port 1 on Side %d slot 1 deconfigured because Port 0 slot 1 is not valid",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][1][1].deconfig(DECONFIG_PORT_1_SLOT_1_DECONFIGURED_BECAUSE_PORT_0_SLOT_1_IS_NOT_VALID));
+ l_hadadeconfig[l_side] = 1;
+ }
+
+ }
+ }
+ }
+ else // if there is no slot 0,0, then everything else is invalid
+ {
+ if(l_dimm_array[l_side][1][0].is_valid())
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.1 violated, Port 1 on Side %d has something but Port 0 slot 0 is empty",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][1][0].deconfig(DECONFIG_PORT_1_HAS_SOMETHING_BUT_PORT_0_SLOT_0_IS_EMPTY));
+ l_hadadeconfig[l_side] = 1;
+ }
+
+ if(l_dimm_array[l_side][0][1].is_valid()) // there is a dimm slot 1, but slot 0 is empty
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.2 violated, Port 0 on Side %d slot 1 has something but Port 0 slot 0 is empty",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][0][1].deconfig(DECONFIG_PORT_0_SLOT_1_HAS_SOMETHING_BUT_PORT_0_SLOT_0_IS_EMPTY));
+ l_hadadeconfig[l_side] = 1;
+ }
+
+ if(l_dimm_array[l_side][1][1].is_valid()) // there is a dimm slot 1, but slot 0 is empty
+ {
+ FAPI_ERR("Deconfig Rule 4.1 :Plug Rule 4.2 violated, Port 0 on Side %d slot 1 has something but Port 0 slot 0 is empty",
+ l_side);
+ FAPI_TRY(l_dimm_array[l_side][1][1].deconfig(DECONFIG_SLOT_1_HAS_SOMETHING_BUT_PORT_0_SLOT_0_IS_EMPTY));
+ l_hadadeconfig[l_side] = 1;
+ }
+ }
+
+ if(l_hadadeconfig[l_side])
+ {
+ FAPI_INF("There was a Deconfig on l_side %d due to a plug rule 4.1 and/or 4.2", l_side);
+ }
+ else
+ {
+ FAPI_INF("No Deconfig on l_side %d so far", l_side);
+ }
+ }
+
+ // Deconfig Rule 4.1 - When Plug rules 4.1 or 4.2 are violated all Logical DIMMs behind the MBA in violation are deconfiged.
+ // This error will be redetected on the next IPL no Persistent guard required. This rule is enforced by mss_eff_cnfg HW procedure.
+
+ // Deconfig by Association Rule 4.1 - If a logical DIMM is deconfigured; all logical DIMMs on the same MBA must also be deconfigured by association.
+ // Since MBAs with no configured DIMMs are also deconfigured this will lead to the MBA also being deconfigured.
+ // This error will be redetected on the next IPL no Persistent guard required.
+ // Deconfig by Association Rule 4.2 MBAs with no configured DIMMs are deconfigured this will lead to the MBA also being deconfigured.
+ // This error will be redetected on the next IPL no Persistent guard required.
+
+ // Note - In an IS DIMM system that is running in interleave mode: due to the interactions between Plug rules 4.1, 4.2 and 3.3 the IS DIMM will need to be plugged in quads.
+ // This means an identical pair of a total size behind one half of a Centaur Pair and another identical pair of the same total size behind the other Centaur in the Pair.
+ // Note that the 2 pairs of DIMMs need not be identical to each other just have the same total size.
+ } // end of strict checking
+
+ for(l_side = 0; l_side < MAX_MBA_PER_CEN; l_side++)
+ {
+ for(l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ for(l_slot = 0; l_slot < MAX_DIMM_PER_PORT; l_slot++)
+ {
+ l_size[l_side] += l_dimm_array[l_side][l_port][l_slot].size;
+ }
+ }
+ }
+
+ FAPI_INF("Sizes on each l_side %d %d", l_size[0], l_size[1]);
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_MBA_CACHELINE_INTERLEAVE_MODE_CONTROL,
+ fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_mrw_mba_cacheline_interleave_mode_control));
+
+ switch(l_mrw_mba_cacheline_interleave_mode_control)
+ {
+ case fapi2::ENUM_ATTR_CEN_MRW_MBA_CACHELINE_INTERLEAVE_MODE_CONTROL_NEVER:
+ l_mss_derived_mba_cacheline_interleave_mode = fapi2::ENUM_ATTR_CEN_MSS_DERIVED_MBA_CACHELINE_INTERLEAVE_MODE_OFF;
+ l_mss_mba_addr_interleave_bit = 0;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_MRW_MBA_CACHELINE_INTERLEAVE_MODE_CONTROL_REQUIRED:
+ if(l_size[0] != l_size[1])
+ {
+ FAPI_ERR("ATTR_MRW_MBA_CACHELINE_INTERLEAVE_MODE_CONTROL is REQUIRED, but size on l_side 0 does not match size on l_side 1 sizes %d %d",
+ l_size[0], l_size[1]);
+ l_mss_derived_mba_cacheline_interleave_mode = fapi2::ENUM_ATTR_CEN_MSS_DERIVED_MBA_CACHELINE_INTERLEAVE_MODE_OFF;
+ l_mss_mba_addr_interleave_bit = 0;
+
+ for(l_side = 0; l_side < MAX_MBA_PER_CEN; l_side++)
+ {
+ for(l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ for(l_slot = 0; l_slot < MAX_DIMM_PER_PORT; l_slot++)
+ {
+ if(l_dimm_array[l_side][l_port][l_slot].is_valid())
+ {
+ FAPI_ERR("Deconfig INTERLEAVE_MODE_CONTROL is REQUIRED violated Port %d on Side %d l_slot %d", l_port, l_side, l_slot);
+ FAPI_TRY(l_dimm_array[l_side][l_port][l_slot].deconfig(DECONFIG_INTERLEAVE_MODE_CONTROL_IS_REQUIRED));
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ l_mss_derived_mba_cacheline_interleave_mode = fapi2::ENUM_ATTR_CEN_MSS_DERIVED_MBA_CACHELINE_INTERLEAVE_MODE_ON;
+ l_mss_mba_addr_interleave_bit = MSS_MBA_ADDR_INTERLEAVE_BIT;
+ }
+
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_MRW_MBA_CACHELINE_INTERLEAVE_MODE_CONTROL_REQUESTED:
+ if(l_size[0] != l_size[1])
+ {
+ l_mss_derived_mba_cacheline_interleave_mode = fapi2::ENUM_ATTR_CEN_MSS_DERIVED_MBA_CACHELINE_INTERLEAVE_MODE_OFF;
+ l_mss_mba_addr_interleave_bit = 0;
+ }
+ else
+ {
+ l_mss_derived_mba_cacheline_interleave_mode = fapi2::ENUM_ATTR_CEN_MSS_DERIVED_MBA_CACHELINE_INTERLEAVE_MODE_ON;
+ l_mss_mba_addr_interleave_bit = MSS_MBA_ADDR_INTERLEAVE_BIT;
+ }
+
+ break;
+
+ default:
+ FAPI_ERR("Internal Error: ATTR_MRW_MBA_CACHELINE_INTERLEAVE_MODE_CONTROL is not a known value");
+ l_mss_derived_mba_cacheline_interleave_mode = fapi2::ENUM_ATTR_CEN_MSS_DERIVED_MBA_CACHELINE_INTERLEAVE_MODE_OFF;
+ l_mss_mba_addr_interleave_bit = 0;
+ break;
+
+ } // end switch (cachline_interleave_mode_control)
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_DERIVED_MBA_CACHELINE_INTERLEAVE_MODE, i_cen_target,
+ l_mss_derived_mba_cacheline_interleave_mode));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_DERIVED_MBA_ADDR_INTERLEAVE_BIT, i_cen_target,
+ l_mss_mba_addr_interleave_bit));
+
+ }
+ while(0);
+
+ FAPI_INF("mb_interleave done");
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ // default constructor
+ mss_eff_mb_dimm::mss_eff_mb_dimm()
+ {
+ module_type = 0;
+ dram_gen = 0;
+ device_density = 0;
+ num_of_ranks = 0;
+ device_width = 0;
+ module_width = 0;
+ thermal_sensor = 0;
+ size = 0;
+ valid = 0;
+ }
+
+ fapi2::ReturnCode mss_eff_mb_dimm::load(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm, uint32_t i_size)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_TYPE, i_dimm, module_type));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_DEVICE_TYPE, i_dimm, dram_gen));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_SDRAM_DENSITY, i_dimm, device_density));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_NUM_RANKS, i_dimm, num_of_ranks));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_DRAM_WIDTH, i_dimm, device_width));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_MEMORY_BUS_WIDTH, i_dimm, module_width));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_THERMAL_SENSOR, i_dimm, thermal_sensor));
+ mydimm_target = i_dimm;
+
+ size = i_size;
+
+ if(i_size != 0)
+ {
+ valid = 1;
+ }
+ else
+ {
+ valid = 0;
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ bool mss_eff_mb_dimm::is_valid()
+ {
+ return valid;
+ }
+
+ fapi2::ReturnCode mss_eff_mb_dimm::deconfig(uint8_t i_case)
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_EFF_MB_INTERLEAVE_PLUG_DECONFIG_DIMM().
+ set_DIMM(mydimm_target).
+ set_CASE(i_case),
+ "Deconfiguring a dimm due to a plugging rule violation at centuar/mba level case num %d (%d%d%d)", i_case, side, port,
+ slot);
+
+ valid = 0;
+ size = 0;
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ bool mss_eff_mb_dimm::operator!=(const mss_eff_mb_dimm& a) const
+ {
+ if( module_type == a.module_type &&
+ dram_gen == a.dram_gen &&
+ device_density == a.device_density &&
+ num_of_ranks == a.num_of_ranks &&
+ device_width == a.device_width &&
+ module_width == a.module_width &&
+ thermal_sensor == a.thermal_sensor &&
+ size == a.size )
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.H
new file mode 100644
index 000000000..d6514ba4c
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.H
@@ -0,0 +1,62 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/// @file p9c_mss_eff_mb_interleave.C
+/// @brief checks the plugging rules for a centaur and works with interleaving within the centaur
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+
+
+#ifndef __MSS_EFF_MB_INTERLEAVE_H
+#define __MSS_EFF_MB_INTERLEAVE_H
+
+#include <fapi2.H>
+
+typedef fapi2::ReturnCode (*p9c_mss_eff_mb_interleave_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>&
+ centaur );
+
+extern "C"
+{
+
+ // This hardware procedure checks the plugging rules for a centaur and works with interleaving within the centaur
+ // if various plug rules are violated at this level of the memory stack, error logs and deconfigures will happen
+ // Many deconfig by assoication rules are not checked here. Just 4.1 and 4.2 plus a required Interleaving check
+ ///
+ /// @brief checks the plugging rules for a centaur and works with interleaving within the centaur
+ /// @param[in] i_cen_target
+ /// @return fapi2::returnCode
+ ///
+ fapi2::ReturnCode p9c_mss_eff_mb_interleave(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_cen_target);
+
+
+
+} // extern "C"
+
+#endif
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.mk
new file mode 100755
index 000000000..cd5f62da8
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.mk
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_mb_interleave.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+
+PROCEDURE=p9c_mss_eff_mb_interleave
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.C
new file mode 100644
index 000000000..d2bf69afe
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.C
@@ -0,0 +1,125 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// @file p9c_mss_eff_pre_config.C
+/// @brief This procedure puts in required attributes for mss_eff_config_thermal which are based on "worst case" config in case these attributes were not able to be setup by mss_eff_config
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include <fapi2.H>
+#include <dimmConsts.H>
+#include <generic/memory/lib/utils/c_str.H>
+
+extern "C" {
+ ///
+ /// @brief This procedure puts in required attributes for mss_eff_config_thermal which are based on "worst case" config in case these attributes were not able to be setup by mss_eff_config
+ /// @param[in] i_target_mba
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_pre_config(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+ {
+ constexpr uint32_t MSS_EFF_VALID = 255;
+
+ // Grab DIMM/SPD data.
+ uint8_t l_cur_dimm_spd_valid_u8array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_spd_custom[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+
+ uint8_t l_cur_mba_port = 0;
+ uint8_t l_cur_mba_dimm = 0;
+ uint32_t l_eff_cen_rcv_imp_dq_dqs_schmoo[MAX_PORTS_PER_MBA] = {0};
+ uint32_t l_eff_cen_drv_imp_dq_dqs_schmoo[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_eff_num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_eff_num_master_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_eff_dimm_ranks_configed[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_eff_dram_gen = fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR3;
+ uint8_t l_eff_dimm_type = fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM;
+ uint8_t l_eff_custom_dimm = fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES;
+ uint8_t l_eff_dram_width = fapi2::ENUM_ATTR_CEN_EFF_DRAM_WIDTH_X4;
+ uint8_t l_eff_dram_tdqs = fapi2::ENUM_ATTR_CEN_EFF_DRAM_TDQS_DISABLE;
+ uint8_t l_eff_num_drops_per_port = fapi2::ENUM_ATTR_CEN_EFF_NUM_DROPS_PER_PORT_SINGLE;
+ const auto l_target_dimm_array = i_target_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_target_dimm_array)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_PORT, l_dimm, l_cur_mba_port));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_DIMM, l_dimm, l_cur_mba_dimm));
+ l_cur_dimm_spd_valid_u8array[l_cur_mba_port][l_cur_mba_dimm] = MSS_EFF_VALID;
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_CUSTOM, l_dimm,
+ l_spd_custom[l_cur_mba_port][l_cur_mba_dimm]));
+ }
+
+ if (l_cur_dimm_spd_valid_u8array[0][0] == MSS_EFF_VALID)
+ {
+ if (l_spd_custom[0][0] == fapi2::ENUM_ATTR_CEN_SPD_CUSTOM_YES)
+ {
+ l_eff_custom_dimm = fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES;
+ }
+ else
+ {
+ l_eff_custom_dimm = fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_NO;
+ }
+ }
+ else
+ {
+ FAPI_INF("WARNING: Plug rule violation at %s!", mss::c_str(i_target_mba));
+ FAPI_INF("WARNING: Do NOT trust ATTR_EFF_CUSTOM_DIMM for %s!", mss::c_str(i_target_mba));
+ }
+
+ for (uint8_t l_cur_port = 0; l_cur_port < MAX_PORTS_PER_MBA; l_cur_port += 1)
+ {
+ l_eff_cen_rcv_imp_dq_dqs_schmoo[l_cur_port] = 0;
+ l_eff_cen_drv_imp_dq_dqs_schmoo[l_cur_port] = 0;
+
+ for (uint8_t l_cur_dimm = 0; l_cur_dimm < MAX_DIMM_PER_PORT; l_cur_dimm += 1)
+ {
+ l_eff_num_ranks_per_dimm[l_cur_port][l_cur_dimm] = 8;
+ l_eff_num_master_ranks_per_dimm[l_cur_port][l_cur_dimm] = 8;
+ l_eff_dimm_ranks_configed[l_cur_port][l_cur_dimm] = MSS_EFF_VALID;
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_RCV_IMP_DQ_DQS_SCHMOO, i_target_mba, l_eff_cen_rcv_imp_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_SCHMOO, i_target_mba, l_eff_cen_drv_imp_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba, l_eff_dram_gen));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_TYPE, i_target_mba, l_eff_dimm_type));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target_mba, l_eff_custom_dimm));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target_mba, l_eff_dram_width));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_TDQS, i_target_mba, l_eff_dram_tdqs));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba, l_eff_num_ranks_per_dimm));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target_mba, l_eff_num_master_ranks_per_dimm));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DIMM_RANKS_CONFIGED, i_target_mba, l_eff_dimm_ranks_configed));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_NUM_DROPS_PER_PORT, i_target_mba, l_eff_num_drops_per_port));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+
+
+} // extern "C"
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.H
new file mode 100755
index 000000000..35a96fe9b
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.H
@@ -0,0 +1,56 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/// @file p9c_mss_eff_pre_config.C
+/// @brief This procedure puts in required attributes for mss_eff_config_thermal which are based on "worst case" config in case these attributes were not able to be setup by mss_eff_config
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+#ifndef MSS_EFF_PRE_CONFIG_H_
+#define MSS_EFF_PRE_CONFIG_H_
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include <fapi2.H>
+
+
+typedef fapi2::ReturnCode (*mss_eff_pre_config_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+extern "C" {
+
+ ///
+ /// @brief This procedure puts in required attributes for mss_eff_config_thermal which are based on "worst case" config in case these attributes were not able to be setup by mss_eff_config
+ /// @param[in] i_target_mba
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_eff_pre_config(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+} // extern "C"
+
+#endif // MSS_EFF_PRE_CONFIG_H_
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.mk
new file mode 100755
index 000000000..746026a42
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.mk
@@ -0,0 +1,30 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_eff_pre_config.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+
+PROCEDURE=p9c_mss_eff_pre_config
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.C
new file mode 100644
index 000000000..93c21029b
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.C
@@ -0,0 +1,747 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/// @file p9c_mss_freq.C
+/// @brief DIMM SPD attributes are read to determine optimal DRAM frequency
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamaring@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+///
+
+//----------------------------------------------------------------------
+// Includes - FAPI
+//----------------------------------------------------------------------
+#include <fapi2.H>
+#include <p9c_mss_freq.H>
+#include <dimmConsts.H>
+#include <generic/memory/lib/utils/c_str.H>
+//----------------------------------------------------------------------
+// ENUMs
+//----------------------------------------------------------------------
+enum
+{
+ MSS_FREQ_EMPTY = 0,
+ MSS_FREQ_SINGLE_DROP = 1,
+ MSS_FREQ_DUAL_DROP = 2,
+ MSS_FREQ_VALID = 255,
+};
+
+//----------------------------------------------------------------------
+// Constants
+//----------------------------------------------------------------------
+constexpr uint8_t DDR4_MTB_DIVIDEND = 1;
+constexpr uint8_t DDR4_MTB_DIVISOR = 8;
+constexpr uint8_t DDR4_FTB_DIVIDEND = 1;
+constexpr uint8_t DDR4_FTB_DIVISOR = 1;
+constexpr uint8_t NUM_CL_SUPPORTED = 21;
+
+
+///
+/// @brief DIMM SPD attributes are read to determine optimal DRAM frequency
+/// @param[in] i_target_memb Centaur target
+/// @return FAPI2_RC_SUCCESS iff frequency + CL found successfully
+///
+fapi2::ReturnCode p9c_mss_freq(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target_memb)
+{
+ uint8_t l_spd_mtb_dividend = 0;
+ uint8_t l_spd_mtb_divisor = 0;
+ uint8_t l_spd_ftb_dividend = 0;
+ uint8_t l_spd_ftb_divisor = 0;
+ uint32_t l_dimm_freq_calc = 0;
+ uint32_t l_dimm_freq_min = 9999;
+ uint8_t l_spd_min_tck_MTB = 0;
+ uint8_t l_spd_tck_offset_FTB = 0;
+ uint8_t l_spd_tck_offset = 0;
+ uint32_t l_spd_min_tck = 0;
+ uint32_t l_spd_min_tck_max = 0;
+ uint8_t l_spd_min_taa_MTB = 0;
+ uint8_t l_spd_taa_offset_FTB = 0;
+ uint8_t l_spd_taa_offset = 0;
+ uint32_t l_spd_min_taa = 0;
+ uint32_t l_spd_min_taa_max = 0;
+ uint32_t l_selected_dimm_freq = 0;
+ uint32_t l_spd_cas_lat_supported = 0xFFFFFFFF;
+ uint32_t l_spd_cas_lat_supported_all = 0xFFFFFFFF;
+ uint8_t l_cas_latency = 0;
+ uint32_t l_cl_mult_tck = 0;
+ uint8_t l_cur_mba_port = 0;
+ uint8_t l_cur_mba_dimm = 0;
+ uint8_t l_cur_mba = 0;
+ uint8_t l_cur_dimm_spd_valid_u8array[MAX_MBA_PER_CEN][MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {{{0}}};
+ uint8_t l_plug_config = 0;
+ uint8_t l_module_type = 0;
+ uint8_t l_module_type_deconfig = 0;
+ uint8_t l_module_type_group_1 = 0;
+ uint8_t l_module_type_group_2 = 0;
+ uint8_t l_module_type_group_1_total = 0;
+ uint8_t l_module_type_group_2_total = 0;
+ uint8_t l_num_ranks[MAX_MBA_PER_CEN][MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {{{0}}};
+ uint8_t l_num_ranks_total = 0;
+ uint32_t l_freq_override = 0;
+ uint8_t l_override_path = 0;
+ uint8_t l_nest_capable_frequencies = 0;
+ uint8_t l_spd_dram_dev_type;
+ uint8_t l_spd_tb_mtb_ddr4 = 0;
+ uint8_t l_spd_tb_ftb_ddr4 = 0;
+ uint8_t l_spd_tckmax_ddr4 = 0;
+ uint8_t l_cl_count_array[NUM_CL_SUPPORTED];
+ uint8_t l_highest_common_cl = 0;
+ uint8_t l_highest_cl_count = 0;
+ uint8_t l_lowest_common_cl = 0;
+ uint32_t l_lowest_cl_count = 0xFFFFFFFF;
+
+ for(uint8_t i = 0; i < NUM_CL_SUPPORTED; i++)
+ {
+ l_cl_count_array[i] = 0; // Initializing each element separately
+ }
+
+ // Get associated MBA's on this centaur
+ const auto l_mbaChiplets = i_target_memb.getChildren<fapi2::TARGET_TYPE_MBA>();
+
+ // Loop through the 2 MBA's
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_DRAM_DEVICE_TYPE, l_dimm, l_spd_dram_dev_type));
+
+ if (l_spd_dram_dev_type == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ // DDR4 ONLY
+ FAPI_DBG("DDR4 detected");
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TIMEBASE_MTB_DDR4, l_dimm, l_spd_tb_mtb_ddr4));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TIMEBASE_FTB_DDR4, l_dimm, l_spd_tb_ftb_ddr4));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TCKMAX_DDR4, l_dimm, l_spd_tckmax_ddr4));
+
+ if ( (l_spd_tb_mtb_ddr4 == 0) && (l_spd_tb_ftb_ddr4 == 0))
+ {
+ // These are now considered constant within DDR4
+ // If DDR4 spec changes to include other values, these const's need to be updated
+ l_spd_mtb_dividend = DDR4_MTB_DIVIDEND;
+ l_spd_mtb_divisor = DDR4_MTB_DIVISOR;
+ l_spd_ftb_dividend = DDR4_FTB_DIVIDEND;
+ l_spd_ftb_divisor = DDR4_FTB_DIVISOR;
+ }
+ else
+ {
+ //Invalid due to the fact that JEDEC dictates that these should be zero.
+ // Log error and continue to next DIMM
+ FAPI_ASSERT_NOEXIT(false,
+ fapi2::CEN_MSS_UNSUPPORTED_SPD_DATA_DDR4().
+ set_MTB_DDR4(l_spd_tb_mtb_ddr4).
+ set_FTB_DDR4(l_spd_tb_ftb_ddr4).
+ set_DIMM_TARGET( l_dimm),
+ "Invalid data received from SPD DDR4 MTB/FTB Timebase");
+ continue;
+ }
+ }
+
+ // common to both DDR3 & DDR4
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TCKMIN, l_dimm, l_spd_min_tck_MTB));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TAAMIN, l_dimm, l_spd_min_taa_MTB));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_CAS_LATENCIES_SUPPORTED, l_dimm, l_spd_cas_lat_supported));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_PORT, l_dimm, l_cur_mba_port));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_DIMM, l_dimm, l_cur_mba_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_mba, l_cur_mba));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_TYPE, l_dimm, l_module_type));
+
+ // from dimm_spd_attributes.xml, R1 = 0x00, R2 = 0x01, R3 = 0x02, R4 = 0x03
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_NUM_RANKS, l_dimm,
+ l_num_ranks[l_cur_mba][l_cur_mba_port][l_cur_mba_dimm]));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_FINE_OFFSET_TAAMIN, l_dimm, l_spd_taa_offset_FTB));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_FINE_OFFSET_TCKMIN, l_dimm, l_spd_tck_offset_FTB));
+
+ l_cur_dimm_spd_valid_u8array[l_cur_mba][l_cur_mba_port][l_cur_mba_dimm] = MSS_FREQ_VALID;
+
+ if ((l_spd_min_tck_MTB == 0) || (l_spd_min_taa_MTB == 0))
+ {
+ //Invalid due to the fact that JEDEC dictates that these should be non-zero.
+ // Log error and continue to next DIMM
+ FAPI_ASSERT_NOEXIT(false,
+ fapi2::CEN_MSS_UNSUPPORTED_SPD_DATA_COMMON().
+ set_MIN_TCK(l_spd_min_tck_MTB).
+ set_MIN_TAA(l_spd_min_taa_MTB).
+ set_DIMM_TARGET(l_dimm).
+ set_TARGET(i_target_memb),
+ "Invalid data received from SPD within TCK Min, or TAA Min");
+ continue;
+ }
+
+ // Calc done on PS units (the multiplication of 1000) to avoid rounding errors.
+ // Frequency listed with multiplication of 2 as clocking data on both +- edges
+ l_spd_min_tck = ( 1000 * l_spd_min_tck_MTB * l_spd_mtb_dividend ) / l_spd_mtb_divisor;
+ l_spd_min_taa = ( 1000 * l_spd_min_taa_MTB * l_spd_mtb_dividend ) / l_spd_mtb_divisor;
+
+ FAPI_INF("min tck = %i, taa = %i", l_spd_min_tck, l_spd_min_taa);
+ FAPI_INF("FTB tck 0x%x, taa 0x%x", l_spd_tck_offset_FTB, l_spd_taa_offset_FTB);
+
+ // Adjusting by tck offset -- tck offset represented in 2's compliment as it could be positive or negative adjustment
+ // No multiplication of 1000 as it is already in picoseconds.
+ if (l_spd_tck_offset_FTB & 0x80)
+ {
+ l_spd_tck_offset_FTB = ~( l_spd_tck_offset_FTB ) + 1;
+ l_spd_tck_offset = (l_spd_tck_offset_FTB * l_spd_ftb_dividend ) / l_spd_ftb_divisor;
+ l_spd_min_tck = l_spd_min_tck - l_spd_tck_offset;
+ FAPI_INF("FTB minus offset %i, min tck %i", l_spd_tck_offset, l_spd_min_tck);
+ }
+ else
+ {
+ l_spd_tck_offset = (l_spd_tck_offset_FTB * l_spd_ftb_dividend ) / l_spd_ftb_divisor;
+ l_spd_min_tck = l_spd_min_tck + l_spd_tck_offset;
+ FAPI_INF("FTB plus offset %i, min tck %i", l_spd_tck_offset, l_spd_min_tck);
+ }
+
+ // Adjusting by taa offset -- taa offset represented in 2's compliment as it could be positive or negative adjustment
+ if (l_spd_taa_offset_FTB & 0x80)
+ {
+ l_spd_taa_offset_FTB = ~( l_spd_taa_offset_FTB) + 1;
+ l_spd_taa_offset = (l_spd_taa_offset_FTB * l_spd_ftb_dividend ) / l_spd_ftb_divisor;
+ l_spd_min_taa = l_spd_min_taa - l_spd_taa_offset;
+ }
+ else
+ {
+ l_spd_taa_offset = (l_spd_taa_offset_FTB * l_spd_ftb_dividend ) / l_spd_ftb_divisor;
+ l_spd_min_taa = l_spd_min_taa + l_spd_taa_offset;
+ }
+
+ if ((l_spd_min_tck == 0) || (l_spd_min_taa == 0))
+ {
+ //Invalid due to the fact that JEDEC dictates that these should be non-zero.
+ // Log error and continue to next DIMM
+ FAPI_ASSERT_NOEXIT(false,
+ fapi2::CEN_MSS_UNSUPPORTED_SPD_DATA_COMMON().
+ set_MIN_TCK(l_spd_min_tck_MTB).
+ set_MIN_TAA(l_spd_min_taa_MTB).
+ set_DIMM_TARGET(l_dimm).
+ set_TARGET(i_target_memb),
+ "Invalid data received from SPD causing TCK Min or TAA Min to be 0");
+ continue;
+ }
+
+ l_dimm_freq_calc = 2000000 / l_spd_min_tck;
+
+ FAPI_INF( "TAA(ps): %d TCK(ps): %d Calc'ed Freq for this dimm: %d", l_spd_min_taa, l_spd_min_tck, l_dimm_freq_calc);
+
+ //is this the slowest dimm?
+ if (l_dimm_freq_calc < l_dimm_freq_min)
+ {
+ l_dimm_freq_min = l_dimm_freq_calc;
+ }
+
+ if (l_spd_min_tck > l_spd_min_tck_max)
+ {
+ l_spd_min_tck_max = l_spd_min_tck;
+ }
+
+ if (l_spd_min_taa > l_spd_min_taa_max)
+ {
+ l_spd_min_taa_max = l_spd_min_taa;
+ }
+
+ if ( l_spd_cas_lat_supported & 0x00000001 )
+ {
+ l_cl_count_array[0]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000002 )
+ {
+ l_cl_count_array[1]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000004 )
+ {
+ l_cl_count_array[2]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000008 )
+ {
+ l_cl_count_array[3]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000010 )
+ {
+ l_cl_count_array[4]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000020 )
+ {
+ l_cl_count_array[5]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000040 )
+ {
+ l_cl_count_array[6]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000080 )
+ {
+ l_cl_count_array[7]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000100 )
+ {
+ l_cl_count_array[8]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000200 )
+ {
+ l_cl_count_array[9]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000400)
+ {
+ l_cl_count_array[10]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00000800 )
+ {
+ l_cl_count_array[11]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00001000 )
+ {
+ l_cl_count_array[12]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00002000 )
+ {
+ l_cl_count_array[13]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00004000)
+ {
+ l_cl_count_array[14]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00008000 )
+ {
+ l_cl_count_array[15]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00010000 )
+ {
+ l_cl_count_array[16]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00020000 )
+ {
+ l_cl_count_array[17]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00040000)
+ {
+ l_cl_count_array[18]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00080000 )
+ {
+ l_cl_count_array[19]++;
+ }
+ else if ( l_spd_cas_lat_supported & 0x00100000 )
+ {
+ l_cl_count_array[20]++;
+ }
+
+ l_spd_cas_lat_supported_all = l_spd_cas_lat_supported_all & l_spd_cas_lat_supported;
+
+ if ( (l_module_type_group_1 == l_module_type) || (l_module_type_group_1 == 0) )
+ {
+ l_module_type_group_1 = l_module_type;
+ l_module_type_group_1_total++;
+ }
+ else if ( (l_module_type_group_2 == l_module_type) || (l_module_type_group_2 == 0) )
+ {
+ l_module_type_group_2 = l_module_type;
+ l_module_type_group_2_total++;
+ }
+
+ } // DIMM
+ } // MBA
+
+ // Check for DIMM Module Type Mixing
+ if (l_module_type_group_2 != 0)
+ {
+ if (l_module_type_group_1_total > l_module_type_group_2_total)
+ {
+ l_module_type_deconfig = l_module_type_group_1;
+ }
+ else
+ {
+ l_module_type_deconfig = l_module_type_group_2;
+ }
+
+ // Loop through the 2 MBA's
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_TYPE, l_dimm, l_module_type));
+
+ FAPI_ASSERT_NOEXIT(l_module_type != l_module_type_deconfig,
+ fapi2::CEN_MSS_MODULE_TYPE_MIX().
+ set_DIMM_TARGET(l_dimm).
+ set_MODULE_TYPE(l_module_type),
+ "Mixing of DIMM Module Types (%d, %d) deconfiguring minority type: %d", l_module_type_group_1, l_module_type_group_2,
+ l_module_type_deconfig);
+ } // DIMM
+ } // MBA
+ } // if
+
+ FAPI_INF( "Highest Supported Frequency amongst DIMMs: %d", l_dimm_freq_min);
+ FAPI_INF( "Minimum TAA(ps) amongst DIMMs: %d Minimum TCK(ps) amongst DIMMs: %d", l_spd_min_taa_max, l_spd_min_tck_max);
+
+ //Determining the cnfg for imposing any cnfg speed limitations
+ if (((l_cur_dimm_spd_valid_u8array[0][0][0] == MSS_FREQ_VALID)
+ && (l_cur_dimm_spd_valid_u8array[0][0][1] == MSS_FREQ_EMPTY))
+ || ((l_cur_dimm_spd_valid_u8array[0][0][1] == MSS_FREQ_VALID)
+ && (l_cur_dimm_spd_valid_u8array[0][0][0] == MSS_FREQ_EMPTY)))
+ {
+ l_plug_config = MSS_FREQ_SINGLE_DROP;
+ l_num_ranks_total = l_num_ranks[0][0][0] + 1;
+ }
+ else if (((l_cur_dimm_spd_valid_u8array[1][0][0] == MSS_FREQ_VALID)
+ && (l_cur_dimm_spd_valid_u8array[1][0][1] == MSS_FREQ_EMPTY))
+ || ((l_cur_dimm_spd_valid_u8array[1][0][1] == MSS_FREQ_VALID)
+ && (l_cur_dimm_spd_valid_u8array[1][0][0] == MSS_FREQ_EMPTY)))
+ {
+ l_plug_config = MSS_FREQ_SINGLE_DROP;
+ l_num_ranks_total = l_num_ranks[1][0][0] + 1;
+ }
+ else if ((l_cur_dimm_spd_valid_u8array[0][0][0] == MSS_FREQ_VALID)
+ && (l_cur_dimm_spd_valid_u8array[0][0][1] == MSS_FREQ_VALID))
+ {
+ l_plug_config = MSS_FREQ_DUAL_DROP;
+ l_num_ranks_total = (l_num_ranks[0][0][0] + 1) + (l_num_ranks[0][0][1] + 1);
+ }
+ else if ((l_cur_dimm_spd_valid_u8array[1][0][0] == MSS_FREQ_VALID)
+ && (l_cur_dimm_spd_valid_u8array[1][0][1] == MSS_FREQ_VALID))
+ {
+ l_plug_config = MSS_FREQ_DUAL_DROP;
+ l_num_ranks_total = (l_num_ranks[1][0][0] + 1) + (l_num_ranks[1][0][1] + 1);
+ }
+ else
+ {
+ l_plug_config = MSS_FREQ_EMPTY;
+ }
+
+ FAPI_INF( "PLUG CONFIG(from SPD): %d, Type of Dimm(from SPD): 0x%02X, Num Ranks(from SPD): %d", l_plug_config,
+ l_module_type, l_num_ranks_total);
+
+ // Impose configuration limitations
+ // Single Drop RDIMMs Cnfgs cannot run faster than 1333
+ // DDR4 min speed 1600 and Cen no longer supports 1866.
+ if (l_spd_dram_dev_type == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ l_dimm_freq_min = 1600;
+ l_spd_min_tck_max = 1250;
+ FAPI_INF( "DDR4/Centaur limitation. Centaur no longer handles 1866 and 1600 is min speed of DDR4. New Freq: %d",
+ l_dimm_freq_min);
+ }
+ else if ((l_module_type_group_1 == fapi2::ENUM_ATTR_CEN_SPD_MODULE_TYPE_RDIMM)
+ && (l_plug_config == MSS_FREQ_SINGLE_DROP)
+ && (l_dimm_freq_min > 1333))
+ {
+ l_dimm_freq_min = 1333;
+ l_spd_min_tck_max = 1500;
+ FAPI_INF( "Single Drop RDIMM with more than 1 Rank Cnfg limitation. New Freq: %d", l_dimm_freq_min);
+ }
+ // Double Drop RDIMMs Cnfgs cannot run faster than 1333 with less than 8 ranks total per port
+ else if ((l_module_type_group_1 == fapi2::ENUM_ATTR_CEN_SPD_MODULE_TYPE_RDIMM) && (l_plug_config == MSS_FREQ_DUAL_DROP)
+ && (l_num_ranks_total < 8) && (l_dimm_freq_min > 1333))
+ {
+ l_dimm_freq_min = 1333;
+ l_spd_min_tck_max = 1500;
+ FAPI_INF( "Dual Drop RDIMM with more than 4 Rank Cnfg limitation. New Freq: %d", l_dimm_freq_min);
+ }
+ // Double Drop RDIMMs Cnfgs cannot run faster than 1066 with 8 ranks total per port
+ else if ((l_module_type_group_1 == fapi2::ENUM_ATTR_CEN_SPD_MODULE_TYPE_RDIMM) && (l_plug_config == MSS_FREQ_DUAL_DROP)
+ && (l_num_ranks_total == 8) && (l_dimm_freq_min > 1066))
+ {
+ l_dimm_freq_min = 1066;
+ l_spd_min_tck_max = 1875;
+ FAPI_INF( "Dual Drop RDIMM with more than 8 Rank Cnfg limitation. New Freq: %d", l_dimm_freq_min);
+ }
+
+ if ( l_spd_min_tck_max == 0)
+ {
+ // Loop through the 2 MBA's
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_TCKMIN, l_dimm, l_spd_min_tck_MTB));
+
+ FAPI_ASSERT_NOEXIT(l_spd_min_tck_MTB != 0,
+ fapi2::CEN_MSS_UNSUPPORTED_SPD_DATA_COMMON().
+ set_MIN_TCK(l_spd_min_tck_max).
+ set_MIN_TAA(l_spd_min_taa_max).
+ set_DIMM_TARGET( l_dimm).
+ set_TARGET(i_target_memb),
+ "l_spd_min_tck_max = 0 unable to calculate freq or cl. Possibly no centaurs configured. ");
+ } // DIMM
+ } // MBA
+ } // if
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ_OVERRIDE, i_target_memb, l_freq_override));
+
+ if ( l_freq_override != 0)
+ {
+ // The relationship is as such
+ // l_dimm_freq_min = 2000000 / l_spd_min_tck_max
+
+ if (l_freq_override == 1866)
+ {
+ l_dimm_freq_min = 1866;
+ l_spd_min_tck_max = 1072;
+ }
+
+ if (l_freq_override == 1600)
+ {
+ l_dimm_freq_min = 1600;
+ l_spd_min_tck_max = 1250;
+ }
+
+ if (l_freq_override == 1333)
+ {
+ l_dimm_freq_min = 1333;
+ l_spd_min_tck_max = 1500;
+ }
+
+ if (l_freq_override == 1066)
+ {
+ l_dimm_freq_min = 1066;
+ l_spd_min_tck_max = 1875;
+ }
+
+ FAPI_INF( "Override Frequency Detected: %d", l_dimm_freq_min);
+ }
+
+ //If no common supported CL get rid of the minority DIMMs
+ FAPI_INF("l_spd_cas_lat_supported_all: %x", l_spd_cas_lat_supported_all);
+
+ if ((l_spd_cas_lat_supported_all == 0))
+ {
+ FAPI_INF("l_spd_cas_lat_supported_all: %x", l_spd_cas_lat_supported_all);
+
+ for(uint8_t i = 0; i < 20; i++)
+ {
+ if (l_cl_count_array[i] > l_highest_cl_count)
+ {
+ l_highest_common_cl = i;
+ }
+ }
+
+ // Loop through the 2 MBA's
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_CAS_LATENCIES_SUPPORTED, l_dimm, l_spd_cas_lat_supported));
+
+ FAPI_ASSERT_NOEXIT(l_spd_cas_lat_supported & 0x0000001 << l_highest_common_cl,
+ fapi2::CEN_MSS_NO_COMMON_SUPPORTED_CL().
+ set_DIMM_TARGET(l_dimm).
+ set_CL_SUPPORTED(l_spd_cas_lat_supported),
+ "No common supported CAS latencies between DIMMS.");
+ } // DIMM
+ } // MBA
+ }//if
+
+ //Determine a proposed CAS latency
+ l_cas_latency = l_spd_min_taa_max / l_spd_min_tck_max;
+
+ FAPI_INF( "CL = TAA / TCK ... TAA(ps): %d TCK(ps): %d", l_spd_min_taa_max, l_spd_min_tck_max);
+ FAPI_INF( "Calculated CL: %d", l_cas_latency);
+
+ if ( l_spd_min_taa_max % l_spd_min_tck_max)
+ {
+ l_cas_latency++;
+ FAPI_INF( "After rounding up ... CL: %d", l_cas_latency);
+ }
+
+ l_cl_mult_tck = l_cas_latency * l_spd_min_tck_max;
+
+ // If the CL proposed is not supported or the TAA exceeds TAA max
+ // Spec defines tAAmax as 20 ns for all DDR3 speed grades.
+ // Break loop if we have an override condition without a solution.
+ while ( ( (!( l_spd_cas_lat_supported_all & (0x00000001 << (l_cas_latency - 4)))) || (l_cl_mult_tck > 20000) )
+ && ( l_override_path == 0 ) )
+ {
+ FAPI_INF( "Warning calculated CL is not supported in VPD. Searching for a new CL.");
+
+ // If not supported, increment the CL up to 18 (highest supported CL) looking for Supported CL
+ while ((!( l_spd_cas_lat_supported_all & (0x00000001 << (l_cas_latency - 4)))) && (l_cas_latency < 18))
+ {
+ l_cas_latency++;
+ }
+
+ // If still not supported CL or TAA is > 20 ns ... pick a slower TCK and start again
+ l_cl_mult_tck = l_cas_latency * l_spd_min_tck_max;
+
+ // Do not move freq if using an override freq. Just continue. Hence the overide in this if statement
+ if ( ( (!( l_spd_cas_lat_supported_all & (0x00000001 << (l_cas_latency - 4)))) || (l_cl_mult_tck > 20000) )
+ && ( l_freq_override == 0) )
+ {
+ FAPI_INF( "No Supported CL works for calculating frequency. Lowering frequency and trying CL Algorithm again.");
+
+ if (l_spd_min_tck_max < 1500)
+ {
+ //1600 to 1333
+ l_spd_min_tck_max = 1500;
+ }
+ else if (l_spd_min_tck_max < 1875)
+ {
+ //1333 to 1066
+ l_spd_min_tck_max = 1875;
+ }
+ else if (l_spd_min_tck_max < 2500)
+ {
+ //1066 to 800
+ l_spd_min_tck_max = 2500;
+ }
+ else
+ {
+ //This is minimum frequency and cannot be lowered
+ //Therefore we will deconfig the minority dimms.
+ for(uint8_t i = 0; i < 20; i++)
+ {
+ if (l_cl_count_array[i] > l_lowest_cl_count)
+ {
+ l_lowest_common_cl = i;
+ }
+ }
+
+ // Loop through the 2 MBA's
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_CAS_LATENCIES_SUPPORTED, l_dimm, l_spd_cas_lat_supported));
+
+ if (l_spd_cas_lat_supported & 0x0000001 << l_lowest_common_cl)
+ {
+ FAPI_ASSERT_NOEXIT(false,
+ fapi2::CEN_MSS_EXCEED_TAA_MAX_NO_CL().
+ set_DIMM_TARGET(l_dimm).
+ set_CL_SUPPORTED(l_spd_cas_lat_supported),
+ "Lowered Frequency to TCLK MIN finding no supported CL without exceeding TAA MAX.");
+ }
+ } // DIMM
+ } // MBA
+ } // else
+
+ // Re-calculate with new tck
+ l_cas_latency = l_spd_min_taa_max / l_spd_min_tck_max;
+
+ if ( l_spd_min_taa_max % l_spd_min_tck_max)
+ {
+ l_cas_latency++;
+ }
+
+ l_cl_mult_tck = l_cas_latency * l_spd_min_tck_max;
+ l_dimm_freq_min = 2000000 / l_spd_min_tck_max;
+
+ } // if
+
+ // Need to break the loop in case we reach this condition because no longer modify freq and CL
+ // With an overrride
+ if ( ( (!( l_spd_cas_lat_supported_all & (0x00000001 << (l_cas_latency - 4)))) || (l_cl_mult_tck > 20000) )
+ && ( l_freq_override != 0) )
+ {
+ FAPI_INF( "No Supported CL works for override frequency. Using override frequency with an unsupported CL.");
+ l_override_path = 1;
+ }
+ } // while
+
+ //bucketize dimm freq.
+ if (l_dimm_freq_min < 1013)
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_UNSUPPORTED_FREQ_CALCULATED().
+ set_DIMM_MIN_FREQ(l_dimm_freq_min),
+ "Unsupported frequency: DIMM Freq calculated < 1013 MHz");
+
+ }
+ else if (l_dimm_freq_min < 1266)
+ {
+ // 1066
+ l_selected_dimm_freq = 1066;
+ }
+ else if (l_dimm_freq_min < 1520)
+ {
+ // 1333
+ l_selected_dimm_freq = 1333;
+ }
+ else if (l_dimm_freq_min < 1773)
+ {
+ // 1600
+ l_selected_dimm_freq = 1600;
+ }
+ else if (l_dimm_freq_min < 2026)
+ {
+ // 1866
+ l_selected_dimm_freq = 1866;
+ }
+ else if (l_dimm_freq_min < 2280)
+ {
+ // 2133
+ l_selected_dimm_freq = 2133;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_UNSUPPORTED_FREQ_CALCULATED().
+ set_DIMM_MIN_FREQ(l_dimm_freq_min),
+ "Unsupported frequency: DIMM Freq calculated > 2133 MHz: %d", l_dimm_freq_min);
+
+ }
+
+ // 0x03 = capable of both 8.0G/9.6G, 0x01 = capable of 8.0G, 0x02 = capable 9.6G
+ if ( l_selected_dimm_freq == 1066)
+ {
+ l_nest_capable_frequencies = 0x01;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_NEST_CAPABLE_FREQUENCIES, i_target_memb, l_nest_capable_frequencies));
+ }
+ else
+ {
+ l_nest_capable_frequencies = 0x03;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_NEST_CAPABLE_FREQUENCIES, i_target_memb, l_nest_capable_frequencies));
+ }
+
+ // set frequency in centaur attribute ATTR_MSS_FREQ
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_FREQ, i_target_memb, l_selected_dimm_freq));
+ FAPI_INF( "Final Chosen Frequency: %d ", l_selected_dimm_freq);
+ FAPI_INF( "Final Chosen CL: %d ", l_cas_latency);
+
+ for (uint32_t k = 0; k < l_mbaChiplets.size(); k++)
+ {
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_CL, l_mbaChiplets[k], l_cas_latency));
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.H
new file mode 100644
index 000000000..baec1dfbb
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.H
@@ -0,0 +1,54 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/// @file p9c_mss_freq.C
+/// @brief DIMM SPD attributes are read to determine optimal DRAM frequency
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamaring@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+
+#ifndef MSS_FREQHWPB_H_
+#define MSS_FREQHWPB_H_
+
+#include <fapi2.H>
+
+typedef fapi2::ReturnCode (*p9c_mss_freq_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>&);
+
+extern "C"
+{
+ ///
+ /// @brief DIMM SPD attributes are read to determine optimal DRAM frequency
+ /// @param[in] i_target_memb Centaur target
+ /// @return FAPI2_RC_SUCCESS iff frequency + CL found successfully
+ ///
+ fapi2::ReturnCode p9c_mss_freq(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target);
+
+} // extern "C"
+
+#endif // MSS_FREQHWPB_H_
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.mk
new file mode 100755
index 000000000..8122f5089
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.mk
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_freq.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+
+PROCEDURE=p9c_mss_freq
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.mk
index 79bc9e413..b57c35954 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.mk
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.mk
@@ -28,5 +28,4 @@
PROCEDURE=p9c_mss_unmask_errors
$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
-#lib$(PROCEDURE)_DEPLIBS+=mss
$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.C
new file mode 100644
index 000000000..92683204a
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.C
@@ -0,0 +1,362 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// @file p9c_mss_volt.C
+/// @brief Reads in supported DIMM voltages from SPD and determines optimal voltage bin for the DIMM voltage domain.
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamaring@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+
+// supported voltage bins: DDR3: 1.35 DDR4: 1.25V (expected)
+
+//----------------------------------------------------------------------
+// Includes - FAPI
+//----------------------------------------------------------------------
+#include <fapi2.H>
+#include <p9c_mss_volt.H>
+
+//----------------------------------------------------------------------
+// Constants
+//----------------------------------------------------------------------
+constexpr uint32_t MAX_TOLERATED_VOLT = 1500;
+constexpr uint32_t MAX_TOLERATED_DDR3_VOLT = 1500;
+constexpr uint32_t MAX_TOLERATED_DDR4_VOLT = 1200;
+constexpr uint32_t DDR3_VPP_VOLT = 0000;
+constexpr uint32_t DDR4_VPP_VOLT = 2500;
+
+
+///
+/// @brief Reads in supported DIMM voltages from SPD and determines optimal voltage bin for the DIMM voltage domain.
+/// @param[in] i_targets_memb - vector of centaur targets
+/// @return FAPI2_RC_SUCCESS iff voltage domain found
+///
+fapi2::ReturnCode p9c_mss_volt(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>>& i_targets_memb)
+{
+ uint8_t l_dimm_functionality = 0;
+ uint8_t l_spd_dramtype = 0;
+ uint8_t l_spd_volts = 0;
+ uint8_t l_spd_volts_all_dimms = 0xFF; //start assuming all voltages supported
+ uint8_t l_dram_ddr3_found_flag = 0;
+ uint8_t l_dram_ddr4_found_flag = 0;
+ uint8_t l_volt_override = 0x00;
+ uint8_t l_volt_override_domain = 0x00;
+
+ uint32_t l_selected_dram_voltage = 0; //this gets written into all centaurs when done.
+ uint32_t l_selected_dram_voltage_vpp = 0;
+ uint32_t l_tolerated_dram_voltage = MAX_TOLERATED_VOLT; //initially set to the max tolerated voltage
+ uint8_t l_dimm_count = 0;
+ uint8_t l_compliant_dimm_voltages = 0;
+
+ //Gather whether 1.5V only DIMMs supported
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VOLT_COMPLIANT_DIMMS, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_compliant_dimm_voltages));
+
+ // Iterate through the list of centaurs
+ for (const auto& l_cen : i_targets_memb)
+ {
+ // Get associated MBA's on this centaur
+ const auto l_mbaChiplets = l_cen.getChildren<fapi2::TARGET_TYPE_MBA>();
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VOLT_OVERRIDE, l_cen, l_volt_override));
+
+ // Note if there is an overrride being applied on the domain
+ if ( (l_volt_override != fapi2::ENUM_ATTR_CEN_MSS_VOLT_OVERRIDE_NONE)
+ && (l_volt_override_domain == fapi2::ENUM_ATTR_CEN_MSS_VOLT_OVERRIDE_NONE) )
+ {
+ l_volt_override_domain = l_volt_override;
+ }
+
+ // Error if our overides are not the same across the domain
+ FAPI_ASSERT(l_volt_override_domain == l_volt_override,
+ fapi2::CEN_MSS_VOLT_OVERIDE_MIXING().
+ set_OVERRIDE_TYPE(l_volt_override).
+ set_OVERRIDE_DOMAIN_TYPE(l_volt_override_domain).
+ set_MEMB_TARGET(l_cen),
+ "Mismatch volt override request. Domain: 0x%x Current Target<fapi2::TARGET_TYPE_MBA> Requests: 0x%x",
+ l_volt_override_domain, l_volt_override);
+
+ // Loop through the 2 MBA's
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_DRAM_DEVICE_TYPE, l_dimm, l_spd_dramtype));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE, l_dimm, l_spd_volts));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FUNCTIONAL, l_dimm, l_dimm_functionality));
+
+ // spd_volts: bit0= NOT 1.5V bit1=1.35V bit2=1.25V, assume a 1.20V in future for DDR4
+ // check for supported voltage/dram type combo DDR3=12, DDR4=13
+ if (l_spd_dramtype == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ l_dram_ddr3_found_flag = 1;
+ }
+ else if (l_spd_dramtype == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ l_dram_ddr4_found_flag = 1;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_VOLT_UNRECOGNIZED_DRAM_DEVICE_TYPE().
+ set_DEVICE_TYPE(l_spd_dramtype).
+ set_DIMM_TARGET(l_dimm),
+ "Unknown DRAM Device Type 0x%x", l_spd_dramtype);
+ }
+
+ if(l_dimm_functionality == fapi2::ENUM_ATTR_FUNCTIONAL_FUNCTIONAL)
+ {
+ //AND dimm voltage capabilities together to find aggregate voltage support on all dimms
+ l_spd_volts_all_dimms = l_spd_volts_all_dimms & l_spd_volts;
+ }
+ }//end of dimms loop
+ }//end of mba loop
+ }//end of centaur (memb) loop
+
+ // now we figure out if we have a supported ddr type and voltage
+ // note: only support DDR3=1.35V and DDR4=1.2xV
+
+ // Mixed Dimms, Deconfig the DDR4.
+ if (l_dram_ddr3_found_flag && l_dram_ddr4_found_flag)
+ {
+ // Iterate through the list of centaurs
+ for (const auto& l_cen : i_targets_memb)
+ {
+ // Get associated MBA's on this centaur
+ const auto l_mbaChiplets = l_cen.getChildren<fapi2::TARGET_TYPE_MBA>();
+
+ // Loop through the 2 MBA's
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_DRAM_DEVICE_TYPE, l_dimm, l_spd_dramtype));
+
+ FAPI_ASSERT(l_spd_dramtype = ! fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4,
+ fapi2::CEN_MSS_VOLT_DDR_TYPE_MIXING_UNSUPPORTED().
+ set_DIMM_DDR4_TARGET(l_dimm).
+ set_DEVICE_TYPE(l_spd_dramtype),
+ "mss_volt: DDR3 and DDR4 mixing not allowed");
+ }//end of dimms loop
+ }//end of mba loop
+ }//end of centaur (memb) loop
+ }//end of if(ddr3 && ddr4)
+
+ FAPI_INF( "Bitwise and of all DIMM_SPD: 0x%02x", l_spd_volts_all_dimms);
+
+ // If we are going to land on using 1.5V and we are not enabling that usage via attribute.
+ if ( ((l_spd_volts_all_dimms & fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_OP1_35) !=
+ fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_OP1_35) &&
+ ((l_spd_volts_all_dimms & fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2V) !=
+ fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2V) &&
+ ((l_spd_volts_all_dimms & fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) !=
+ fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) &&
+ (l_compliant_dimm_voltages == fapi2::ENUM_ATTR_CEN_MSS_VOLT_COMPLIANT_DIMMS_PROCEDURE_DEFINED) )
+ {
+
+ // Iterate through the list of centaurs
+ for (const auto& l_cen : i_targets_memb)
+ {
+ // Get associated MBA's on this centaur
+ const auto l_mbaChiplets = l_cen.getChildren<fapi2::TARGET_TYPE_MBA>();
+
+ // Loop through the 2 MBA's
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE, l_dimm, l_spd_volts));
+ FAPI_ASSERT((l_spd_volts & fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) ==
+ fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5,
+ fapi2::CEN_MSS_VOLT_DDR_TYPE_COMPLIANT_VOLTAGE().
+ set_DIMM_CV_TARGET(l_dimm).
+ set_DIMM_VOLTAGE(l_spd_volts),
+ "One or more DIMMs operate 1.5V which is not supported.");
+ }//end of dimms loop
+ }//end of mba loop
+ }//end of centaur (memb) loop
+ }
+
+ //Picking voltages based on overrides or supported voltages.
+ if (l_volt_override != fapi2::ENUM_ATTR_CEN_MSS_VOLT_OVERRIDE_NONE)
+ {
+ if (l_volt_override == fapi2::ENUM_ATTR_CEN_MSS_VOLT_OVERRIDE_VOLT_135)
+ {
+ l_selected_dram_voltage = 1350;
+ FAPI_INF( "mss_volt_overide being applied. MSS_VOLT_OVERRIDE: 1.35V");
+ FAPI_INF( "NOTE: Still checking for violations of tolerated voltage. If DIMMs cannot tolerate, the override will not be applied.");
+ }
+ else if (l_volt_override == fapi2::ENUM_ATTR_CEN_MSS_VOLT_OVERRIDE_VOLT_120)
+ {
+ l_selected_dram_voltage = 1200;
+ FAPI_INF( "mss_volt_overide being applied. MSS_VOLT_OVERRIDE: 1.20V");
+ FAPI_INF( "NOTE: Still checking for violations of tolerated voltage. If DIMMs cannot tolerate, the override will not be applied.");
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_VOLT_OVERIDE_UKNOWN().
+ set_OVERRIDE_TYPE(l_volt_override),
+ "Unknown volt override request. Override Request: 0x%x", l_volt_override);
+ }
+ }
+ else if (l_dram_ddr3_found_flag
+ && ((l_spd_volts_all_dimms & fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_OP1_35) ==
+ fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_OP1_35))
+ {
+ l_selected_dram_voltage = 1350;
+ l_selected_dram_voltage_vpp = DDR3_VPP_VOLT;
+ }
+ else if (l_dram_ddr4_found_flag
+ && ((l_spd_volts_all_dimms & fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2V) ==
+ fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2V))
+ {
+ l_selected_dram_voltage = 1200;
+ l_selected_dram_voltage_vpp = DDR4_VPP_VOLT;
+ }
+ else if ( ((l_spd_volts_all_dimms & fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) !=
+ fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) &&
+ (l_compliant_dimm_voltages == fapi2::ENUM_ATTR_CEN_MSS_VOLT_COMPLIANT_DIMMS_ALL_VOLTAGES))
+ {
+ l_selected_dram_voltage = 1500;
+ l_selected_dram_voltage_vpp = DDR3_VPP_VOLT;
+ }
+ else
+ {
+ // Iterate through the list of centaurs
+ for (const auto& l_cen : i_targets_memb)
+ {
+ // Get associated MBA's on this centaur
+ const auto l_mbaChiplets = l_cen.getChildren<fapi2::TARGET_TYPE_MBA>();
+
+ // Loop through the 2 MBA's
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE, l_dimm, l_spd_volts));
+ FAPI_ASSERT((l_spd_volts & fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) !=
+ fapi2::ENUM_ATTR_CEN_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5,
+ fapi2::CEN_MSS_VOLT_DDR_TYPE_REQUIRED_VOLTAGE().
+ set_DIMM_UV_TARGET(l_dimm).
+ set_DIMM_VOLTAGE(l_spd_volts),
+ "One or more DIMMs do not support required voltage for DIMM type");
+ }//end of dimms loop
+ }//end of mba loop
+ }//end of centaur (memb) loop
+ }
+
+ // Must check to see if we violate Tolerent voltages of Non-functional Dimms
+ // If so we must error/deconfigure on the dimm level primarily then centaur level.
+ // Iterate through the list of centaurs
+ for (const auto& l_cen : i_targets_memb)
+ {
+ l_tolerated_dram_voltage = MAX_TOLERATED_VOLT; // using 1.5 as this is the largest supported voltage
+ // Get associated MBA's on this centaur
+ const auto l_mbaChiplets = l_cen.getChildren<fapi2::TARGET_TYPE_MBA>();
+
+ for (const auto& l_mba : l_mbaChiplets)
+ {
+ // Get a vector of DIMM targets
+ const auto l_dimm_targets = l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
+
+ for (const auto& l_dimm : l_dimm_targets)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FUNCTIONAL, l_dimm, l_dimm_functionality));
+
+
+ if(l_dimm_functionality == fapi2::ENUM_ATTR_FUNCTIONAL_NON_FUNCTIONAL)
+ {
+ if (l_spd_dramtype == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
+ {
+ if (l_tolerated_dram_voltage > MAX_TOLERATED_DDR3_VOLT)
+ {
+ l_tolerated_dram_voltage = MAX_TOLERATED_DDR3_VOLT;
+ }
+
+ FAPI_ASSERT(MAX_TOLERATED_DDR3_VOLT > l_selected_dram_voltage,
+ fapi2::CEN_MSS_VOLT_TOLERATED_VOLTAGE_VIOLATION().
+ set_CHIP_TARGET(l_dimm).
+ set_DIMM_VOLTAGE(l_selected_dram_voltage),
+ "One or more DIMMs classified non-functional has a"
+ " tolerated voltage below selected voltage.");
+ }
+
+ if (l_spd_dramtype == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR4)
+ {
+ if (l_tolerated_dram_voltage > MAX_TOLERATED_DDR4_VOLT)
+ {
+ l_tolerated_dram_voltage = MAX_TOLERATED_DDR4_VOLT;
+ }
+
+ FAPI_ASSERT(MAX_TOLERATED_DDR4_VOLT > l_selected_dram_voltage,
+ fapi2::CEN_MSS_VOLT_TOLERATED_VOLTAGE_VIOLATION().
+ set_CHIP_TARGET(l_dimm).
+ set_DIMM_VOLTAGE(l_selected_dram_voltage),
+ "One or more DIMMs classified non-functional has a"
+ " tolerated voltage below selected voltage.");
+ }
+
+ }//End of functional check
+ }//End of Dimm loop
+ }// End of MBA loop
+
+ FAPI_ASSERT(l_tolerated_dram_voltage > l_selected_dram_voltage,
+ fapi2::CEN_MSS_VOLT_TOLERATED_VOLTAGE_VIOLATION().
+ set_CHIP_TARGET(l_cen).
+ set_DIMM_VOLTAGE(l_selected_dram_voltage),
+ "Deconfiguring the associated Centaur.");
+ }//End of Centaur (MEMB) loop
+
+ // Iterate through the list of centaurs again, to update ATTR
+ for (const auto& l_cen : i_targets_memb)
+ {
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_VOLT, l_cen, l_selected_dram_voltage));
+ FAPI_INF( "mss_volt calculation complete. MSS_VOLT: %d", l_selected_dram_voltage);
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_VOLT_VPP, l_cen, l_selected_dram_voltage_vpp));
+ FAPI_INF( "mss_volt calculation complete. MSS_VOLT_VPP: %d", l_selected_dram_voltage_vpp);
+ }
+
+ // Initialize DIMM Count Attribute for mss_volt_dimm_count to use
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_VMEM_REGULATOR_MAX_DIMM_COUNT, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_dimm_count));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.H
new file mode 100644
index 000000000..db7db0d7c
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.H
@@ -0,0 +1,54 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// @file p9c_mss_volt.H
+/// @brief Reads in supported DIMM voltages from SPD and determines optimal voltage bin for the DIMM voltage domain.
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamaring@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB
+
+
+#ifndef MSS_VOLTHWPB_H_
+#define MSS_VOLTHWPB_H_
+
+#include <fapi2.H>
+
+typedef fapi2::ReturnCode (*p9c_mss_volt_FP_t)(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>>&);
+
+extern "C"
+{
+
+ ///
+ /// @brief Reads in supported DIMM voltages from SPD and determines optimal voltage bin for the DIMM voltage domain.
+ /// @param[in] i_targets_memb - vector of centaur targets
+ /// @return FAPI2_RC_SUCCESS iff operating voltage found
+ ///
+ fapi2::ReturnCode p9c_mss_volt(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>>& l_targets_memb);
+
+} // extern "C"
+
+#endif // MSS_VOLTHWPB_H_
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.mk
new file mode 100755
index 000000000..1f1f92b9e
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.mk
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_volt.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+
+PROCEDURE=p9c_mss_volt
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.C b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.C
new file mode 100644
index 000000000..13a38d737
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.C
@@ -0,0 +1,305 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: mss_eff_config_thermal_wrap.C,v 1.4 2014/02/19 23:30:25 asaetow Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/ipl/fapi2/wrapper/mss_eff_config_thermal_wrap.C,v $
+//------------------------------------------------------------------------------
+// *|
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+// *|
+// *! TITLE : mss_eff_config_thermal_wrap.C
+// *!
+// *! OWNER NAME : Joab Henderson Email: joabhend@us.ibm.com
+// *! BACKUP NAME : Michael Pardeik Email: pardeik@us.ibm.com
+// *!
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include <prcdUtils.H>
+//#include <verifUtils.H>
+
+#include <croClientCapi.H>
+#include <ecmdClientCapi.H>
+#include <ecmdDataBuffer.H>
+#include <ecmdUtils.H>
+#include <ecmdSharedUtils.H>
+#include <fapi2.H>
+#include <fapi2ClientCapi.H>
+#include <fapi2SharedUtils.H>
+
+#include <p9c_mss_eff_config_thermal.H>
+
+
+//------------------------------------------------------------------------------
+// Function definitions
+//------------------------------------------------------------------------------
+
+// display help message
+void
+help()
+{
+ // procedure constants
+ std::string PROCEDURE = "p9c_mss_eff_config_thermal_wrap";
+ std::string REVISION = "$Revision: 1.4 $";
+
+ // build help message
+ char outstr[256];
+ snprintf(outstr, sizeof(outstr), "\nThis is the help text for the procedure %s (%s).\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+ ecmdOutput(" [-h] [-k#] [-n#] [-s#] [-p#] [-d] [-quiet] [-verif]\n");
+ ecmdOutput("\n");
+ ecmdOutput("Additional options:\n");
+ ecmdOutput(" -h Display this help message.\n");
+
+ ecmdOutput(" -k# Specify which cage to act on (default = 0).\n");
+ ecmdOutput(" -n# Specify which node to act on (default = 0).\n");
+ ecmdOutput(" -s# Specify which slot to act on (default = 0).\n");
+ ecmdOutput(" -p# Specify which chip position to act on (default = 0).\n");
+ ecmdOutput(" -quiet Suppress printing of eCMD DLL/procedure information (default = false).\n");
+ ecmdOutput(" -verif Run procedure in sim verification mode (default = false).\n");
+ return;
+}
+
+// main function
+int
+main(int argc, char* argv[])
+{
+ // procedure constants
+ const std::string PROCEDURE = "mss_eff_config_thermal_wrap";
+ const std::string REVISION = "$Revision: 1.4 $";
+
+ // from prcdUtils
+ extern bool GLOBAL_SIM_MODE;
+ extern bool GLOBAL_VERIF_MODE;
+
+ // flow/control variables
+ uint32_t rc = ECMD_SUCCESS;
+ fapi2::ReturnCode rc_fapi;
+ ecmdDllInfo DLLINFO;
+ ecmdLooperData node_looper;
+ ecmdChipTarget node_target;
+ char outstr[256];
+
+ // required parameters & optional flags
+
+ // load and initialize the eCMD Dll
+ // if left NULL, which DLL to load is determined by the ECMD_DLL_FILE
+ // environment variable if set to a specific value, the specified DLL
+ // will be loaded
+ rc = ecmdLoadDll("");
+
+ if (rc)
+ {
+ return rc;
+ }
+
+ do
+ {
+ // initalize FAPI extension
+ rc = fapi2InitExtension();
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing FAPI extension!\n");
+ break;
+ }
+
+ // establish if this is a simulation run or not
+ rc = ecmdQueryDllInfo(DLLINFO);
+
+ if (rc)
+ {
+ ecmdOutput("Error querying DLL!\n");
+ break;
+ }
+
+ if (DLLINFO.dllEnv == ECMD_DLL_ENV_SIM)
+ {
+ GLOBAL_SIM_MODE = true;
+ }
+
+ // show help message
+ if (ecmdParseOption(&argc, &argv, "-h"))
+ {
+ help();
+ break;
+ }
+
+
+ // run procedure in sim verification mode
+ if (ecmdParseOption(&argc, &argv, "-verif"))
+ {
+ GLOBAL_VERIF_MODE = true;
+ }
+
+ // parse out common eCMD args like -p0, -c0, -coe, etc..
+ // any found args will be removed from arg list upon return
+ rc = ecmdCommandArgs(&argc, &argv);
+
+ if (rc)
+ {
+ ecmdOutputError("Error parsing eCMD arguments\n");
+ break;
+ }
+
+ // unsupported arguments left over?
+ if (argc != 1)
+ {
+ ecmdOutputError("Unknown/unsupported arguments specified!\n");
+ help();
+ rc = ECMD_INVALID_ARGS;
+ break;
+ }
+
+ // print procedure information header
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ // print informational message
+ snprintf(outstr, sizeof(outstr), "Procedure %s: %s\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+
+ // always print the DLL info to the screen, unless in quiet mode
+ rc = ecmdDisplayDllInfo();
+
+ if (rc)
+ {
+ ecmdOutputError("Error displaying DLL info!");
+ break;
+ }
+ }
+
+ // configure looper to iterate over all nodes
+ node_target.cageState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.nodeState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.slotState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.posState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+ rc = ecmdConfigLooperInit(node_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, node_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing node looper!\n");
+ break;
+ }
+
+ // loop over specified configured nodes
+ while (ecmdConfigLooperNext(node_target, node_looper))
+ {
+ std::vector<ecmdChipTarget> ecmd_chip_targets;
+ ecmdLooperData cen_looper;
+ ecmdChipTarget cen_target;
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Processing %s\n",
+ ecmdWriteTarget(node_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ cen_target.chipType = "cen";
+ cen_target.chipTypeState = ECMD_TARGET_FIELD_VALID;
+ cen_target.chipUnitType = "mba";
+ cen_target.chipUnitTypeState = ECMD_TARGET_FIELD_VALID;
+
+ cen_target.cage = node_target.cage;
+ cen_target.node = node_target.node;
+
+ cen_target.cageState = ECMD_TARGET_FIELD_VALID;
+ cen_target.nodeState = ECMD_TARGET_FIELD_VALID;
+ cen_target.slotState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.posState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ cen_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+ cen_target.chipUnitNumState = ECMD_TARGET_FIELD_WILDCARD;
+
+ rc = ecmdConfigLooperInit(cen_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, cen_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing chip looper!\n");
+ break;
+ }
+
+ // loop over configured positions inside current node
+ while(ecmdConfigLooperNext(cen_target, cen_looper))
+ {
+ fapi2::Target<fapi2::TARGET_TYPE_MBA> fapi_target(&cen_target);
+ uint8_t is_functional;
+ rc = FAPI_ATTR_GET(fapi2::ATTR_FUNCTIONAL, fapi_target, is_functional);
+
+ if (rc)
+ {
+ snprintf(outstr, sizeof(outstr), "ERROR: Problem getting ATTR_FUNCTIONAL");
+ ecmdOutput(outstr);
+ break;
+ }
+
+ if (is_functional == 0)
+ {
+ continue;
+ }
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Going to call %s on %s\n",
+ PROCEDURE.c_str(),
+ ecmdWriteTarget(cen_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ // invoke FAPI procedure core
+ FAPI_EXEC_HWP(rc_fapi,
+ p9c_mss_eff_config_thermal,
+ fapi_target);
+ rc = (uint32_t) rc_fapi;
+
+ if (rc)
+ {
+ snprintf(outstr, sizeof(outstr), "ERROR: %s FAPI call exited with bad return code = %s 0x%08x\n",
+ PROCEDURE.c_str(),
+ ecmdParseReturnCode(rc).c_str(), rc);
+ ecmdOutputError(outstr);
+ break;
+ }
+ }
+ }
+
+ if (rc)
+ {
+ break;
+ }
+ }
+ while(0);
+
+ ecmdUnloadDll();
+ return rc;
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.mk b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.mk
new file mode 100755
index 000000000..8a458b31b
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.mk
@@ -0,0 +1,29 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_thermal_wrap.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+WRAPPER=p9c_mss_eff_config_thermal_wrap
+$(WRAPPER)_USELIBS+=p9c_mss_eff_config_thermal
+$(WRAPPER)_DEPLIBS+=cen
+$(call BUILD_WRAPPER)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.C b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.C
new file mode 100755
index 000000000..b1123f378
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.C
@@ -0,0 +1,307 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: mss_eff_config_wrap.C,v 1.5 2014/02/19 21:47:11 jmcgill Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/ipl/fapi2/wrapper/mss_eff_config_wrap.C,v $
+//------------------------------------------------------------------------------
+// *|
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+// *|
+// *! TITLE : mss_eff_config_wrap.C
+// *!
+// *! OWNER NAME : Anuwat Saetow Email: asaetow@us.ibm.com
+// *!
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include <prcdUtils.H>
+//#include <verifUtils.H>
+
+#include <croClientCapi.H>
+#include <ecmdClientCapi.H>
+#include <ecmdDataBuffer.H>
+#include <ecmdUtils.H>
+#include <ecmdSharedUtils.H>
+#include <fapi2.H>
+#include <fapi2ClientCapi.H>
+#include <fapi2SharedUtils.H>
+
+#include <p9c_mss_eff_config.H>
+
+
+//------------------------------------------------------------------------------
+// Function definitions
+//------------------------------------------------------------------------------
+
+// display help message
+void
+help()
+{
+ // procedure constants
+ std::string PROCEDURE = "mss_eff_config_wrap";
+ std::string REVISION = "$Revision: 1.5 $";
+
+ // build help message
+ char outstr[256];
+ snprintf(outstr, sizeof(outstr), "\nThis is the help text for the procedure %s (%s).\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+ ecmdOutput(" [-h] [-k#] [-n#] [-s#] [-p#] [-d] [-quiet] [-verif]\n");
+ ecmdOutput("\n");
+ ecmdOutput("Additional options:\n");
+ ecmdOutput(" -h Display this help message.\n");
+
+ ecmdOutput(" -k# Specify which cage to act on (default = 0).\n");
+ ecmdOutput(" -n# Specify which node to act on (default = 0).\n");
+ ecmdOutput(" -s# Specify which slot to act on (default = 0).\n");
+ ecmdOutput(" -p# Specify which chip position to act on (default = 0).\n");
+ ecmdOutput(" -d Enable debugging output (default = false)\n");
+ ecmdOutput(" -quiet Suppress printing of eCMD DLL/procedure information (default = false).\n");
+ ecmdOutput(" -verif Run procedure in sim verification mode (default = false).\n");
+ return;
+}
+
+// main function
+int
+main(int argc, char* argv[])
+{
+ // procedure constants
+ const std::string PROCEDURE = "mss_eff_config_wrap";
+ const std::string REVISION = "$Revision: 1.5 $";
+
+ // from prcdUtils
+ extern bool GLOBAL_SIM_MODE;
+ extern bool GLOBAL_VERIF_MODE;
+
+ // flow/control variables
+ uint32_t rc = ECMD_SUCCESS;
+ fapi2::ReturnCode rc_fapi;
+ ecmdDllInfo DLLINFO;
+ ecmdLooperData node_looper;
+ ecmdChipTarget node_target;
+ char outstr[256];
+
+ // required parameters & optional flags
+
+ // load and initialize the eCMD Dll
+ // if left NULL, which DLL to load is determined by the ECMD_DLL_FILE
+ // environment variable if set to a specific value, the specified DLL
+ // will be loaded
+ rc = ecmdLoadDll("");
+
+ if (rc)
+ {
+ return rc;
+ }
+
+ do
+ {
+ // initalize FAPI extension
+ rc = fapi2InitExtension();
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing FAPI extension!\n");
+ break;
+ }
+
+ // establish if this is a simulation run or not
+ rc = ecmdQueryDllInfo(DLLINFO);
+
+ if (rc)
+ {
+ ecmdOutput("Error querying DLL!\n");
+ break;
+ }
+
+ if (DLLINFO.dllEnv == ECMD_DLL_ENV_SIM)
+ {
+ GLOBAL_SIM_MODE = true;
+ }
+
+ // show help message
+ if (ecmdParseOption(&argc, &argv, "-h"))
+ {
+ help();
+ break;
+ }
+
+
+ // run procedure in sim verification mode
+ if (ecmdParseOption(&argc, &argv, "-verif"))
+ {
+ GLOBAL_VERIF_MODE = true;
+ }
+
+ // parse out common eCMD args like -p0, -c0, -coe, etc..
+ // any found args will be removed from arg list upon return
+ rc = ecmdCommandArgs(&argc, &argv);
+
+ if (rc)
+ {
+ ecmdOutputError("Error parsing eCMD arguments\n");
+ break;
+ }
+
+ // unsupported arguments left over?
+ if (argc != 1)
+ {
+ ecmdOutputError("Unknown/unsupported arguments specified!\n");
+ help();
+ rc = ECMD_INVALID_ARGS;
+ break;
+ }
+
+ // print procedure information header
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ // print informational message
+ snprintf(outstr, sizeof(outstr), "Procedure %s: %s\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+
+ // always print the DLL info to the screen, unless in quiet mode
+ rc = ecmdDisplayDllInfo();
+
+ if (rc)
+ {
+ ecmdOutputError("Error displaying DLL info!");
+ break;
+ }
+ }
+
+ // configure looper to iterate over all nodes
+ node_target.cageState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.nodeState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.slotState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.posState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+ rc = ecmdConfigLooperInit(node_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, node_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing node looper!\n");
+ break;
+ }
+
+ // loop over specified configured nodes
+ while (ecmdConfigLooperNext(node_target, node_looper))
+ {
+ std::vector<ecmdChipTarget> ecmd_chip_targets;
+ std::vector<fapi2::Target<fapi2::TARGET_TYPE_MBA>> fapi_chip_targets;
+ ecmdLooperData cen_looper;
+ ecmdChipTarget cen_target;
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Processing %s\n",
+ ecmdWriteTarget(node_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ cen_target.chipType = "cen";
+ cen_target.chipTypeState = ECMD_TARGET_FIELD_VALID;
+ cen_target.chipUnitType = "mba";
+ cen_target.chipUnitTypeState = ECMD_TARGET_FIELD_VALID;
+
+ cen_target.cage = node_target.cage;
+ cen_target.node = node_target.node;
+
+ cen_target.cageState = ECMD_TARGET_FIELD_VALID;
+ cen_target.nodeState = ECMD_TARGET_FIELD_VALID;
+ cen_target.slotState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.posState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ cen_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+ cen_target.chipUnitNumState = ECMD_TARGET_FIELD_WILDCARD;
+
+ rc = ecmdConfigLooperInit(cen_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, cen_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing chip looper!\n");
+ break;
+ }
+
+ // loop over configured positions inside current node
+ while(ecmdConfigLooperNext(cen_target, cen_looper))
+ {
+ fapi2::Target<fapi2::TARGET_TYPE_MBA> fapi_target(&cen_target);
+ uint8_t is_functional;
+
+ rc = FAPI_ATTR_GET(fapi2::ATTR_FUNCTIONAL, fapi_target, is_functional);
+
+ if (rc)
+ {
+ snprintf(outstr, sizeof(outstr), "ERROR: Problem getting ATTR_FUNCTIONAL");
+ ecmdOutput(outstr);
+ break;
+ }
+
+ if (is_functional == 0)
+ {
+ continue;
+ }
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Going to call %s on %s\n",
+ PROCEDURE.c_str(),
+ ecmdWriteTarget(cen_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ // invoke FAPI procedure core
+ FAPI_EXEC_HWP(rc_fapi,
+ p9c_mss_eff_config,
+ fapi_target);
+ rc = (uint32_t) rc_fapi;
+
+ if (rc)
+ {
+ snprintf(outstr, sizeof(outstr), "ERROR: %s FAPI call exited with bad return code = %s 0x%08x\n",
+ PROCEDURE.c_str(),
+ ecmdParseReturnCode(rc).c_str(), rc);
+ ecmdOutputError(outstr);
+ break;
+ }
+ }
+ }
+
+ if (rc)
+ {
+ break;
+ }
+ }
+ while(0);
+
+ ecmdUnloadDll();
+ return rc;
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.mk b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.mk
new file mode 100755
index 000000000..051cdfdce
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.mk
@@ -0,0 +1,29 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_config_wrap.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+WRAPPER=p9c_mss_eff_config_wrap
+$(WRAPPER)_USELIBS+=p9c_mss_eff_config
+$(WRAPPER)_DEPLIBS+=cen
+$(call BUILD_WRAPPER)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.C b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.C
new file mode 100755
index 000000000..229ae21af
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.C
@@ -0,0 +1,311 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: mss_eff_mb_interleave_wrap.C,v 1.2 2014/02/19 23:29:25 asaetow Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/ipl/fapi2/wrapper/mss_eff_mb_interleave_wrap.C,v $
+//------------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+// *! Licensed material - Program property of IBM
+// *! Refer to copyright instructions form no. G120-2083
+// *! Created on Wed Jan 8 2014 at 07:56:54
+//------------------------------------------------------------------------------
+// *! TITLE : mss_eff_mb_interleave_wrap
+// *! DESCRIPTION : see additional comments below
+// *! OWNER NAME : Bellows Mark D. (Mark D),319432 Email: bellows@us.ibm.com
+// *! BACKUP NAME : Email: ______@us.ibm.com
+
+// *! ADDITIONAL COMMENTS :
+//
+//------------------------------------------------------------------------------
+// Don't forget to create CVS comments when you check in your changes!
+//------------------------------------------------------------------------------
+// CHANGE HISTORY:
+//------------------------------------------------------------------------------
+// Version:| Author: | Date: | Comment:
+//---------|----------|---------|-----------------------------------------------
+// 1.0 | bellows |08-JAN-14| Created.
+#include <prcdUtils.H>
+//#include <verifUtils.H>
+
+#include <croClientCapi.H>
+#include <ecmdClientCapi.H>
+#include <ecmdDataBuffer.H>
+#include <ecmdUtils.H>
+#include <ecmdSharedUtils.H>
+#include <fapi2.H>
+#include <fapi2ClientCapi.H>
+#include <fapi2SharedUtils.H>
+
+#include <p9c_mss_eff_mb_interleave.H>
+
+
+//------------------------------------------------------------------------------
+// Function definitions
+//------------------------------------------------------------------------------
+
+// display help message
+void
+help()
+{
+ // procedure constants
+ std::string PROCEDURE = "mss_eff_mb_interleave_wrap";
+ std::string REVISION = "$Revision: 1.2 $";
+
+ // build help message
+ char outstr[256];
+ snprintf(outstr, sizeof(outstr), "\nThis is the help text for the procedure %s (%s).\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+ ecmdOutput(" [-h] [-k#] [-n#] [-s#] [-p#] [-d] [-quiet] [-verif]\n");
+ ecmdOutput("\n");
+ ecmdOutput("Additional options:\n");
+ ecmdOutput(" -h Display this help message.\n");
+
+ ecmdOutput(" -k# Specify which cage to act on (default = 0).\n");
+ ecmdOutput(" -n# Specify which node to act on (default = 0).\n");
+ ecmdOutput(" -s# Specify which slot to act on (default = 0).\n");
+ ecmdOutput(" -p# Specify which chip position to act on (default = 0).\n");
+ ecmdOutput(" -quiet Suppress printing of eCMD DLL/procedure information (default = false).\n");
+ ecmdOutput(" -verif Run procedure in sim verification mode (default = false).\n");
+ return;
+}
+
+// main function
+int
+main(int argc, char* argv[])
+{
+ // procedure constants
+ const std::string PROCEDURE = "mss_eff_mb_interleave_wrap";
+ const std::string REVISION = "$Revision: 1.2 $";
+
+ // from prcdUtils
+ extern bool GLOBAL_SIM_MODE;
+ extern bool GLOBAL_VERIF_MODE;
+
+ // flow/control variables
+ uint32_t rc = ECMD_SUCCESS;
+ fapi2::ReturnCode rc_fapi;
+ ecmdDllInfo DLLINFO;
+ ecmdLooperData node_looper;
+ ecmdChipTarget node_target;
+ char outstr[256];
+
+ // required parameters & optional flags
+
+ // load and initialize the eCMD Dll
+ // if left NULL, which DLL to load is determined by the ECMD_DLL_FILE
+ // environment variable if set to a specific value, the specified DLL
+ // will be loaded
+ rc = ecmdLoadDll("");
+
+ if (rc)
+ {
+ return rc;
+ }
+
+ do
+ {
+ // initalize FAPI extension
+ rc = fapi2InitExtension();
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing FAPI extension!\n");
+ break;
+ }
+
+ // establish if this is a simulation run or not
+ rc = ecmdQueryDllInfo(DLLINFO);
+
+ if (rc)
+ {
+ ecmdOutput("Error querying DLL!\n");
+ break;
+ }
+
+ if (DLLINFO.dllEnv == ECMD_DLL_ENV_SIM)
+ {
+ GLOBAL_SIM_MODE = true;
+ }
+
+ // show help message
+ if (ecmdParseOption(&argc, &argv, "-h"))
+ {
+ help();
+ break;
+ }
+
+ // run procedure in sim verification mode
+ if (ecmdParseOption(&argc, &argv, "-verif"))
+ {
+ GLOBAL_VERIF_MODE = true;
+ }
+
+ // parse out common eCMD args like -p0, -c0, -coe, etc..
+ // any found args will be removed from arg list upon return
+ rc = ecmdCommandArgs(&argc, &argv);
+
+ if (rc)
+ {
+ ecmdOutputError("Error parsing eCMD arguments\n");
+ break;
+ }
+
+ // unsupported arguments left over?
+ if (argc != 1)
+ {
+ ecmdOutputError("Unknown/unsupported arguments specified!\n");
+ help();
+ rc = ECMD_INVALID_ARGS;
+ break;
+ }
+
+ // print procedure information header
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ // print informational message
+ snprintf(outstr, sizeof(outstr), "Procedure %s: %s\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+
+ // always print the DLL info to the screen, unless in quiet mode
+ rc = ecmdDisplayDllInfo();
+
+ if (rc)
+ {
+ ecmdOutputError("Error displaying DLL info!");
+ break;
+ }
+ }
+
+ // configure looper to iterate over all nodes
+ node_target.cageState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.nodeState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.slotState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.posState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+ rc = ecmdConfigLooperInit(node_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, node_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing node looper!\n");
+ break;
+ }
+
+ // loop over specified configured nodes
+ while (ecmdConfigLooperNext(node_target, node_looper))
+ {
+ std::vector<ecmdChipTarget> ecmd_chip_targets;
+ ecmdLooperData cen_looper;
+ ecmdChipTarget cen_target;
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Processing %s\n",
+ ecmdWriteTarget(node_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ cen_target.chipType = "cen";
+ cen_target.chipTypeState = ECMD_TARGET_FIELD_VALID;
+ cen_target.chipUnitType = "";
+ cen_target.chipUnitTypeState = ECMD_TARGET_FIELD_UNUSED;
+
+ cen_target.cage = node_target.cage;
+ cen_target.node = node_target.node;
+
+ cen_target.cageState = ECMD_TARGET_FIELD_VALID;
+ cen_target.nodeState = ECMD_TARGET_FIELD_VALID;
+ cen_target.slotState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.posState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ cen_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+ cen_target.chipUnitNumState = ECMD_TARGET_FIELD_UNUSED;
+
+ rc = ecmdConfigLooperInit(cen_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, cen_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing chip looper!\n");
+ break;
+ }
+
+ // loop over configured positions inside current node
+ while(ecmdConfigLooperNext(cen_target, cen_looper))
+ {
+ fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> fapi_target(&cen_target);
+ uint8_t is_functional;
+
+ rc = FAPI_ATTR_GET(fapi2::ATTR_FUNCTIONAL, fapi_target, is_functional);
+
+ if (rc)
+ {
+ snprintf(outstr, sizeof(outstr), "ERROR: Problem getting ATTR_FUNCTIONAL");
+ ecmdOutput(outstr);
+ break;
+ }
+
+ if (is_functional == 0)
+ {
+ continue;
+ }
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Going to call %s on %s\n",
+ PROCEDURE.c_str(),
+ ecmdWriteTarget(cen_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ // invoke FAPI procedure core
+ FAPI_EXEC_HWP(rc_fapi,
+ p9c_mss_eff_mb_interleave,
+ fapi_target);
+ rc = (uint32_t) rc_fapi;
+
+ if (rc)
+ {
+ snprintf(outstr, sizeof(outstr), "ERROR: %s FAPI call exited with bad return code = %s 0x%08x\n",
+ PROCEDURE.c_str(),
+ ecmdParseReturnCode(rc).c_str(), rc);
+ ecmdOutputError(outstr);
+ break;
+ }
+ }
+ }
+
+ if (rc)
+ {
+ break;
+ }
+ }
+ while(0);
+
+ ecmdUnloadDll();
+ return rc;
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.mk b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.mk
new file mode 100755
index 000000000..48fe5d3fc
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.mk
@@ -0,0 +1,29 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_eff_mb_interleave_wrap.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+WRAPPER=p9c_mss_eff_mb_interleave_wrap
+$(WRAPPER)_USELIBS+=p9c_mss_eff_mb_interleave
+$(WRAPPER)_DEPLIBS+=cen
+$(call BUILD_WRAPPER)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.C b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.C
new file mode 100644
index 000000000..9c328ec7b
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.C
@@ -0,0 +1,286 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: mss_freq_wrap.C,v 1.4 2013/09/23 20:26:05 jmcgill Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/ipl/fapi2/wrapper/mss_freq_wrap.C,v $
+//------------------------------------------------------------------------------
+// *|
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+// *|
+// *! TITLE : mss_freq_wrap.C
+// *!
+// *! OWNER NAME : Jacob Sloat Email: jdsloat@us.ibm.com
+// *!
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include <prcdUtils.H>
+//#include <verifUtils.H>
+
+#include <croClientCapi.H>
+#include <ecmdClientCapi.H>
+#include <ecmdDataBuffer.H>
+#include <ecmdUtils.H>
+#include <ecmdSharedUtils.H>
+#include <fapi2.H>
+#include <fapi2ClientCapi.H>
+#include <fapi2SharedUtils.H>
+
+#include <p9c_mss_freq.H>
+
+
+//------------------------------------------------------------------------------
+// Function definitions
+//------------------------------------------------------------------------------
+
+// display help message
+void
+help()
+{
+ // procedure constants
+ std::string PROCEDURE = "mss_freq_wrap";
+ std::string REVISION = "$Revision: 1.4 $";
+
+ // build help message
+ char outstr[256];
+ snprintf(outstr, sizeof(outstr), "\nThis is the help text for the procedure %s (%s).\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+ ecmdOutput(" [-h] [-k#] [-n#] [-s#] [-p#] [-d] [-quiet] [-verif]\n");
+ ecmdOutput("\n");
+ ecmdOutput("Additional options:\n");
+ ecmdOutput(" -h Display this help message.\n");
+
+ ecmdOutput(" -k# Specify which cage to act on (default = 0).\n");
+ ecmdOutput(" -n# Specify which node to act on (default = 0).\n");
+ ecmdOutput(" -s# Specify which slot to act on (default = 0).\n");
+ ecmdOutput(" -p# Specify which chip position to act on (default = 0).\n");
+ ecmdOutput(" -quiet Suppress printing of eCMD DLL/procedure information (default = false).\n");
+ ecmdOutput(" -verif Run procedure in sim verification mode (default = false).\n");
+ return;
+}
+
+// main function
+int
+main(int argc, char* argv[])
+{
+ // procedure constants
+ const std::string PROCEDURE = "mss_freq_wrap";
+ const std::string REVISION = "$Revision: 1.4 $";
+
+ // from prcdUtils
+ extern bool GLOBAL_SIM_MODE;
+ extern bool GLOBAL_VERIF_MODE;
+
+ // flow/control variables
+ uint32_t rc = ECMD_SUCCESS;
+ fapi2::ReturnCode rc_fapi;
+ ecmdDllInfo DLLINFO;
+ ecmdLooperData node_looper;
+ ecmdChipTarget node_target;
+ char outstr[256];
+
+ // required parameters & optional flags
+
+ // load and initialize the eCMD Dll
+ // if left NULL, which DLL to load is determined by the ECMD_DLL_FILE
+ // environment variable if set to a specific value, the specified DLL
+ // will be loaded
+ rc = ecmdLoadDll("");
+
+ if (rc)
+ {
+ return rc;
+ }
+
+ do
+ {
+ // initalize FAPI extension
+ rc = fapi2InitExtension();
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing FAPI extension!\n");
+ break;
+ }
+
+ // establish if this is a simulation run or not
+ rc = ecmdQueryDllInfo(DLLINFO);
+
+ if (rc)
+ {
+ ecmdOutput("Error querying DLL!\n");
+ break;
+ }
+
+ if (DLLINFO.dllEnv == ECMD_DLL_ENV_SIM)
+ {
+ GLOBAL_SIM_MODE = true;
+ }
+
+ // show help message
+ if (ecmdParseOption(&argc, &argv, "-h"))
+ {
+ help();
+ break;
+ }
+
+ // run procedure in sim verification mode
+ if (ecmdParseOption(&argc, &argv, "-verif"))
+ {
+ GLOBAL_VERIF_MODE = true;
+ }
+
+ // parse out common eCMD args like -p0, -c0, -coe, etc..
+ // any found args will be removed from arg list upon return
+ rc = ecmdCommandArgs(&argc, &argv);
+
+ if (rc)
+ {
+ ecmdOutputError("Error parsing eCMD arguments\n");
+ break;
+ }
+
+ // unsupported arguments left over?
+ if (argc != 1)
+ {
+ ecmdOutputError("Unknown/unsupported arguments specified!\n");
+ help();
+ rc = ECMD_INVALID_ARGS;
+ break;
+ }
+
+ // print procedure information header
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ // print informational message
+ snprintf(outstr, sizeof(outstr), "Procedure %s: %s\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+
+ // always print the DLL info to the screen, unless in quiet mode
+ rc = ecmdDisplayDllInfo();
+
+ if (rc)
+ {
+ ecmdOutputError("Error displaying DLL info!");
+ break;
+ }
+ }
+
+ // configure looper to iterate over all nodes
+ node_target.cageState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.nodeState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.slotState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.posState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+ rc = ecmdConfigLooperInit(node_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, node_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing node looper!\n");
+ break;
+ }
+
+ // loop over specified configured nodes
+ while (ecmdConfigLooperNext(node_target, node_looper))
+ {
+ std::vector<ecmdChipTarget> ecmd_chip_targets;
+ std::vector<fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>> fapi_chip_targets;
+ ecmdLooperData cen_looper;
+ ecmdChipTarget cen_target;
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Processing %s\n",
+ ecmdWriteTarget(node_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ cen_target.chipType = "cen";
+ cen_target.chipTypeState = ECMD_TARGET_FIELD_VALID;
+
+ cen_target.cage = node_target.cage;
+ cen_target.node = node_target.node;
+
+ cen_target.cageState = ECMD_TARGET_FIELD_VALID;
+ cen_target.nodeState = ECMD_TARGET_FIELD_VALID;
+ cen_target.slotState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.posState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ cen_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+
+ rc = ecmdConfigLooperInit(cen_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, cen_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing chip looper!\n");
+ break;
+ }
+
+ // loop over configured positions inside current node
+ while(ecmdConfigLooperNext(cen_target, cen_looper))
+ {
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Going to call %s on %s\n",
+ PROCEDURE.c_str(),
+ ecmdWriteTarget(cen_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ // invoke FAPI procedure core
+ fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> fapi_target(&cen_target);
+ FAPI_EXEC_HWP(rc_fapi,
+ p9c_mss_freq,
+ fapi_target);
+ rc = (uint32_t) rc_fapi;
+
+ if (rc)
+ {
+ snprintf(outstr, sizeof(outstr), "ERROR: %s FAPI call exited with bad return code = %s 0x%08x\n",
+ PROCEDURE.c_str(),
+ ecmdParseReturnCode(rc).c_str(), rc);
+ ecmdOutputError(outstr);
+ break;
+ }
+ }
+ }
+
+ if (rc)
+ {
+ break;
+ }
+ }
+ while(0);
+
+ ecmdUnloadDll();
+ return rc;
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.mk b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.mk
new file mode 100755
index 000000000..ed82eeb8b
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.mk
@@ -0,0 +1,29 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_freq_wrap.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+WRAPPER=p9c_mss_freq_wrap
+$(WRAPPER)_USELIBS+=p9c_mss_freq
+$(WRAPPER)_DEPLIBS+=cen
+$(call BUILD_WRAPPER)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.C b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.C
new file mode 100644
index 000000000..29e010d5a
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.C
@@ -0,0 +1,304 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: mss_volt_wrap.C,v 1.6 2013/09/23 20:27:13 jmcgill Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/ipl/fapi/wrapper/mss_volt_wrap.C,v $
+//------------------------------------------------------------------------------
+// *|
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+// *|
+// *! TITLE : mss_volt_wrap.C
+// *!
+// *! OWNER NAME : Jacob Sloat Email: jdsloat@us.ibm.com
+// *!
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include <prcdUtils.H>
+//#include <verifUtils.H>
+
+#include <croClientCapi.H>
+#include <ecmdClientCapi.H>
+#include <ecmdDataBuffer.H>
+#include <ecmdUtils.H>
+#include <ecmdSharedUtils.H>
+#include <fapi2.H>
+#include <fapi2ClientCapi.H>
+#include <fapi2SharedUtils.H>
+
+#include <p9c_mss_volt.H>
+
+
+//------------------------------------------------------------------------------
+// Function definitions
+//------------------------------------------------------------------------------
+
+// display help message
+void
+help()
+{
+ // procedure constants
+ std::string PROCEDURE = "mss_volt_wrap";
+ std::string REVISION = "$Revision: 1.6 $";
+
+ // build help message
+ char outstr[256];
+ snprintf(outstr, sizeof(outstr), "\nThis is the help text for the procedure %s (%s).\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+ ecmdOutput(" [-h] [-k#] [-n#] [-s#] [-p#] [-d] [-quiet] [-verif]\n");
+ ecmdOutput("\n");
+ ecmdOutput("Additional options:\n");
+ ecmdOutput(" -h Display this help message.\n");
+
+ ecmdOutput(" -k# Specify which cage to act on (default = 0).\n");
+ ecmdOutput(" -n# Specify which node to act on (default = 0).\n");
+ ecmdOutput(" -s# Specify which slot to act on (default = 0).\n");
+ ecmdOutput(" -p# Specify which chip position to act on (default = 0).\n");
+ ecmdOutput(" -quiet Suppress printing of eCMD DLL/procedure information (default = false).\n");
+ ecmdOutput(" -verif Run procedure in sim verification mode (default = false).\n");
+ return;
+}
+
+// main function
+int
+main(int argc, char* argv[])
+{
+ // procedure constants
+ const std::string PROCEDURE = "mss_volt_wrap";
+ const std::string REVISION = "$Revision: 1.6 $";
+
+ // from prcdUtils
+ extern bool GLOBAL_SIM_MODE;
+ extern bool GLOBAL_VERIF_MODE;
+
+ // flow/control variables
+ uint32_t rc = ECMD_SUCCESS;
+ fapi2::ReturnCode rc_fapi;
+ ecmdDllInfo DLLINFO;
+ ecmdLooperData node_looper;
+ ecmdChipTarget node_target;
+ char outstr[256];
+
+ // required parameters & optional flags
+
+ // load and initialize the eCMD Dll
+ // if left NULL, which DLL to load is determined by the ECMD_DLL_FILE
+ // environment variable if set to a specific value, the specified DLL
+ // will be loaded
+ rc = ecmdLoadDll("");
+
+ if (rc)
+ {
+ return rc;
+ }
+
+ do
+ {
+ // initalize FAPI extension
+ rc = fapi2InitExtension();
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing FAPI extension!\n");
+ break;
+ }
+
+ // establish if this is a simulation run or not
+ rc = ecmdQueryDllInfo(DLLINFO);
+
+ if (rc)
+ {
+ ecmdOutput("Error querying DLL!\n");
+ break;
+ }
+
+ if (DLLINFO.dllEnv == ECMD_DLL_ENV_SIM)
+ {
+ GLOBAL_SIM_MODE = true;
+ }
+
+ // show help message
+ if (ecmdParseOption(&argc, &argv, "-h"))
+ {
+ help();
+ break;
+ }
+
+
+ // run procedure in sim verification mode
+ if (ecmdParseOption(&argc, &argv, "-verif"))
+ {
+ GLOBAL_VERIF_MODE = true;
+ }
+
+ // parse out common eCMD args like -p0, -c0, -coe, etc..
+ // any found args will be removed from arg list upon return
+ rc = ecmdCommandArgs(&argc, &argv);
+
+ if (rc)
+ {
+ ecmdOutputError("Error parsing eCMD arguments\n");
+ break;
+ }
+
+ // unsupported arguments left over?
+ if (argc != 1)
+ {
+ ecmdOutputError("Unknown/unsupported arguments specified!\n");
+ help();
+ rc = ECMD_INVALID_ARGS;
+ break;
+ }
+
+ // print procedure information header
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ // print informational message
+ snprintf(outstr, sizeof(outstr), "Procedure %s: %s\n",
+ PROCEDURE.c_str(), REVISION.c_str());
+ ecmdOutput(outstr);
+
+ // always print the DLL info to the screen, unless in quiet mode
+ rc = ecmdDisplayDllInfo();
+
+ if (rc)
+ {
+ ecmdOutputError("Error displaying DLL info!");
+ break;
+ }
+ }
+
+ // configure looper to iterate over all nodes
+ node_target.cageState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.nodeState = ECMD_TARGET_FIELD_WILDCARD;
+ node_target.slotState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.posState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ node_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+ rc = ecmdConfigLooperInit(node_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, node_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing node looper!\n");
+ break;
+ }
+
+ // loop over specified configured nodes
+ while (ecmdConfigLooperNext(node_target, node_looper))
+ {
+ std::vector<ecmdChipTarget> ecmd_chip_targets;
+ std::vector<fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>> fapi_chip_targets;
+ ecmdLooperData cen_looper;
+ ecmdChipTarget cen_target;
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Processing %s\n",
+ ecmdWriteTarget(node_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ cen_target.chipType = "cen";
+ cen_target.chipTypeState = ECMD_TARGET_FIELD_VALID;
+
+ cen_target.cage = node_target.cage;
+ cen_target.node = node_target.node;
+
+ cen_target.cageState = ECMD_TARGET_FIELD_VALID;
+ cen_target.nodeState = ECMD_TARGET_FIELD_VALID;
+ cen_target.slotState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.posState = ECMD_TARGET_FIELD_WILDCARD;
+ cen_target.coreState = ECMD_TARGET_FIELD_UNUSED;
+ cen_target.threadState = ECMD_TARGET_FIELD_UNUSED;
+
+ rc = ecmdConfigLooperInit(cen_target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, cen_looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing chip looper!\n");
+ break;
+ }
+
+ // loop over configured positions inside current node
+ while(ecmdConfigLooperNext(cen_target, cen_looper))
+ {
+ ecmd_chip_targets.push_back(cen_target);
+ }
+
+ /*
+ for (std::vector<ecmdChipTarget>::iterator i = ecmd_chip_targets.begin();
+ i != ecmd_chip_targets.end();
+ i++)
+ {
+ fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> fapi_target(*i);
+ // ecmdTargetToFapiTarget(*i, fapi_target);
+ fapi_chip_targets.push_back(fapi_target);
+ }
+ */
+ for(const auto& target : ecmd_chip_targets)
+ {
+ // Setting up a fapi2::Target from an ecmdChipTarget and adding to vector
+ fapi_chip_targets.push_back ( fapi2::plat_target_handle_t(&target) );
+ }
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr), "Going to call %s on %s\n",
+ PROCEDURE.c_str(),
+ ecmdWriteTarget(cen_target).c_str());
+ ecmdOutput(outstr);
+ }
+
+ // invoke FAPI procedure core
+ FAPI_EXEC_HWP(rc_fapi,
+ p9c_mss_volt,
+ fapi_chip_targets);
+ rc = (uint32_t) rc_fapi;
+
+ if (rc)
+ {
+ snprintf(outstr, sizeof(outstr), "ERROR: %s FAPI call exited with bad return code = %s 0x%08x\n",
+ PROCEDURE.c_str(),
+ ecmdParseReturnCode(rc).c_str(), rc);
+ ecmdOutputError(outstr);
+ break;
+ }
+ }
+
+ if (rc)
+ {
+ break;
+ }
+ }
+ while(0);
+
+ ecmdUnloadDll();
+ return rc;
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.mk b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.mk
new file mode 100755
index 000000000..4f210c1a5
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.mk
@@ -0,0 +1,29 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_volt_wrap.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+WRAPPER=p9c_mss_volt_wrap
+$(WRAPPER)_USELIBS+=p9c_mss_volt
+$(WRAPPER)_DEPLIBS+=cen
+$(call BUILD_WRAPPER)
OpenPOWER on IntegriCloud