summaryrefslogtreecommitdiffstats
path: root/src/usr/hwpf/hwp/mc_config
diff options
context:
space:
mode:
authorThi Tran <thi@us.ibm.com>2014-11-13 13:46:21 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2014-12-13 10:47:21 -0600
commit1d730ba9e2d823e9690e6dcae168b0ccae85a948 (patch)
tree10e10e15879c6f072d31dfb3ad23fc1c747300f0 /src/usr/hwpf/hwp/mc_config
parent597e79a3055b155af20d6d64ade2fd2e95699954 (diff)
downloadtalos-hostboot-1d730ba9e2d823e9690e6dcae168b0ccae85a948.tar.gz
talos-hostboot-1d730ba9e2d823e9690e6dcae168b0ccae85a948.zip
SW284608: HWP Memory Throttle Calculation Efficiency and ISDIMM Throttle Support
CQ:SW284608 Change-Id: Ief2d91781ced462009c499564a8ffcbad5da8487 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14446 Reviewed-by: Michael D. Pardeik <pardeik@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: Thi N. Tran <thi@us.ibm.com> Tested-by: Thi N. Tran <thi@us.ibm.com> Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14471 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/hwpf/hwp/mc_config')
-rw-r--r--src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C422
-rw-r--r--src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C1602
2 files changed, 325 insertions, 1699 deletions
diff --git a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C
index 3cf18b247..21668b90e 100644
--- a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C
+++ b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C
@@ -22,7 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: mss_bulk_pwr_throttles.C,v 1.22 2014/06/02 13:10:53 pardeik Exp $
+// $Id: mss_bulk_pwr_throttles.C,v 1.28 2014/12/01 19:07:07 pardeik Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/
// centaur/working/procedures/ipl/fapi/mss_bulk_pwr_throttles.C,v $
//------------------------------------------------------------------------------
@@ -73,6 +73,24 @@
//------------------------------------------------------------------------------
// Version:| Author: | Date: | Comment:
//---------|----------|---------|-----------------------------------------------
+// 1.28 | pardeik |01-DEC-14| Gerrit review updates
+// | | | changed MAX_UTIL to max_util
+// | | | changed MIN_UTIL const to min_util float
+// | | | changed IDLE_UTIL const to idle_util float
+// 1.27 | pardeik |13-NOV-14| initialize l_channel_power_intercept and
+// | | | l_channel_power_slope to zero to prevent
+// | | | compile errors
+// 1.26 | pardeik |05-NOV-14| removed strings in trace statements
+// | | | changed FAPI_IMP to FAPI_INF
+// 1.25 | pardeik |31-OCT-14| change ISDIMM_MEMORY_THROTTLE_PERCENT to 65
+// 1.24 | pardeik |31-OCT-14| fixed equation using ISDIMM_MEMORY_THROTTLE_PERCENT
+// | | | use power instead of utilization for error check
+// | | | RC_MSS_NOT_ENOUGH_AVAILABLE_DIMM_POWER
+// 1.23 | pardeik |27-OCT-14| Change to not call mss_power_to_throttle_calc
+// | | | Make throttle determination more efficient
+// | | | Non Custom DIMMs use hardcoded values and do
+// | | | not use power curves for these
+// | | | Remove mss_throttle_to_power.H include
// 1.22 | pardeik |21-MAY-14| Removed section that adjusts power limit
// | | | (was not getting correct throttle values
// | | | to have channel pair power be under limit)
@@ -138,7 +156,6 @@
// My Includes
//------------------------------------------------------------------------------
#include <mss_bulk_pwr_throttles.H>
-#include <mss_throttle_to_power.H>
//------------------------------------------------------------------------------
// Includes
@@ -158,7 +175,6 @@ extern "C" {
const fapi::Target & i_target_mba
);
-
//------------------------------------------------------------------------------
// @brief mss_bulk_pwr_throttles(): This function determines the throttle values
// from a MBA channel pair power limit
@@ -171,45 +187,78 @@ extern "C" {
fapi::ReturnCode mss_bulk_pwr_throttles(const fapi::Target & i_target_mba
)
{
- fapi::ReturnCode rc;
-
- const char* procedure_name = "mss_bulk_pwr_throttles";
+ fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS;
- FAPI_IMP("*** Running %s on %s ***", procedure_name,
- i_target_mba.toEcmdString());
+ FAPI_INF("*** Running mss_bulk_pwr_throttles ***");
-// min utilization (percent of max) allowed for floor
- const float MIN_UTIL = 1;
+ const uint8_t MAX_NUM_PORTS = 2;
+ const uint8_t MAX_NUM_DIMMS = 2;
+ float idle_util = 0; // in percent
+ float 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
+ const uint32_t ISDIMM_MAX_DIMM_POWER = 1200; // cW, max ISDIMM power for no throttling
+ const uint32_t ISDIMM_MIN_DIMM_POWER = 800; // cW, min ISDIMM power for throttling
+ const 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 channel_pair_watt_target;
- uint32_t throttle_n_per_mba;
- uint32_t throttle_n_per_chip;
- uint32_t throttle_d;
- bool not_enough_available_power;
- bool channel_pair_throttle_done;
- float channel_pair_power;
- uint8_t custom_dimm;
+ uint32_t l_power_slope_array[MAX_NUM_PORTS][MAX_NUM_DIMMS];
+ uint32_t l_power_int_array[MAX_NUM_PORTS][MAX_NUM_DIMMS];
+ uint8_t l_dimm_ranks_array[MAX_NUM_PORTS][MAX_NUM_DIMMS];
+ uint8_t l_port;
+ uint8_t l_dimm;
+ float l_dimm_power_array_idle[MAX_NUM_PORTS][MAX_NUM_DIMMS];
+ float l_dimm_power_array_max[MAX_NUM_PORTS][MAX_NUM_DIMMS];
+ float l_channel_power_array_idle[MAX_NUM_PORTS];
+ float l_channel_power_array_max[MAX_NUM_PORTS];
+ uint8_t l_power_curve_percent_uplift;
+ uint8_t l_power_curve_percent_uplift_idle;
+ uint32_t l_max_dram_databus_util;
+ uint8_t l_num_mba_with_dimms;
+ uint8_t l_custom_dimm;
+ fapi::Target l_target_chip;
+ std::vector<fapi::Target> l_target_mba_array;
+ std::vector<fapi::Target> l_target_dimm_array;
+ uint8_t l_mba_index;
+ uint32_t l_throttle_d;
+ float l_channel_pair_power_idle;
+ float l_channel_pair_power_max;
+ uint32_t l_channel_pair_watt_target;
+ float l_utilization;
+ uint32_t l_number_of_dimms;
+ float l_channel_power_slope = 0;
+ float l_channel_power_intercept = 0;
+ uint32_t l_throttle_n_per_mba;
+ uint32_t l_throttle_n_per_chip;
+ uint32_t channel_pair_power;
uint32_t runtime_throttle_n_per_mba;
uint32_t runtime_throttle_n_per_chip;
- uint32_t runtime_throttle_d;
-// Get input attributes
- rc = FAPI_ATTR_GET(ATTR_EFF_CUSTOM_DIMM, &i_target_mba, custom_dimm);
+// get input attributes
+ rc = FAPI_ATTR_GET(ATTR_EFF_CUSTOM_DIMM, &i_target_mba, l_custom_dimm);
if (rc) {
FAPI_ERR("Error getting attribute ATTR_EFF_CUSTOM_DIMM");
return rc;
}
- rc = FAPI_ATTR_GET(ATTR_MSS_MEM_WATT_TARGET,
- &i_target_mba, channel_pair_watt_target);
+ rc = FAPI_ATTR_GET(ATTR_MRW_MAX_DRAM_DATABUS_UTIL,
+ NULL, l_max_dram_databus_util);
if (rc) {
- FAPI_ERR("Error getting attribute ATTR_MSS_MEM_WATT_TARGET");
+ FAPI_ERR("Error getting attribute ATTR_MRW_MAX_DRAM_DATABUS_UTIL");
return rc;
}
- rc = FAPI_ATTR_GET(ATTR_MRW_MEM_THROTTLE_DENOMINATOR, NULL, throttle_d);
+ rc = FAPI_ATTR_GET(ATTR_MRW_MEM_THROTTLE_DENOMINATOR, NULL, l_throttle_d);
if (rc) {
FAPI_ERR("Error getting attribute ATTR_MRW_MEM_THROTTLE_DENOMINATOR");
return rc;
}
+ rc = FAPI_ATTR_GET(ATTR_MSS_MEM_WATT_TARGET,
+ &i_target_mba, l_channel_pair_watt_target);
+ if (rc) {
+ FAPI_ERR("Error getting attribute ATTR_MSS_MEM_WATT_TARGET");
+ return rc;
+ }
rc = FAPI_ATTR_GET(ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_MBA,
&i_target_mba, runtime_throttle_n_per_mba);
if (rc) {
@@ -222,148 +271,287 @@ extern "C" {
FAPI_ERR("Error getting attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_CHIP");
return rc;
}
- rc = FAPI_ATTR_GET(ATTR_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR,
- &i_target_mba, runtime_throttle_d);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR");
- return rc;
- }
+// other attributes for custom dimms to get
+ if (l_custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES)
+ {
+ rc = FAPI_ATTR_GET(ATTR_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT,
+ NULL, l_power_curve_percent_uplift);
+ if (rc) {
+ FAPI_ERR("Error getting attribute ATTR_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT");
+ return rc;
+ }
+ rc = FAPI_ATTR_GET(ATTR_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT_IDLE,
+ NULL, l_power_curve_percent_uplift_idle);
+ if (rc) {
+ FAPI_ERR("Error getting attribute ATTR_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT_IDLE");
+ return rc;
+ }
+ rc = FAPI_ATTR_GET(ATTR_MSS_POWER_SLOPE,
+ &i_target_mba, l_power_slope_array);
+ if (rc) {
+ FAPI_ERR("Error getting attribute ATTR_MSS_POWER_SLOPE");
+ return rc;
+ }
+ rc = FAPI_ATTR_GET(ATTR_MSS_POWER_INT,
+ &i_target_mba, l_power_int_array);
+ if (rc) {
+ FAPI_ERR("Error getting attribute ATTR_MSS_POWER_INT");
+ return rc;
+ }
+ rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM,
+ &i_target_mba, l_dimm_ranks_array);
+ if (rc) {
+ FAPI_ERR("Error getting attribute ATTR_EFF_NUM_RANKS_PER_DIMM");
+ return rc;
+ }
+ }
-//------------------------------------------------------------------------------
-// THROTTLE SECTION
-//------------------------------------------------------------------------------
+// Maximum theoretical data bus utilization (percent of max) (for ceiling)
+// Comes from MRW value in c% - convert to %
+ float max_util = (float) l_max_dram_databus_util / 100;
-// Determine if the channel pair power for this MBA is over the limit when the
-// runtime memory throttle settings are used
-// If not over the limit, then use the runtime throttle settings (defined in
-// mss_eff_config_thermal)
-// If over limit, then increase throttle value until it is at or below limit
-// If unable to get power below limit, then call out an error
-
-// Start with the runtime throttle settings since we may have a thermal/power limit
- throttle_n_per_mba = runtime_throttle_n_per_mba;
- throttle_n_per_chip = runtime_throttle_n_per_chip;
-
-// calculate power and change throttle values in this while loop until limit has
-// been satisfied or throttles have reached the minimum limit
- not_enough_available_power = false;
- channel_pair_throttle_done = false;
- while (channel_pair_throttle_done == false)
+// determine the dimm power
+// For custom dimms, use the VPD power curve data
+ if (l_custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES)
{
- rc = mss_throttle_to_power_calc(
- i_target_mba,
- throttle_n_per_mba,
- throttle_n_per_chip,
- throttle_d,
- channel_pair_power
- );
- if (rc)
- {
- FAPI_ERR("Error (0x%x) calling mss_throttle_to_power_calc", static_cast<uint32_t>(rc));
+// get number of mba's with dimms
+// Get Centaur target for the given MBA
+ rc = fapiGetParentChip(i_target_mba, l_target_chip);
+ if (rc) {
+ FAPI_ERR("Error calling fapiGetParentChip");
return rc;
}
+// Get MBA targets from the parent chip centaur
+ rc = fapiGetChildChiplets(l_target_chip,
+ fapi::TARGET_TYPE_MBA_CHIPLET,
+ l_target_mba_array,
+ fapi::TARGET_STATE_PRESENT);
+ if (rc) {
+ FAPI_ERR("Error calling fapiGetChildChiplets");
+ return rc;
+ }
+ l_num_mba_with_dimms = 0;
+ for (l_mba_index=0; l_mba_index < l_target_mba_array.size(); l_mba_index++)
+ {
+ rc = fapiGetAssociatedDimms(l_target_mba_array[l_mba_index],
+ l_target_dimm_array,
+ fapi::TARGET_STATE_PRESENT);
+ if (rc) {
+ FAPI_ERR("Error calling fapiGetAssociatedDimms");
+ return rc;
+ }
+ if (l_target_dimm_array.size() > 0)
+ {
+ l_num_mba_with_dimms++;
+ }
+ }
-// compare channel pair power to mss_watt_target for channel and decrease
-// throttles if it is above this limit
-// throttle decrease will decrement throttle numerator by one
-// and recalculate power until utilization (N/M) reaches a lower limit
-
- if (channel_pair_power > channel_pair_watt_target)
+// 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_NUM_PORTS; l_port++)
{
-// check to see if dimm utilization is greater than the min utilization limit,
-// continue if it is, error if it is not
- if ((((float)throttle_n_per_chip * 100 * 4) / throttle_d) >
- MIN_UTIL)
+ l_channel_power_array_idle[l_port] = 0;
+ l_channel_power_array_max[l_port] = 0;
+ for (l_dimm=0; l_dimm < MAX_NUM_DIMMS; l_dimm++)
{
- if (throttle_n_per_chip > 1)
+// 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] + (idle_util / 100 * l_power_slope_array[l_port][l_dimm]) + l_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] + (max_util / 100 * l_power_slope_array[l_port][l_dimm]) + l_power_int_array[l_port][l_dimm];
+ }
+// Include any system uplift here too
+ if (l_dimm_power_array_idle[l_port][l_dimm] > 0)
{
- if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES)
- {
-// CDIMMs, use per chip throttling for any thermal or available power limits
- throttle_n_per_chip--;
- }
- else
- {
-// ISDIMMs, use per mba throttling for available power limit
-// per_mba throttling (ie. per dimm for ISDIMMs) will limit performance if all
-// traffic is sent to one dimm, so use the per_chip
- throttle_n_per_chip--;
- }
+ 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);
}
-// This was increment throttle_d++, but don't want to change the denominator since OCC does not set it.
-// Done if we reach this point (ie. not enough power)
- else
+ if (l_dimm_power_array_max[l_port][l_dimm] > 0)
{
- channel_pair_throttle_done = true;
- not_enough_available_power = true;
+ 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);
}
- FAPI_DBG("Throttle update [N_per_mba/N_per_chip/M %d/%d/%d]", throttle_n_per_mba, throttle_n_per_chip, throttle_d);
+// 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, idle_util, max_util, l_power_slope_array[l_port][l_dimm], l_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, min_util, 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) / ( (max_util / 100) - (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 > max_util)
+ {
+ l_utilization = 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 > (max_util / 100 * l_throttle_d / 4) )
+ {
+ l_throttle_n_per_mba = int((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
+ 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, 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
+ rc = fapiGetAssociatedDimms(i_target_mba,
+ l_target_dimm_array,
+ fapi::TARGET_STATE_PRESENT);
+ if (rc) {
+ FAPI_ERR("Error calling fapiGetAssociatedDimms");
+ return rc;
+ }
+ 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 = max_util;
+ 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 = min_util;
}
-// minimum utilization limit was reached for this throttle N/M value
else
{
-// Throttles can't be changed anymore (already at or below MIN_UTIL)
- channel_pair_throttle_done = true;
- not_enough_available_power = true;
+ l_utilization = max_util * (1 - (float)ISDIMM_MEMORY_THROTTLE_PERCENT / 100);
}
+ channel_pair_power = ISDIMM_MIN_DIMM_POWER * l_number_of_dimms;
}
-// channel pair power is less than limit, so keep existing throttles
else
{
- FAPI_INF("There is enough available memory power [Channel Pair Power %4.2f/%d cW]", channel_pair_power, channel_pair_watt_target);
- channel_pair_throttle_done = true;
+ // error case, available power less than allocated minimum dimm power
+ l_utilization = 0;
+ 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);
+
}
-// Set per_mba throttle to per_chip throttle if it is greater
-// This way, when OCC throttles using per_mba due to thermal reasons,
-// it has a higher chance of making an immediate impact
-// NOTE: If above throttle determination uses throttle_n_per_mba, then
-// we need to change this around
- if (throttle_n_per_mba > throttle_n_per_chip)
+// adjust the throttles to minimum utilization if needed
+ if (l_utilization < min_util)
{
- throttle_n_per_mba = throttle_n_per_chip;
+ l_throttle_n_per_mba = int(min_util / 100 * l_throttle_d / 4);
+ l_throttle_n_per_chip = l_throttle_n_per_mba * l_num_mba_with_dimms;
}
- FAPI_INF("Final Throttle Settings [N_per_mba/N_per_chip/M %d/%d/%d]", throttle_n_per_mba, throttle_n_per_chip, throttle_d);
+// 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_mba == 0))
+ {
+ l_throttle_n_per_mba = 1;
+ l_throttle_n_per_chip = l_throttle_n_per_mba * l_num_mba_with_dimms;
+ }
-//------------------------------------------------------------------------------
-// update output attributes
+// adjust the throttles to the MRW thermal limit throttles (ie. thermal/power limit less than available power)
+ if ( (l_throttle_n_per_mba > runtime_throttle_n_per_mba) ||
+ (l_throttle_n_per_chip > 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, runtime_throttle_n_per_mba, runtime_throttle_n_per_chip, l_throttle_d);
+ if (l_throttle_n_per_mba > runtime_throttle_n_per_mba) {
+ l_throttle_n_per_mba = runtime_throttle_n_per_mba;
+ }
+ if (l_throttle_n_per_chip > runtime_throttle_n_per_chip) {
+ l_throttle_n_per_chip = 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 == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES)
+ {
+ 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][Throttles %d/%d/%d]", l_channel_pair_watt_target, l_utilization, channel_pair_power, l_throttle_n_per_mba, l_throttle_n_per_chip, l_throttle_d);
+
+// Update output attributes
rc = FAPI_ATTR_SET(ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA,
- &i_target_mba, throttle_n_per_mba);
+ &i_target_mba, l_throttle_n_per_mba);
if (rc) {
FAPI_ERR("Error writing attribute ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA");
return rc;
}
rc = FAPI_ATTR_SET(ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP,
- &i_target_mba, throttle_n_per_chip);
+ &i_target_mba, l_throttle_n_per_chip);
if (rc) {
FAPI_ERR("Error writing attribute ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP");
return rc;
}
rc = FAPI_ATTR_SET(ATTR_MSS_MEM_THROTTLE_DENOMINATOR,
- &i_target_mba, throttle_d);
+ &i_target_mba, l_throttle_d);
if (rc) {
FAPI_ERR("Error writing attribute ATTR_MSS_MEM_THROTTLE_DENOMINATOR");
return rc;
}
+ rc = FAPI_ATTR_SET(ATTR_MSS_CHANNEL_PAIR_MAXPOWER,
+ &i_target_mba, channel_pair_power);
+ if (rc) {
+ FAPI_ERR("Error writing attribute ATTR_MSS_CHANNEL_PAIR_MAXPOWER");
+ return rc;
+ }
- if (not_enough_available_power == true)
+// Check to see if there is not enough available power at min_util or higher
+ if (channel_pair_power > l_channel_pair_watt_target)
{
-// return error for TMGT to handle if there is not enough available memory power
-// at the minimum utilization throttle setting
- FAPI_ERR("Not enough available memory power [Channel Pair Power %4.2f/%d cW]", channel_pair_power, channel_pair_watt_target);
- const float & PAIR_POWER = channel_pair_power;
- const uint32_t & PAIR_WATT_TARGET = channel_pair_watt_target;
+ FAPI_ERR("Not enough available memory power [Channel Pair Power %d/%d cW]", channel_pair_power, l_channel_pair_watt_target);
+ const uint32_t & PAIR_POWER = channel_pair_power;
+ const uint32_t & PAIR_WATT_TARGET = l_channel_pair_watt_target;
const fapi::Target & MEM_MBA = i_target_mba;
FAPI_SET_HWP_ERROR(rc, RC_MSS_NOT_ENOUGH_AVAILABLE_DIMM_POWER);
return rc;
+
}
- FAPI_IMP("*** %s COMPLETE on %s ***", procedure_name,
- i_target_mba.toEcmdString());
+ FAPI_INF("*** mss_bulk_pwr_throttles COMPLETE ***");
return rc;
+
}
} //end extern C
diff --git a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C
index 5a2fb48f7..a86cf1d0e 100644
--- a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C
+++ b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C
@@ -22,7 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: mss_eff_config_thermal.C,v 1.27 2014/06/02 13:11:01 pardeik Exp $
+// $Id: mss_eff_config_thermal.C,v 1.29 2014/11/06 21:05:54 pardeik Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/
// centaur/working/procedures/ipl/fapi/mss_eff_config_thermal.C,v $
//------------------------------------------------------------------------------
@@ -55,6 +55,14 @@
//------------------------------------------------------------------------------
// Version:| Author: | Date: | Comment:
//---------|----------|---------|-----------------------------------------------
+// 1.29 | pardeik |06-NOV-14| removed strings in trace statements
+// | | | changed FAPI_IMP to FAPI_INF
+// | | | removed unused constants
+// 1.28 | pardeik |28-OCT-14| Updates for non custom dimm power procedure
+// | | | Removed mss_eff_config_thermal_term
+// | | | Removed mss_eff_config_thermal_get_wc_term
+// | | | Removed mss_eff_config_thermal_get_cen_drv_value
+// | | | Updates to mss_eff_config_thermal_powercurve
// 1.27 | pardeik |22-MAY-14| Removed attribute update section not needed
// | | | Initialize runtime throttle attributes before
// | | | calling bulk_pwr_throttles
@@ -142,18 +150,9 @@ TODO ITEMS:
const uint8_t NUM_PORTS = 2;
const uint8_t NUM_DIMMS = 2;
const uint8_t NUM_RANKS = 4;
-const uint32_t ISDIMM_POWER_SLOPE_DEFAULT = 940;
-const uint32_t ISDIMM_POWER_INT_DEFAULT = 900;
// Only use values here (not any valid bits or flag bits)
const uint32_t CDIMM_POWER_SLOPE_DEFAULT = 0x0240;
const uint32_t CDIMM_POWER_INT_DEFAULT = 0x00CE;
-// These are based on what was used when ISDIMM power values were taken from the
-// power calculator
-const uint8_t IDLE_DIMM_UTILIZATION = 0;
-const uint8_t ACTIVE_DIMM_UTILIZATION = 70;
-const uint8_t DATA_BUS_READ_PERCENT = 66;
-const uint8_t DATA_BUS_WRITE_PERCENT = 34;
-
extern "C" {
@@ -174,43 +173,6 @@ extern "C" {
const fapi::Target & i_target_mba
);
- fapi::ReturnCode mss_eff_config_thermal_term
- (
- const char nom_or_wc_term[4],
- uint8_t i_port,
- uint8_t i_dimm,
- uint8_t i_rank,
- uint32_t i_dimm_voltage,
- uint8_t i_dram_width,
- uint8_t i_dram_tdqs,
- uint8_t i_dimm_type,
- uint8_t i_stack_type,
- uint8_t i_dimm_master_ranks_array[NUM_PORTS][NUM_DIMMS],
- uint8_t i_dimm_ranks_configed_array[NUM_PORTS][NUM_DIMMS],
- uint8_t i_dimm_dram_ron[NUM_PORTS][NUM_DIMMS],
- uint8_t i_dimm_rank_odt_rd[NUM_PORTS][NUM_DIMMS][NUM_RANKS],
- uint8_t i_dimm_rank_odt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS],
- uint8_t i_dram_rtt_nom[NUM_PORTS][NUM_DIMMS][NUM_RANKS],
- uint8_t i_dram_rtt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS],
- uint8_t i_cen_dq_dqs_rcv_imp[NUM_PORTS],
- uint8_t i_cen_dq_dqs_drv_imp[NUM_PORTS],
- float &o_dimm_power_adder_termination
- );
-
- fapi::ReturnCode mss_eff_config_thermal_get_wc_term
- (
- const fapi::Target &i_target_mba,
- uint8_t i_port,
- uint8_t &o_cen_dq_dqs_rcv_imp_wc,
- uint8_t &o_cen_dq_dqs_drv_imp_wc
- );
-
- fapi::ReturnCode mss_eff_config_thermal_get_cen_drv_value
- (
- uint8_t i_cen_dq_dqs_drv_imp,
- uint8_t &o_cen_dq_dqs_drv_imp
- );
-
//------------------------------------------------------------------------------
// @brief mss_eff_config_thermal(): This function determines the
@@ -225,9 +187,7 @@ extern "C" {
{
fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS;
- const char* procedure_name = "mss_eff_config_thermal";
-
- FAPI_IMP("*** Running %s on %s ***", procedure_name,
+ FAPI_INF("*** Running mss_eff_config_thermal on %s ***",
i_target_mba.toEcmdString());
rc = mss_eff_config_thermal_powercurve(i_target_mba);
@@ -244,7 +204,7 @@ extern "C" {
}
- FAPI_IMP("*** %s COMPLETE on %s ***", procedure_name,
+ FAPI_INF("*** mss_eff_config_thermal COMPLETE on %s ***",
i_target_mba.toEcmdString());
return rc;
}
@@ -262,126 +222,24 @@ extern "C" {
{
fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS;
- const char* procedure_name = "mss_eff_config_thermal_powercurve";
-
- FAPI_IMP("*** Running %s on %s ***", procedure_name,
+ FAPI_INF("*** Running mss_eff_config_thermal_powercurve on %s ***",
i_target_mba.toEcmdString());
- enum
- {
- DDR3 = fapi::ENUM_ATTR_EFF_DRAM_GEN_DDR3,
- DDR4 = fapi::ENUM_ATTR_EFF_DRAM_GEN_DDR4,
- X4 = fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X4,
- X8 = fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X8,
- };
-
-// Structure types for the table that holds dimm power and adjustment values
-// that will be used
-
- struct dimm_power_t
- {
- uint32_t idle;
- uint32_t active;
- };
- struct dimm_type_t
- {
- int32_t udimm;
- int32_t lrdimm;
- int32_t rdimm;
- };
- struct power_data_t
- {
- uint8_t dram_generation;
- uint8_t dram_width;
- uint8_t dimm_ranks;
- dimm_power_t rank_power;
- dimm_type_t dimm_type_adder;
- int32_t dimm_voltage_base;
- int32_t dimm_frequency_base;
- };
-
-//------------------------------------------------------------------------------
-// Master Ranks column uses the values in the same table entry for the number of
-// master ranks specified. Default is to have it use same power for each master
-// rank, so that is why master ranks = 1. If we need to separate power based on
-// number of master ranks, then have the table setup for descending master rank
-// values. We always need an entry for master ranks of 1. Table lookup will
-// stop after first matching entry is found (DRAM Generation, DRAM Width, and
-// Master Ranks = dimm_master_ranks_array OR 1)
-//
-// These values need to cover the power of all IBM dimms. Values will come from
-// the power calculator and be verified by hardware measurements.
-//
-// Base Voltage and Base Frequency values need to match what mss_volt/mss_freq
-// uses.
-//
-// DRAM DRAM Master RankPower DIMMType Base Base
-// Gen Width Ranks idle,full Adder Volt Freq
-// cW U,LR,RDIMM mV MHz
-//------------------------------------------------------------------------------
-// TODO: Update ISDIMM power table values after measurements have been taken
- power_data_t power_table[] =
- {
- { DDR3, X4, 1, { 70,373}, {0,93,104}, 1350, 1066 },
- { DDR3, X8, 1, { 52,300}, {0,93,104}, 1350, 1066 },
- { DDR4, X4, 1, { 70,373}, {0,93,104}, 1350, 1066 },
- { DDR4, X8, 1, { 52,300}, {0,93,104}, 1350, 1066 },
- };
-
// other variables used in this function
fapi::Target target_chip;
- std::vector<fapi::Target> target_dimm_array;
uint8_t port;
uint8_t dimm;
- uint8_t mba_port;
- uint8_t mba_dimm;
- uint8_t rank;
- uint8_t entry;
- uint8_t dimm_type;
- uint8_t stack_type[NUM_PORTS][NUM_DIMMS];
uint8_t custom_dimm;
uint8_t dimm_ranks_array[NUM_PORTS][NUM_DIMMS];
- uint32_t power_table_size;
uint32_t power_slope_array[NUM_PORTS][NUM_DIMMS];
uint32_t power_int_array[NUM_PORTS][NUM_DIMMS];
uint32_t power_slope2_array[NUM_PORTS][NUM_DIMMS];
uint32_t power_int2_array[NUM_PORTS][NUM_DIMMS];
- uint8_t found_entry_in_table;
- uint8_t dram_width;
- uint8_t dram_tdqs;
- uint8_t dram_gen;
- uint32_t dimm_voltage;
- uint32_t dimm_frequency;
- uint8_t dimm_ranks_configed_array[NUM_PORTS][NUM_DIMMS];
- uint8_t dimm_master_ranks_array[NUM_PORTS][NUM_DIMMS];
- int32_t dimm_power_adder_type;
- float dimm_power_multiplier_volt;
- float dimm_power_mulitiplier_freq;
- float dimm_idle_power;
- float dimm_active_power;
- float dimm_power_adder_termination = 0;
- float dimm_power_adder_termination_largest = 0;
- uint8_t dimm_rank_odt_rd[NUM_PORTS][NUM_DIMMS][NUM_RANKS];
- uint8_t dimm_rank_odt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS];
- uint8_t dimm_dram_ron[NUM_PORTS][NUM_DIMMS];
- uint8_t cen_dq_dqs_rcv_imp[NUM_PORTS];
- uint8_t cen_dq_dqs_drv_imp[NUM_PORTS];
- float dimm_power_adder_termination_wc = 0;
- float dimm_power_adder_termination_largest_wc = 0;
- uint8_t cen_dq_dqs_rcv_imp_wc[NUM_PORTS];
- uint8_t cen_dq_dqs_drv_imp_wc[NUM_PORTS];
- uint8_t num_dimms_on_port;
- uint8_t dram_rtt_nom[NUM_PORTS][NUM_DIMMS][NUM_RANKS];
- uint8_t dram_rtt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS];
- char dram_gen_str[4];
- uint8_t dimm_number_registers[NUM_PORTS][NUM_DIMMS];
- uint8_t dimm_index;
uint32_t cdimm_master_power_slope;
uint32_t cdimm_master_power_intercept;
uint32_t cdimm_supplier_power_slope;
uint32_t cdimm_supplier_power_intercept;
- power_table_size = (sizeof(power_table))/(sizeof(power_data_t));
//------------------------------------------------------------------------------
// Get input attributes
@@ -394,97 +252,17 @@ extern "C" {
return rc;
}
- rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_GEN, &i_target_mba, dram_gen);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_DRAM_GEN");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_TYPE, &i_target_mba, dimm_type);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_DIMM_TYPE");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_STACK_TYPE, &i_target_mba, stack_type);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_STACK_TYPE");
- return rc;
- }
rc = FAPI_ATTR_GET(ATTR_EFF_CUSTOM_DIMM, &i_target_mba, custom_dimm);
if (rc) {
FAPI_ERR("Error getting attribute ATTR_EFF_CUSTOM_DIMM");
return rc;
}
- rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target_mba, dram_width);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_DRAM_WIDTH");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_TDQS, &i_target_mba, dram_tdqs);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_DRAM_TDQS");
- return rc;
- }
rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM,
&i_target_mba, dimm_ranks_array);
if (rc) {
FAPI_ERR("Error getting attribute ATTR_EFF_NUM_RANKS_PER_DIMM");
return rc;
}
- rc = FAPI_ATTR_GET(ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM,
- &i_target_mba, dimm_master_ranks_array);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_RANKS_CONFIGED,
- &i_target_mba, dimm_ranks_configed_array);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_DIMM_RANKS_CONFIGED");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_VPD_DRAM_RON, &i_target_mba, dimm_dram_ron);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_VPD_DRAM_RON");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_VPD_ODT_RD, &i_target_mba, dimm_rank_odt_rd);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_VPD_ODT_RD");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_VPD_ODT_WR, &i_target_mba, dimm_rank_odt_wr);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_VPD_ODT_WR");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_CEN_RCV_IMP_DQ_DQS,
- &i_target_mba, cen_dq_dqs_rcv_imp);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_CEN_RCV_IMP_DQ_DQS");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_CEN_DRV_IMP_DQ_DQS,
- &i_target_mba, cen_dq_dqs_drv_imp);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_CEN_DRV_IMP_DQ_DQS");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_VPD_DRAM_RTT_NOM, &i_target_mba, dram_rtt_nom);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_VPD_DRAM_RTT_NOM");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_VPD_DRAM_RTT_WR, &i_target_mba, dram_rtt_wr);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_VPD_DRAM_RTT_WR");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_NUM_DROPS_PER_PORT,
- &i_target_mba, num_dimms_on_port);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_NUM_DROPS_PER_PORT");
- return rc;
- }
// Only get power curve values for custom dimms to prevent errors
if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES)
{
@@ -515,172 +293,12 @@ extern "C" {
}
}
-// Get voltage and frequency attributes
- rc = FAPI_ATTR_GET(ATTR_MSS_VOLT, &target_chip, dimm_voltage);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_MSS_VOLT");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_MSS_FREQ, &target_chip, dimm_frequency);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_MSS_FREQ");
- return rc;
- }
-
-// get any attributes from DIMM SPD
- if (
- (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_NO)
- && (dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM)
- )
- {
- rc = fapiGetAssociatedDimms(i_target_mba, target_dimm_array,
- fapi::TARGET_STATE_PRESENT);
- if (rc) {
- FAPI_ERR("Error from fapiGetAssociatedDimms");
- return rc;
- }
- for (dimm_index=0;
- dimm_index < target_dimm_array.size();
- dimm_index++)
- {
- rc = FAPI_ATTR_GET(ATTR_MBA_PORT,
- &target_dimm_array[dimm_index], port);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_MBA_PORT");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_MBA_DIMM,
- &target_dimm_array[dimm_index], dimm);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_MBA_DIMM");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_SPD_NUM_OF_REGISTERS_USED_ON_RDIMM,
- &target_dimm_array[dimm_index],
- dimm_number_registers[port][dimm]);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_SPD_NUM_OF_REGISTERS_USED_ON_RDIMM");
- return rc;
- }
- }
- }
-
-
-// determine worst case termination settings here for ISDIMMs (to be used later)
- if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_NO)
- {
-// get worst case termination values that will be used
-// Only look at Centaur DQ/DQS Driver and Receiver termination settings
-// Note that the DRAM rtt_nom, rtt_wr, and ron will not be allowed to change,
-// all these will stay at the nominal settings
- for (port=0; port < NUM_PORTS; port++)
- {
- rc = mss_eff_config_thermal_get_wc_term
- (
- i_target_mba,
- port,
- cen_dq_dqs_rcv_imp_wc[port],
- cen_dq_dqs_drv_imp_wc[port]
- );
- if (rc)
- {
- FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_get_wc_term", static_cast<uint32_t>(rc));
- return rc;
- }
- }
- }
-
//------------------------------------------------------------------------------
// Power Curve Determination
//------------------------------------------------------------------------------
// Iterate through the MBA ports to get power slope/intercept values
for (port=0; port < NUM_PORTS; port++)
{
-// Get termination power for ISDIMM
- if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_NO)
- {
- dimm_power_adder_termination_largest=0;
- dimm_power_adder_termination_largest_wc=0;
-
-// iterate through the dimms on each port to determine termination power to use
- for (dimm=0; dimm < NUM_DIMMS; dimm++)
- {
-// calculate the effective net termination for each rank
- for (rank=0; rank < NUM_RANKS; rank++)
- {
-// nominal termination
- rc = mss_eff_config_thermal_term
- (
- "NOM",
- port,
- dimm,
- rank,
- dimm_voltage,
- dram_width,
- dram_tdqs,
- dimm_type,
- stack_type[port][dimm],
- dimm_master_ranks_array,
- dimm_ranks_configed_array,
- dimm_dram_ron,
- dimm_rank_odt_rd,
- dimm_rank_odt_wr,
- dram_rtt_nom,
- dram_rtt_wr,
- cen_dq_dqs_rcv_imp,
- cen_dq_dqs_drv_imp,
- dimm_power_adder_termination
- );
- if (rc)
- {
- FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_term", static_cast<uint32_t>(rc));
- return rc;
- }
- if (dimm_power_adder_termination >
- dimm_power_adder_termination_largest)
- {
- dimm_power_adder_termination_largest =
- dimm_power_adder_termination;
- }
-
-// worst case termination
- rc = mss_eff_config_thermal_term
- (
- "WC",
- port,
- dimm,
- rank,
- dimm_voltage,
- dram_width,
- dram_tdqs,
- dimm_type,
- stack_type[port][dimm],
- dimm_master_ranks_array,
- dimm_ranks_configed_array,
- dimm_dram_ron,
- dimm_rank_odt_rd,
- dimm_rank_odt_wr,
- dram_rtt_nom,
- dram_rtt_wr,
- cen_dq_dqs_rcv_imp_wc,
- cen_dq_dqs_drv_imp_wc,
- dimm_power_adder_termination_wc
- );
- if (rc)
- {
- FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_term", static_cast<uint32_t>(rc));
- return rc;
- }
- if (dimm_power_adder_termination_wc >
- dimm_power_adder_termination_largest_wc)
- {
- dimm_power_adder_termination_largest_wc =
- dimm_power_adder_termination_wc;
- }
- }
- }
- }
-
// iterate through the dimms on each port again to determine power slope and
// intercept
for (dimm=0; dimm < NUM_DIMMS; dimm++)
@@ -760,213 +378,9 @@ extern "C" {
}
FAPI_DBG("CDIMM Power [P%d:D%d][SLOPE=%d:INT=%d cW][SLOPE2=%d:INT2=%d cW]", port, dimm, power_slope_array[port][dimm], power_int_array[port][dimm], power_slope2_array[port][dimm], power_int2_array[port][dimm]);
}
-// ISDIMM power slope/intercept will come from equation
- else
- {
-// Get the dimm power from table and add on any adjustments (if not found in
-// table - should never happen - then default values will be used)
- power_slope_array[port][dimm] =
- ISDIMM_POWER_SLOPE_DEFAULT;
- power_int_array[port][dimm] = ISDIMM_POWER_INT_DEFAULT;
-
- found_entry_in_table = 0;
- for (entry = 0; entry < power_table_size; entry++)
- {
- if (
- (power_table[entry].dram_generation == dram_gen)
- &&
- (power_table[entry].dram_width == dram_width)
- &&
- ((power_table[entry].dimm_ranks ==
- dimm_master_ranks_array[port][dimm]) ||
- (power_table[entry].dimm_ranks == 1))
- )
- {
-// get adder for dimm type
- if (dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM)
- {
- dimm_power_adder_type =
- power_table[entry].dimm_type_adder.udimm;
- }
- else if (dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM)
- {
- dimm_power_adder_type =
- power_table[entry].dimm_type_adder.lrdimm;
- }
- else // RDIMM
- {
- dimm_power_adder_type =
- power_table[entry].dimm_type_adder.rdimm;
- }
-
-
- if (dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) {
- dimm_power_adder_type =
- dimm_power_adder_type *
- dimm_number_registers[port][dimm];
- }
-
-// get adder for dimm voltage
- dimm_power_multiplier_volt =
- (
- (float(dimm_voltage) /
- power_table[entry].dimm_voltage_base)
- *
- (float(dimm_voltage) /
- power_table[entry].dimm_voltage_base)
- );
-// get adder for dimm frequency
- dimm_power_mulitiplier_freq =
- (float(dimm_frequency) /
- power_table[entry].dimm_frequency_base);
-// get adder for termination using equation (in cW)
- dimm_power_adder_termination =
- dimm_power_adder_termination_largest * 100;
- dimm_power_adder_termination_wc =
- dimm_power_adder_termination_largest_wc * 100;
-// add up power for each dimm on channel and divide by number of dimms to get an
-// average power for each dimm
-// calculate idle and active dimm power (active power includes worst case
-// termination power)
- dimm_idle_power =
- (
- (float(
- (
- (
- power_table[entry].rank_power.idle
- *
- (
- dimm_master_ranks_array[port][dimm]
- + (dimm_ranks_array[port][dimm] -
- dimm_master_ranks_array
- [port][dimm])
- ) + dimm_power_adder_type
- )
- * (dimm_power_multiplier_volt)
- * (dimm_power_mulitiplier_freq)
- )
- *
- num_dimms_on_port
- )
- / (num_dimms_on_port)
- )
- );
-//------------------------------------------------------------------------------
- dimm_active_power =
- (
- (float(
- (
- (
- (power_table[entry].rank_power.idle
- *
- (
- dimm_master_ranks_array[port][dimm]
- +
- (
- dimm_ranks_array[port][dimm] -
- dimm_master_ranks_array
- [port][dimm]
- )
- )
- +
- (
- power_table[entry].rank_power.active
- -
- power_table[entry].rank_power.idle
- )
- )
- +
- dimm_power_adder_type
- )
- * (dimm_power_multiplier_volt)
- * (dimm_power_mulitiplier_freq)
- )
- * num_dimms_on_port -
- (power_table[entry].rank_power.active
- - power_table[entry].rank_power.idle)
- * (num_dimms_on_port - 1)
- + dimm_power_adder_termination
- + (dimm_power_adder_termination_wc -
- dimm_power_adder_termination)
- )
- /
- (num_dimms_on_port)
- )
- );
-//------------------------------------------------------------------------------
-// calculate dimm power slope and intercept (add on 0.5 so value is effectively
-// rounded to nearest integer)
- power_slope_array[port][dimm] =
- int(
- (dimm_active_power - dimm_idle_power) /
- (float(ACTIVE_DIMM_UTILIZATION -
- IDLE_DIMM_UTILIZATION) / 100)
- + 0.5
- );
- power_int_array[port][dimm] =
- int(dimm_idle_power + 0.5);
- power_slope2_array[port][dimm] =
- power_slope_array[port][dimm];
- power_int2_array[port][dimm] =
- power_int_array[port][dimm];
- if (power_table[entry].dram_generation == DDR3)
- {
- sprintf(dram_gen_str, "DDR3");
- }
- if (power_table[entry].dram_generation == DDR4)
- {
- sprintf(dram_gen_str, "DDR4");
- }
-
- found_entry_in_table = 1;
- FAPI_DBG("FOUND ENTRY: GEN=%s WIDTH=X%d RANK=%d IDLE(%d%%)=%d ACTIVE(%d%%)=%d ADDER[TYPE=%d WCTERM=%4.2f] Multiplier[VOLT=%4.2f FREQ=%4.2f]", dram_gen_str, power_table[entry].dram_width, power_table[entry].dimm_ranks, IDLE_DIMM_UTILIZATION, power_table[entry].rank_power.idle, ACTIVE_DIMM_UTILIZATION, power_table[entry].rank_power.active, dimm_power_adder_type, dimm_power_adder_termination_wc, dimm_power_multiplier_volt, dimm_power_mulitiplier_freq);
- FAPI_DBG("ISDIMM Power [P%d:D%d][%s:X%d:R%d/%d:%d:%d][IDLE(%d%%)=%4.2f:ACTIVE(%d%%)=%4.2f cW][SLOPE=%d:INT=%d cW]", port, dimm, dram_gen_str, power_table[entry].dram_width, dimm_master_ranks_array[port][dimm], (dimm_ranks_array[port][dimm] - dimm_master_ranks_array[port][dimm]), dimm_voltage, dimm_frequency, IDLE_DIMM_UTILIZATION, dimm_idle_power, ACTIVE_DIMM_UTILIZATION, dimm_active_power, power_slope_array[port][dimm], power_int_array[port][dimm]);
- FAPI_DBG("ISDIMM Power [P%d:D%d][SLOPE=%d:INT=%d cW][SLOPE2=%d:INT2=%d cW]", port, dimm, power_slope_array[port][dimm], power_int_array[port][dimm], power_slope2_array[port][dimm], power_int2_array[port][dimm]);
- break;
- }
-
- }
-//------------------------------------------------------------------------------
- if (found_entry_in_table == 0)
- {
-
- FAPI_ERR("Failed to Find DIMM Power Values on %s. Default values will be used [P%d:D%d][Slope=%d:INT=%d cW]", i_target_mba.toEcmdString(), port, dimm, power_slope_array[port][dimm], power_int_array[port][dimm]);
-
-// get dimm target, we should always find a valid dimm target from this
-// since we have ranks present on this dimm if we are here in the code
- for (dimm_index=0;
- dimm_index < target_dimm_array.size();
- dimm_index++)
- {
- rc = FAPI_ATTR_GET
- (ATTR_MBA_PORT,
- &target_dimm_array[dimm_index], mba_port);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_MBA_PORT");
- return rc;
- }
- rc = FAPI_ATTR_GET
- (ATTR_MBA_DIMM,
- &target_dimm_array[dimm_index], mba_dimm);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_MBA_DIMM");
- return rc;
- }
- if ( (mba_port == port) && (mba_dimm == dimm)) {
- break;
- }
- }
- const fapi::Target & MEM_DIMM =
- target_dimm_array[dimm_index];
- uint32_t FFDC_DATA_1 = dram_gen;
- uint32_t FFDC_DATA_2 = dram_width;
- uint8_t FFDC_DATA_3 =
- dimm_master_ranks_array[port][dimm];
- FAPI_SET_HWP_ERROR
- (rc, RC_MSS_DIMM_NOT_FOUND_IN_POWER_TABLE);
- if (rc) fapiLogError(rc);
- }
- }
+// 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.
}
}
}
@@ -997,7 +411,7 @@ extern "C" {
return rc;
}
- FAPI_IMP("*** %s COMPLETE on %s ***", procedure_name,
+ FAPI_INF("*** mss_eff_config_thermal_powercurve COMPLETE on %s ***",
i_target_mba.toEcmdString());
return rc;
}
@@ -1015,9 +429,7 @@ extern "C" {
{
fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS;
- const char* procedure_name = "mss_eff_config_thermal_throttles";
-
- FAPI_IMP("*** Running %s on %s ***", procedure_name,
+ FAPI_INF("*** Running mss_eff_config_thermal_throttles on %s ***",
i_target_mba.toEcmdString());
// variables used in this function
@@ -1078,8 +490,6 @@ extern "C" {
return rc;
}
-
-
// 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 (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES)
@@ -1180,7 +590,6 @@ extern "C" {
return rc;
}
-
// Call the procedure function that takes a channel pair power limit and
// converts it to throttle values
@@ -1191,6 +600,8 @@ extern "C" {
return rc;
}
+ FAPI_INF("MRW Power/Thermal Limit %d. Throttles [%d/%d/%d].", channel_pair_thermal_power_limit, runtime_throttle_n_per_mba, runtime_throttle_n_per_chip, runtime_throttle_d);
+
// 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)
rc = FAPI_ATTR_GET(ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA,
@@ -1248,982 +659,9 @@ extern "C" {
return rc;
}
- FAPI_IMP("*** %s COMPLETE on %s ***", procedure_name,
+ FAPI_INF("*** mss_eff_config_thermal_throttles COMPLETE on %s ***",
i_target_mba.toEcmdString());
return rc;
}
-//------------------------------------------------------------------------------
-// @brief mss_eff_config_thermal_term(): This function calculates the data bus
-// termination power
-//
-// @param[in] const char i_nom_or_wc_term[4]: description of what is being
-// calculated (ie. NOM or WC)
-// @param[in] uint8_t i_port: MBA port being worked on
-// @param[in] uint8_t i_dimm: DIMM being worked on
-// @param[in] uint8_t i_rank: Rank being worked on
-// @param[in] uint32_t i_dimm_voltage: DIMM Voltage
-// @param[in] uint8_t i_dram_width: DRAM Width
-// @param[in] uint8_t i_dram_tdqs: DRAM TDQS enable/disable
-// @param[in] uint8_t i_dimm_type: DIMM Type
-// @param[in] uint8_t i_stack_type: DRAM Stack Type
-// @param[in] uint8_t i_dimm_master_ranks_array: Number of Master Ranks
-// @param[in] uint8_t i_dimm_ranks_configed_array[NUM_PORTS][NUM_DIMMS]:
-// Master Ranks configured
-// @param[in] uint8_t i_dimm_dram_ron[NUM_PORTS][NUM_DIMMS]: DRAM RON driver
-// impedance
-// @param[in] uint8_t i_dimm_rank_odt_rd[NUM_PORTS][NUM_DIMMS][NUM_RANKS]:
-// Read ODT
-// @param[in] uint8_t i_dimm_rank_odt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS]:
-// Write ODT
-// @param[in] uint8_t i_dram_rtt_nom[NUM_PORTS][NUM_DIMMS][NUM_RANKS]: DRAM
-// RTT NOM
-// @param[in] uint8_t i_dram_rtt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS]: DRAM
-// RTT WR
-// @param[in] uint8_t i_cen_dq_dqs_rcv_imp[NUM_PORTS]: Centaur DQ/DQS
-// receiver impedance
-// @param[in] uint8_t i_cen_dq_dqs_drv_imp[NUM_PORTS]: Centaur DQ/DQS driver
-// impedance
-// @param[out] float &o_dimm_power_adder_termination: Termination Power
-// Calculated in Watts
-//
-// @return fapi::ReturnCode
-//------------------------------------------------------------------------------
-
- fapi::ReturnCode mss_eff_config_thermal_term
- (
- const char i_nom_or_wc_term[4],
- uint8_t i_port,
- uint8_t i_dimm,
- uint8_t i_rank,
- uint32_t i_dimm_voltage,
- uint8_t i_dram_width,
- uint8_t i_dram_tdqs,
- uint8_t i_dimm_type,
- uint8_t i_stack_type,
- uint8_t i_dimm_master_ranks_array[NUM_PORTS][NUM_DIMMS],
- uint8_t i_dimm_ranks_configed_array[NUM_PORTS][NUM_DIMMS],
- uint8_t i_dimm_dram_ron[NUM_PORTS][NUM_DIMMS],
- uint8_t i_dimm_rank_odt_rd[NUM_PORTS][NUM_DIMMS][NUM_RANKS],
- uint8_t i_dimm_rank_odt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS],
- uint8_t i_dram_rtt_nom[NUM_PORTS][NUM_DIMMS][NUM_RANKS],
- uint8_t i_dram_rtt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS],
- uint8_t i_cen_dq_dqs_rcv_imp[NUM_PORTS],
- uint8_t i_cen_dq_dqs_drv_imp[NUM_PORTS],
- float &o_dimm_power_adder_termination
- )
- {
- fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS;
-
- const char* procedure_name = "mss_eff_config_thermal_term";
-
- FAPI_IMP("*** Running %s ***", procedure_name);
-
- uint8_t number_nets_term_rd;
- uint8_t number_nets_term_wr;
- uint8_t ma0odt01_dimm;
- uint8_t ma1odt01_dimm;
- uint8_t ma0odt0_rank;
- uint8_t ma0odt1_rank;
- uint8_t ma1odt0_rank;
- uint8_t ma1odt1_rank;
- uint8_t rank_mask;
- float eff_term_rd;
- float eff_net_term_rd;
- float term_odt_mult_rd;
- float eff_term_wr;
- float eff_net_term_wr;
- float term_odt_mult_wr;
- uint8_t cen_dq_dqs_drv_imp_value;
-
-// Get number of nets that will have termination applied from ODT (DQ,DQS,DM,
-// TDQS)
-// number of nets for DQ (9 DRAMs x 8 bits each, or 18 DRAMs x 4 bits each = 72)
- number_nets_term_rd = 72;
- number_nets_term_wr = 72;
-// add in number of nets for DQS + DM + TDQS (TDQS only supported for X8, DM
-// only used for writes)
- if (i_dram_width == fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X4)
- {
- number_nets_term_rd = number_nets_term_rd + 36 + 0 + 0;
- number_nets_term_wr = number_nets_term_wr + 36 + 0 + 0;
- }
- else if ((i_dram_width == fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X8) &&
- (i_dram_tdqs == fapi::ENUM_ATTR_EFF_DRAM_TDQS_DISABLE))
- {
- number_nets_term_rd = number_nets_term_rd + 18 + 0 + 0;
- number_nets_term_wr = number_nets_term_wr + 18 + 9 + 0;
- }
- else if ((i_dram_width == fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X8) &&
- (i_dram_tdqs == fapi::ENUM_ATTR_EFF_DRAM_TDQS_ENABLE))
- {
- number_nets_term_rd = number_nets_term_rd + 18 + 0 + 18;
- number_nets_term_wr = number_nets_term_wr + 18 + 0 + 18;
- }
-
-// which rank is mapped to the [01]ODT[01] nets, from centaur spec, every type
-// uses Ranks 0,1,4,5, with the following exceptions
-// Type 1D used Ranks 0,2,4,6 in that order (0_ODT0,0_ODT1,1_ODT0,1_ODT1)
-// expect that EFF_ODT_RD and EFF_ODT_WR will be setup correctly so we just need
-// to add up any termination in parallel for the bits set in these attributes
-// Also need to consider if ODT is tied high for writes (if rtt_wr is set for
-// the rank being written to, then it will be assumed that ODT is tied high)
-
-// Type_1D is also the following (use these instead of attribute)
-// 1. RDIMM or UDIMM
-// 2. 4 Master Ranks
-// 3. Planar or DDP/QDP
- if (
- ((i_dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM)
- || (i_dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM))
- &&
- (i_dimm_master_ranks_array[i_port][i_dimm] == 4)
- &&
- ((i_stack_type == fapi::ENUM_ATTR_EFF_STACK_TYPE_NONE)
- || (i_stack_type == fapi::ENUM_ATTR_EFF_STACK_TYPE_DDP_QDP))
- )
- {
- ma0odt01_dimm = 0;
- ma1odt01_dimm = 1;
- ma0odt0_rank = 0;
- ma0odt1_rank = 2;
- ma1odt0_rank = 0;
- ma1odt1_rank = 2;
- }
- else
- {
- ma0odt01_dimm = 0;
- ma1odt01_dimm = 1;
- ma0odt0_rank = 0;
- ma0odt1_rank = 1;
- ma1odt0_rank = 0;
- ma1odt1_rank = 1;
- }
-
-// check to see if rank is configured, only get termination power for these
-// ranks
- rank_mask = 0x00;
- if (i_rank == 0)
- {
- rank_mask = 0x80;
- }
- else if (i_rank == 1)
- {
- rank_mask = 0x40;
- }
- else if (i_rank == 2)
- {
- rank_mask = 0x20;
- }
- else if (i_rank == 3)
- {
- rank_mask = 0x10;
- }
- if ((i_dimm_ranks_configed_array[i_port][i_dimm] & rank_mask) != 0)
- {
-// effective net termination = [(active termination in parallel || driver
-// impedance) + active termination in parallel]
-
-
-
-//------------------------------------------------------------------------------
-// calculate out effective termination for reads
-//------------------------------------------------------------------------------
- eff_term_rd = 0;
-
-//------------------------------------------------------------------------------
-// 0ODT0
- if (
- ((i_dimm_rank_odt_rd[i_port][i_dimm][i_rank] & 0x80) != 0)
- &&
- (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)
- )
- {
- if (eff_term_rd == 0)
- {
- eff_term_rd =
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank];
- }
- else
- {
- eff_term_rd =
- (eff_term_rd *
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank])
- /
- (eff_term_rd +
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]);
- }
- FAPI_DBG("[P%d:D%d:R%d] 0ODT0 RD TERMINATION = %4.2f (%d)", i_port, i_dimm, i_rank, eff_term_rd, i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]);
-
- }
-//------------------------------------------------------------------------------
-// 0ODT1
- if (
- ((i_dimm_rank_odt_rd[i_port][i_dimm][i_rank] & 0x40) != 0)
- &&
- (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)
- )
- {
- if (eff_term_rd == 0)
- {
- eff_term_rd =
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank];
- }
- else
- {
- eff_term_rd =
- (eff_term_rd *
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank])
- /
- (eff_term_rd +
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]);
- }
- FAPI_DBG("[P%d:D%d:R%d] 0ODT1 RD TERMINATION = %4.2f (%d)", i_port, i_dimm, i_rank, eff_term_rd, i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]);
- }
-//------------------------------------------------------------------------------
-// 1ODT0
- if (
- ((i_dimm_rank_odt_rd[i_port][i_dimm][i_rank] & 0x20) != 0)
- &&
- (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)
- )
- {
- if (eff_term_rd == 0)
- {
- eff_term_rd =
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank];
- }
- else
- {
- eff_term_rd =
- (eff_term_rd *
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank])
- /
- (eff_term_rd +
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]);
- }
- FAPI_DBG("[P%d:D%d:R%d] 1ODT0 RD TERMINATION = %4.2f (%d)", i_port, i_dimm, i_rank, eff_term_rd, i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]);
- }
-//------------------------------------------------------------------------------
-// 1ODT1
- if (
- ((i_dimm_rank_odt_rd[i_port][i_dimm][i_rank] & 0x10) != 0)
- &&
- (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)
- )
- {
- if (eff_term_rd == 0)
- {
- eff_term_rd =
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank];
- }
- else
- {
- eff_term_rd =
- (eff_term_rd *
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank])
- /
- (eff_term_rd +
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]);
- }
- FAPI_DBG("[P%d:D%d:R%d] 1ODT1 RD TERMINATION = %4.2f (%d)", i_port, i_dimm, i_rank, eff_term_rd, i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]);
- }
-
-// calculate out effective read termination
- if (eff_term_rd != 0)
- {
- eff_net_term_rd =
- (float(
- (float(eff_term_rd * i_cen_dq_dqs_rcv_imp[i_port]) /
- (eff_term_rd + i_cen_dq_dqs_rcv_imp[i_port]))
- * i_dimm_dram_ron[i_port][i_dimm]
- )
- /
- (
- (float(eff_term_rd * i_cen_dq_dqs_rcv_imp[i_port]) /
- (eff_term_rd + i_cen_dq_dqs_rcv_imp[i_port])
- )
- + i_dimm_dram_ron[i_port][i_dimm]
- )
- )
- +
- (float(eff_term_rd * i_cen_dq_dqs_rcv_imp[i_port]) /
- (eff_term_rd + i_cen_dq_dqs_rcv_imp[i_port]));
- term_odt_mult_rd = 1.25;
- }
- else
- {
- eff_net_term_rd =
- (float((i_cen_dq_dqs_rcv_imp[i_port]) *
- i_dimm_dram_ron[i_port][i_dimm])
- / ((i_cen_dq_dqs_rcv_imp[i_port]) +
- i_dimm_dram_ron[i_port][i_dimm])
- )
- +
- (i_cen_dq_dqs_rcv_imp[i_port]);
- term_odt_mult_rd = 1;
- }
-// writes
-//------------------------------------------------------------------------------
-// calculate out effective termination for writes
-//------------------------------------------------------------------------------
- eff_term_wr = 0;
-
-// check to see if ODT is tied high (rank is not one of the ranks that get ODT
-// driven to it, and rtt_wr or rtt_nom are enabled)
- if (
- (
- (((i_rank != ma0odt0_rank) && (i_rank != ma0odt1_rank)) &&
- (i_dimm == 0))
- ||
- (((i_rank != ma1odt0_rank) && (i_rank != ma1odt1_rank)) &&
- (i_dimm == 1))
- )
- &&
- ((i_dram_rtt_wr[i_port][i_dimm][i_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) ||
- (i_dram_rtt_nom[i_port][i_dimm][i_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE))
- )
- {
-// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has
-// it enabled)
- if (i_dram_rtt_wr[i_port][i_dimm][i_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE)
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr = i_dram_rtt_wr[i_port][i_dimm][i_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr * i_dram_rtt_wr[i_port][i_dimm][i_rank])
- /
- (eff_term_wr + i_dram_rtt_wr[i_port][i_dimm][i_rank]);
- }
- }
-
- // dynamic ODT disabled, so use rtt_nom
- else if (i_dram_rtt_nom[i_port][i_dimm][i_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr = i_dram_rtt_nom[i_port][i_dimm][i_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr * i_dram_rtt_nom[i_port][i_dimm][i_rank])
- /
- (eff_term_wr +
- i_dram_rtt_nom[i_port][i_dimm][i_rank]);
- }
-
- }
- FAPI_DBG("[P%d:D%d:R%d] WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_wr[i_port][i_dimm][i_rank], i_dram_rtt_nom[i_port][i_dimm][i_rank]);
- }
-//------------------------------------------------------------------------------
-// 0ODT0
- if (
- ((i_dimm_rank_odt_wr[i_port][i_dimm][i_rank] & 0x80) != 0)
- &&
- ((i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) ||
- (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE))
- )
- {
-// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has
-// it enabled)
- if (
- (i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE)
- && (i_dimm == 0)
- && (i_rank == ma0odt0_rank)
- )
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr =
- i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr *
- i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank])
- /
- (eff_term_wr +
- i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank]);
- }
- }
- // dynamic ODT disabled, so use rtt_nom
- else if (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr =
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr *
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank])
- /
- (eff_term_wr +
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]);
- }
-
- }
- FAPI_DBG("[P%d:D%d:R%d] 0ODT0 WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank], i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank]);
- }
-//------------------------------------------------------------------------------
-// 0ODT1
- if (
- ((i_dimm_rank_odt_wr[i_port][i_dimm][i_rank] & 0x40) != 0)
- &&
- ((i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) ||
- (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE))
- )
- {
-// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has
-// it enabled)
- if (
- (i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE)
- && (i_dimm == 0)
- && (i_rank == ma0odt1_rank)
- )
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr =
- i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr *
- i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank])
- /
- (eff_term_wr +
- i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank]);
- }
- }
-// dynamic ODT disabled, so use rtt_nom
- else if (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr =
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr *
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank])
- /
- (eff_term_wr +
- i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]);
- }
-
- }
- FAPI_DBG("[P%d:D%d:R%d] 0ODT1 WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank], i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank]);
- }
-//------------------------------------------------------------------------------
-// 1ODT0
- if (
- ((i_dimm_rank_odt_wr[i_port][i_dimm][i_rank] & 0x20) != 0)
- &&
- ((i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) ||
- (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE))
- )
- {
-// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has
-// it enabled)
- if (
- (i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE)
- && (i_dimm == 1)
- && (i_rank == ma1odt0_rank)
- )
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr =
- i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr *
- i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank])
- /
- (eff_term_wr +
- i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank]);
- }
- }
- // dynamic ODT disabled, so use rtt_nom
- else if (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr =
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr *
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank])
- /
- (eff_term_wr +
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]);
- }
-
- }
- FAPI_DBG("[P%d:D%d:R%d] 1ODT0 WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank], i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank]);
- }
-//------------------------------------------------------------------------------
-// 1ODT1
- if (
- ((i_dimm_rank_odt_wr[i_port][i_dimm][i_rank] & 0x10) != 0)
- &&
- ((i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) ||
- (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE))
- )
- {
-// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has
-// it enabled)
- if (
- (i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE)
- && (i_dimm == 1)
- && (i_rank == ma1odt1_rank)
- )
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr =
- i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr *
- i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank])
- /
- (eff_term_wr +
- i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank]);
- }
- }
- // dynamic ODT disabled, so use rtt_nom
- else if (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank] !=
- fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)
- {
- if (eff_term_wr == 0)
- {
- eff_term_wr =
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank];
- }
- else
- {
- eff_term_wr =
- (eff_term_wr *
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank])
- /
- (eff_term_wr +
- i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]);
- }
-
- }
- FAPI_DBG("[P%d:D%d:R%d] 1ODT1 WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank], i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank]);
- }
-
-
-// Translate enum value to a resistance value for i_cen_dq_dqs_drv_imp[i_port]
- rc = mss_eff_config_thermal_get_cen_drv_value
- (
- i_cen_dq_dqs_drv_imp[i_port],
- cen_dq_dqs_drv_imp_value
- );
- if (rc)
- {
- FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_get_cen_drv_value", static_cast<uint32_t>(rc));
- return rc;
- }
-
- if (eff_term_wr != 0)
- {
- eff_net_term_wr =
- (float(eff_term_wr * cen_dq_dqs_drv_imp_value) /
- (eff_term_wr + cen_dq_dqs_drv_imp_value)) + eff_term_wr;
- term_odt_mult_wr = 1.25;
- }
- else
- {
- eff_net_term_wr = cen_dq_dqs_drv_imp_value;
- term_odt_mult_wr = 1;
- }
-
-//------------------------------------------------------------------------------
-// From Warren:
-// Termination power = (voltage/net termination) * number of nets *
-// (% of traffic on bus*1.25)
-// The net termination is the effective termination that exists between the
-// power rail and ground. So in my calculations this is all the active
-// termination in parallel with the driver impedance + all the active
-// termination in parallel. The value is different for reads and writes.
-// Number of nets includes the strobe nets (2 nets per strobe)
-// % of traffic on bus is the % of the bus used for data traffic split out from
-// reads and writes. The 1.25 factor is due to the odt_en signals being active
-// longer then the data windows.
-// Value here is in Watts (W)
- o_dimm_power_adder_termination =
- float(i_dimm_voltage) / 1000
- *
- (
- ((float(i_dimm_voltage) / 1000 / eff_net_term_rd) *
- (number_nets_term_rd) *
- (float(ACTIVE_DIMM_UTILIZATION) / 100) *
- (float(DATA_BUS_READ_PERCENT) / 100) * (term_odt_mult_rd))
- +
- ((float(i_dimm_voltage) / 1000 / eff_net_term_wr) *
- (number_nets_term_wr) *
- (float(ACTIVE_DIMM_UTILIZATION) / 100) *
- (float(DATA_BUS_WRITE_PERCENT) / 100) * (term_odt_mult_wr))
- );
- FAPI_DBG("%s TERM:[P%d:D%d:R%d] CEN[DRV=%d RCV=%d] DRAM[DRV=%d ODT_RD=%4.2f ODT_WR=%4.2f]", i_nom_or_wc_term, i_port, i_dimm, i_rank, cen_dq_dqs_drv_imp_value, i_cen_dq_dqs_rcv_imp[i_port], i_dimm_dram_ron[i_port][i_dimm], eff_term_rd, eff_term_wr);
- FAPI_DBG("%s TERM POWER:[P%d:D%d:R%d] RD[Nets=%d EffTerm=%3.2f ODTMult=%1.2f] WR[Nets=%d EffTerm=%3.2f ODTMult=%1.2f] TermPower(%d%%)=%2.2f W", i_nom_or_wc_term, i_port, i_dimm, i_rank, number_nets_term_rd, eff_net_term_rd, term_odt_mult_rd, number_nets_term_wr, eff_net_term_wr, term_odt_mult_wr, ACTIVE_DIMM_UTILIZATION, o_dimm_power_adder_termination);
- }
- else
- {
-// rank not configured, so it has no termination power associated with it
- o_dimm_power_adder_termination = 0;
- }
-
- FAPI_IMP("*** %s COMPLETE ***", procedure_name);
- return rc;
- }
-
-//------------------------------------------------------------------------------
-// @brief mss_eff_config_thermal_get_wc_term(): This function finds the worst
-// case termination settings possible for a given set of termination settings
-//
-// @param[in] const fapi::Target &i_target_mba: MBA Target
-// @param[in] uint8_t i_port: MBA port being worked on
-// @param[out] uint8_t &o_cen_dq_dqs_rcv_imp_wc: Worst Case Centaur DQ/DQS
-// receiver impedance (output)
-// @param[out] uint8_t &o_cen_dq_dqs_drv_imp_wc: Worst Case Centaur DQ/DQS
-// driver impedance (output)
-//
-// @return fapi::ReturnCode
-//------------------------------------------------------------------------------
-
- fapi::ReturnCode mss_eff_config_thermal_get_wc_term
- (
- const fapi::Target &i_target_mba,
- uint8_t i_port,
- uint8_t &o_cen_dq_dqs_rcv_imp_wc,
- uint8_t &o_cen_dq_dqs_drv_imp_wc
- )
- {
- fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS;
-
- const char * procedure_name = "mss_eff_config_thermal_get_wc_term";
-
- FAPI_IMP("*** Running %s ***", procedure_name);
-
- uint8_t l_cen_dq_dqs_rcv_imp[NUM_PORTS];
- uint8_t l_cen_dq_dqs_drv_imp[NUM_PORTS];
- uint32_t l_cen_dq_dqs_rcv_imp_schmoo[NUM_PORTS];
- uint32_t l_cen_dq_dqs_drv_imp_schmoo[NUM_PORTS];
- uint32_t l_loop;
- uint32_t l_schmoo_mask;
-
-// This lists out the number and enum values for the centaur dq/dqs receiver and
-// driver impedance. Have the list go from strongest to weakest termination.
-// If the size changes at all, then updates are needed below to get the correct
-// mask
-
- const uint8_t MAX_CEN_RCV_IMP = 10;
- uint8_t cen_rcv_imp_array[] = {
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM15,
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM20,
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM30,
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM40,
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM48,
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM60,
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM80,
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM120,
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM160,
- fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM240
- };
-
- const uint8_t MAX_CEN_DRV_IMP = 16;
- uint8_t cen_drv_imp_array[] = {
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM24_FFE0,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE0,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE480,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE240,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE160,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE120,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE0,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE480,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE240,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE160,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE120,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE0,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE480,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE240,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE160,
- fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE120
- };
-
-
-// Get attributes for nominal settings and possible settings to choose from
- rc = FAPI_ATTR_GET(ATTR_EFF_CEN_RCV_IMP_DQ_DQS,
- &i_target_mba, l_cen_dq_dqs_rcv_imp);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_CEN_RCV_IMP_DQ_DQS");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_CEN_DRV_IMP_DQ_DQS,
- &i_target_mba, l_cen_dq_dqs_drv_imp);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_CEN_DRV_IMP_DQ_DQS");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_CEN_RCV_IMP_DQ_DQS_SCHMOO,
- &i_target_mba, l_cen_dq_dqs_rcv_imp_schmoo);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_CEN_RCV_IMP_DQ_DQS_SCHMOO");
- return rc;
- }
- rc = FAPI_ATTR_GET(ATTR_EFF_CEN_DRV_IMP_DQ_DQS_SCHMOO,
- &i_target_mba, l_cen_dq_dqs_drv_imp_schmoo);
- if (rc) {
- FAPI_ERR("Error getting attribute ATTR_EFF_CEN_DRV_IMP_DQ_DQS_SCHMOO");
- return rc;
- }
-
-// initialize to default values in case below does not find a match
- o_cen_dq_dqs_rcv_imp_wc = l_cen_dq_dqs_rcv_imp[i_port];
- o_cen_dq_dqs_drv_imp_wc = l_cen_dq_dqs_drv_imp[i_port];
-
-// find strongest termination setting that could be used, if none found, then
-// use nominal
- l_schmoo_mask = 0x00000000;
- for (l_loop=0; l_loop < MAX_CEN_RCV_IMP; l_loop++)
- {
- switch (l_loop)
- {
- case 0:
- l_schmoo_mask = 0x80000000;
- break;
- case 1:
- l_schmoo_mask = 0x40000000;
- break;
- case 2:
- l_schmoo_mask = 0x20000000;
- break;
- case 3:
- l_schmoo_mask = 0x10000000;
- break;
- case 4:
- l_schmoo_mask = 0x08000000;
- break;
- case 5:
- l_schmoo_mask = 0x04000000;
- break;
- case 6:
- l_schmoo_mask = 0x02000000;
- break;
- case 7:
- l_schmoo_mask = 0x01000000;
- break;
- case 8:
- l_schmoo_mask = 0x00800000;
- break;
- case 9:
- l_schmoo_mask = 0x00400000;
- break;
- default:
- o_cen_dq_dqs_rcv_imp_wc = l_cen_dq_dqs_rcv_imp[i_port];
- }
- if ((l_cen_dq_dqs_rcv_imp_schmoo[i_port] & l_schmoo_mask) != 0)
- {
- o_cen_dq_dqs_rcv_imp_wc = cen_rcv_imp_array[l_loop];
- break;
- }
- }
-
- l_schmoo_mask = 0x00000000;
- for (l_loop=0; l_loop < MAX_CEN_DRV_IMP; l_loop++)
- {
- switch (l_loop)
- {
- case 0:
- l_schmoo_mask = 0x80000000;
- break;
- case 1:
- l_schmoo_mask = 0x40000000;
- break;
- case 2:
- l_schmoo_mask = 0x20000000;
- break;
- case 3:
- l_schmoo_mask = 0x10000000;
- break;
- case 4:
- l_schmoo_mask = 0x08000000;
- break;
- case 5:
- l_schmoo_mask = 0x04000000;
- break;
- case 6:
- l_schmoo_mask = 0x02000000;
- break;
- case 7:
- l_schmoo_mask = 0x01000000;
- break;
- case 8:
- l_schmoo_mask = 0x00800000;
- break;
- case 9:
- l_schmoo_mask = 0x00400000;
- break;
- case 10:
- l_schmoo_mask = 0x00200000;
- break;
- case 11:
- l_schmoo_mask = 0x00100000;
- break;
- case 12:
- l_schmoo_mask = 0x00080000;
- break;
- case 13:
- l_schmoo_mask = 0x00040000;
- break;
- case 14:
- l_schmoo_mask = 0x00020000;
- break;
- case 15:
- l_schmoo_mask = 0x00010000;
- break;
- default:
- o_cen_dq_dqs_drv_imp_wc = l_cen_dq_dqs_drv_imp[i_port];
- }
- if ((l_cen_dq_dqs_drv_imp_schmoo[i_port] & l_schmoo_mask) != 0)
- {
- o_cen_dq_dqs_drv_imp_wc = cen_drv_imp_array[l_loop];
- break;
- }
- }
-
- FAPI_IMP("*** %s COMPLETE ***", procedure_name);
- return rc;
- }
-
-
-//------------------------------------------------------------------------------
-// @brief mss_eff_config_thermal_get_cen_drv_value(): This function will
-// translate the centaur driver impedance enum value to a termination resistance
-//
-// @param[in] uint8_t &i_cen_dq_dqs_drv_imp: Centaur DQ/DQS driver impedance
-// enum setting (input)
-// @param[out] uint8_t &o_cen_dq_dqs_drv_imp: Centaur DQ/DQS driver impedance
-// value (output)
-//
-// @return fapi::ReturnCode
-//------------------------------------------------------------------------------
-
- fapi::ReturnCode mss_eff_config_thermal_get_cen_drv_value
- (
- uint8_t i_cen_dq_dqs_drv_imp,
- uint8_t &o_cen_dq_dqs_drv_imp
- )
- {
- fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS;
-
- const char* procedure_name = "mss_eff_config_thermal_get_cen_drv_value";
-
- FAPI_IMP("*** Running %s ***", procedure_name);
-
- switch (i_cen_dq_dqs_drv_imp)
- {
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM24_FFE0:
- o_cen_dq_dqs_drv_imp = 24;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE0:
- o_cen_dq_dqs_drv_imp = 30;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE480:
- o_cen_dq_dqs_drv_imp = 30;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE240:
- o_cen_dq_dqs_drv_imp = 30;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE160:
- o_cen_dq_dqs_drv_imp = 30;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE120:
- o_cen_dq_dqs_drv_imp = 30;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE0:
- o_cen_dq_dqs_drv_imp = 34;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE480:
- o_cen_dq_dqs_drv_imp = 34;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE240:
- o_cen_dq_dqs_drv_imp = 34;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE160:
- o_cen_dq_dqs_drv_imp = 34;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE120:
- o_cen_dq_dqs_drv_imp = 34;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE0:
- o_cen_dq_dqs_drv_imp = 40;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE480:
- o_cen_dq_dqs_drv_imp = 40;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE240:
- o_cen_dq_dqs_drv_imp = 40;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE160:
- o_cen_dq_dqs_drv_imp = 40;
- break;
- case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE120:
- o_cen_dq_dqs_drv_imp = 40;
- break;
- default:
- o_cen_dq_dqs_drv_imp = 24;
- }
-
- FAPI_IMP("*** %s COMPLETE ***", procedure_name);
- return rc;
- }
-
-
} //end extern C
OpenPOWER on IntegriCloud