summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Jones <mjjones@us.ibm.com>2012-05-11 08:21:51 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-05-21 12:49:40 -0500
commit8277968ad48681189bf58cb785ebf01c5d6fdf37 (patch)
treec42f396962cde9be4151eb9bbdd40b99a3100ba6
parenta32430814a0f190f08102d776b886656060c8509 (diff)
downloadtalos-hostboot-8277968ad48681189bf58cb785ebf01c5d6fdf37.tar.gz
talos-hostboot-8277968ad48681189bf58cb785ebf01c5d6fdf37.zip
HWP: Merge updated mss_freq into Hostboot
Current Hostboot contains a version that did not pass FW review. This is a version that passes the FW review. This change does not need a detailed review. Change-Id: I5021707b39bd1ffaa6ac3a20ceb7fd6de2c362d9 RTC: 37047 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1051 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--src/usr/hwpf/hwp/dram_training/memory_errors.xml15
-rw-r--r--src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.C244
-rw-r--r--src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.H7
3 files changed, 209 insertions, 57 deletions
diff --git a/src/usr/hwpf/hwp/dram_training/memory_errors.xml b/src/usr/hwpf/hwp/dram_training/memory_errors.xml
index 2ff29fd61..82b5c7b96 100644
--- a/src/usr/hwpf/hwp/dram_training/memory_errors.xml
+++ b/src/usr/hwpf/hwp/dram_training/memory_errors.xml
@@ -294,4 +294,19 @@
<description>Invalid to use ECC spare in x8 mode. </description>
</hwpError>
+ <hwpError>
+ <rc>RC_MSS_UNSUPPORTED_SPD_DATA</rc>
+ <description>Invalid SPD data returned. </description>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_NO_COMMON_SUPPORTED_CL</rc>
+ <description>Current Configuration has no common supported CL Values. </description>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_EXCEED_TAA_MAX_NO_CL</rc>
+ <description> Exceeded TAA MAX with Lowest frequency. No compatable CL. </description>
+ </hwpError>
+
</hwpErrors>
diff --git a/src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.C b/src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.C
index 3d6573c9e..82c60bbe0 100644
--- a/src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.C
+++ b/src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.C
@@ -44,7 +44,16 @@
//---------|----------|----------|----------------------------------------------
// 1.1 | jsabrow | 09/30/11 | Initial draft.
// 1.2 | bellows | 12/21/11 | fixed function call to mss_freq
-// 1.4 | jsabrow |
+// 1.4 | jsabrow |
+// 1.6 | jdsloat | 05/03/12 | Fixed per Firmware request, added CL calc
+// 1.7 | jdsloat | 05/03/12 | Uncommented Set Attributes
+// 1.8 | jdsloat | 05/07/12 | fixed per Firmware request
+// 1.9 | jdsloat | 05/07/12 | Unused Variables removed
+// 1.11 | jdsloat | 05/07/12 | Uncommented Set Attributes
+// 1.12 | jdsloat | 05/08/12 | Fixed per Firmware request, fixed CL attribute set, fixed MTB usage.
+// 1.13 | jdsloat | 05/09/12 | Fixed per Firmware request
+// 1.14 | jdsloat | 05/10/12 | Fixed per Firmware Request, RC checks, 0 checks
+//
// This procedure takes CENTAUR as argument. for each DIMM (under each MBA)
// DIMM SPD attributes are read to determine optimal DRAM frequency
// frequency bins: 800*, 1066*, 1333, 1600, 1866, 2133, 2400*, 2666*
@@ -58,130 +67,257 @@
using namespace fapi;
-fapi::ReturnCode mss_freq(fapi::Target &i_target_memb)
+fapi::ReturnCode mss_freq(const fapi::Target &i_target_memb)
{
fapi::ReturnCode l_rc;
std::vector<fapi::Target> l_mbaChiplets;
std::vector<fapi::Target> l_dimm_targets;
- uint8_t l_spd_byte10=0;
- uint8_t l_spd_byte11=0;
- uint8_t l_spd_byte12=0;
- uint32_t l_spd_byte1415=0xFFFF;
- uint8_t l_spd_byte16=0;
+ uint8_t l_spd_mtb_dividend=0;
+ uint8_t l_spd_mtb_divisor=0;
uint32_t l_dimm_freq_calc=0;
- uint32_t l_dimm_freq_max=9999;
+ uint32_t l_dimm_freq_min=9999;
+ uint8_t l_spd_min_tck_MTB=0;
+ uint32_t l_spd_min_tck=0;
+ uint32_t l_spd_min_tck_max=0;
+ uint8_t l_spd_min_taa_MTB=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_dimm_all_cas=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;
// Get associated MBA's on this centaur
l_rc=fapiGetChildChiplets(i_target_memb, fapi::TARGET_TYPE_MBA_CHIPLET, l_mbaChiplets);
+ if (l_rc)
+ {
+ FAPI_ERR("Error Getting MBA targets.");
+ return l_rc;
+ }
// Loop through the 2 MBA's
for (uint32_t i=0; i < l_mbaChiplets.size(); i++)
{
// Get a vector of DIMM targets
l_rc = fapiGetAssociatedDimms(l_mbaChiplets[i], l_dimm_targets);
+ if (l_rc)
+ {
+ FAPI_ERR("Error Getting DIMM targets.");
+ return l_rc;
+ }
for (uint32_t j=0; j < l_dimm_targets.size(); j++)
{
- l_rc = FAPI_ATTR_GET(ATTR_SPD_MTB_DIVIDEND, &l_dimm_targets[j], l_spd_byte10);
+ l_rc = FAPI_ATTR_GET(ATTR_SPD_MTB_DIVIDEND, &l_dimm_targets[j], l_spd_mtb_dividend);
if (l_rc)
{
- FAPI_ERR("Unable to read SPD byte 10.");
+ FAPI_ERR("Unable to read SPD Medium Timebase Dividend.");
break;
}
- l_rc = FAPI_ATTR_GET(ATTR_SPD_MTB_DIVISOR, &l_dimm_targets[j], l_spd_byte11);
+ l_rc = FAPI_ATTR_GET(ATTR_SPD_MTB_DIVISOR, &l_dimm_targets[j], l_spd_mtb_divisor);
if (l_rc)
{
- FAPI_ERR("Unable to read SPD byte 11.");
+ FAPI_ERR("Unable to read SPD Medium Timebase Divisor.");
break;
}
- l_rc = FAPI_ATTR_GET(ATTR_SPD_TCKMIN, &l_dimm_targets[j], l_spd_byte12);
+ l_rc = FAPI_ATTR_GET(ATTR_SPD_TCKMIN, &l_dimm_targets[j], l_spd_min_tck_MTB);
if (l_rc)
{
- FAPI_ERR("Unable to read SPD byte 12.");
+ FAPI_ERR("Unable to read SPD Minimum TCK (Min Clock Cycle).");
break;
- }
-
- //TODO: need to check that bytes 10, 11 nor 12 are zero
- //JEDEC doesn't allow zeroes in these bytes, but we should check.
- //integer-safe equation for dram clock * 2
- l_dimm_freq_calc = 2000000 / ( ( 1000 * l_spd_byte12 * l_spd_byte10 ) / l_spd_byte11);
-
- //is this the slowest dimm?
- if (l_dimm_freq_calc < l_dimm_freq_max)
- {
- l_dimm_freq_max = l_dimm_freq_calc;
}
- l_rc = FAPI_ATTR_GET(ATTR_SPD_CAS_LATENCIES_SUPPORTED, &l_dimm_targets[j], l_spd_byte1415);
+ l_rc = FAPI_ATTR_GET(ATTR_SPD_TAAMIN, &l_dimm_targets[j], l_spd_min_taa_MTB);
if (l_rc)
{
- FAPI_ERR("Unable to read SPD byte 14-15.");
+ FAPI_ERR("Unable to read SPD Minimum TAA (Min CAS Latency Time).");
break;
- }
-
- //'AND' all dimm CAS support
- l_dimm_all_cas = l_dimm_all_cas & l_spd_byte1415;
-
- l_rc = FAPI_ATTR_GET(ATTR_SPD_TAAMIN, &l_dimm_targets[j], l_spd_byte16);
+ }
+ l_rc = FAPI_ATTR_GET(ATTR_SPD_CAS_LATENCIES_SUPPORTED, &l_dimm_targets[j], l_spd_cas_lat_supported);
if (l_rc)
{
- FAPI_ERR("Unable to read SPD byte 16.");
+ FAPI_ERR("Unable to read SPD Supported CAS Latencies.");
break;
- }
+ }
+ if ((l_spd_min_tck_MTB == 0)||(l_spd_mtb_dividend == 0)||(l_spd_mtb_divisor == 0)||(l_spd_min_taa_MTB == 0))
+ {
+ //Invalid due to the fact that JEDEC dictates that these should be non-zero.
+ FAPI_ERR("Invalid data recieved from SPD within MTB Dividend, MTB Divisor, TCK Min, or TAA Min");
+ FAPI_SET_HWP_ERROR(l_rc, RC_MSS_UNSUPPORTED_SPD_DATA);
+ break;
+ }
+
+ // 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;
+ 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.
+ FAPI_ERR("Invalid data recieved from SPD causing TCK Min or TAA Min to be 0");
+ FAPI_SET_HWP_ERROR(l_rc, RC_MSS_UNSUPPORTED_SPD_DATA);
+ break;
+ }
+ l_dimm_freq_calc = 2000000 / l_spd_min_tck;
- }
- }
-
+ //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;
+ }
+
+ l_spd_cas_lat_supported_all = l_spd_cas_lat_supported_all & l_spd_cas_lat_supported;
+
+ }
+ if (l_rc)
+ {
+ break;
+ }
+ }
+
+ if ((l_spd_cas_lat_supported_all == 0) && (!l_rc))
+ {
+ FAPI_ERR("No common supported CAS latencies between DIMMS.");
+ FAPI_SET_HWP_ERROR(l_rc, RC_MSS_NO_COMMON_SUPPORTED_CL);
+ }
+
+ if (!l_rc)
+ {
+
+ //Determine a proposed CAS latency
+ 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;
+
+ // If the CL proposed is not supported or the TAA exceeds TAA max
+ // Spec defines tAAmax as 20 ns for all DDR3 speed grades.
+ while ((!( l_spd_cas_lat_supported_all & (0x00000001<<(l_cas_latency-4)))) || (l_cl_mult_tck > 20000))
+ {
+ // 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;
+
+ if ((!( l_spd_cas_lat_supported_all & (0x00000001<<(l_cas_latency-4)))) || (l_cl_mult_tck > 20000))
+ {
+ 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
+ FAPI_ERR("Lowered Frequency to TCLK MIN finding no supported CL without exceeding TAA MAX.");
+ FAPI_SET_HWP_ERROR(l_rc, RC_MSS_EXCEED_TAA_MAX_NO_CL );
+ break;
+ }
+
+ // 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;
+
+ }
+ }
+ }
+
+ FAPI_INF( "Calculated Frequency: %d ", l_dimm_freq_min);
+
//bucketize dimm freq.
if (!l_rc)
- {
- if (l_dimm_freq_max < 1013)
+ {
+ if (l_dimm_freq_min < 1013)
{
- // 800 isn't supported
- l_selected_dimm_freq=800;
+ FAPI_ERR("Unsupported frequency: DIMM Freq calculated < 1013 MHz");
+ FAPI_SET_HWP_ERROR(l_rc, RC_MSS_UNSUPPORTED_FREQ_CALCULATED);
}
- else if (l_dimm_freq_max < 1266)
+ else if (l_dimm_freq_min < 1266)
{
// 1066
l_selected_dimm_freq=1066;
}
- else if (l_dimm_freq_max < 1520)
+ else if (l_dimm_freq_min < 1520)
{
// 1333
l_selected_dimm_freq=1333;
}
- else if (l_dimm_freq_max < 1773)
+ else if (l_dimm_freq_min < 1773)
{
// 1600
l_selected_dimm_freq=1600;
}
- else if (l_dimm_freq_max < 2026)
+ else if (l_dimm_freq_min < 2026)
{
// 1866
l_selected_dimm_freq=1866;
}
- else if (l_dimm_freq_max < 2280)
+ else if (l_dimm_freq_min < 2280)
{
// 2133
l_selected_dimm_freq=2133;
}
else
{
- //FAPI_ERR("Error dimm freq calculated > 2133 MHz");
+ FAPI_ERR("Unsupported frequency: DIMM Freq calculated > 2133 MHz: %d", l_dimm_freq_min);
+ FAPI_SET_HWP_ERROR(l_rc, RC_MSS_UNSUPPORTED_FREQ_CALCULATED);
}
- }
+ }
- //TODO: frequency consideration for CAS
-
// set frequency in centaur attribute ATTR_MSS_FREQ
if (!l_rc)
- {
+ {
l_rc = FAPI_ATTR_SET(ATTR_MSS_FREQ, &i_target_memb, l_selected_dimm_freq);
- }
+ if (l_rc)
+ {
+ return l_rc;
+ }
+ FAPI_INF( "Successfully Calculated Frequency: %d ", l_selected_dimm_freq);
+ FAPI_INF( "Successfully Calculated CL: %d ", l_cas_latency);
+ for (uint32_t k=0; k < l_mbaChiplets.size(); k++)
+ {
+ l_rc = FAPI_ATTR_SET(ATTR_EFF_DRAM_CL, &l_mbaChiplets[k], l_cas_latency);
+ if (l_rc)
+ {
+ return l_rc;
+ }
+ }
+ }
//all done.
return l_rc;
diff --git a/src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.H b/src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.H
index 36b67813a..bcd6ae2a0 100644
--- a/src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.H
+++ b/src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.H
@@ -42,13 +42,14 @@
//---------|----------|---------_|-----------------------------------------------
// 1.0 | jsabrow | 11/30/11 | initial drop
// 1.2 | jsabrow | 02/14/12 | Updates for initial code review
+// 1.3 | jdsloat | 04/26/12 | Code review updates
#ifndef MSS_FREQHWPB_H_
#define MSS_FREQHWPB_H_
#include <fapi.H>
-typedef fapi::ReturnCode (*mss_freq_FP_t)(fapi::Target &);
+typedef fapi::ReturnCode (*mss_freq_FP_t)(const fapi::Target &);
extern "C"
{
@@ -56,12 +57,12 @@ extern "C"
/**
* @brief mss_freq procedure. Determines operating frequency for dimms behind a centaur
*
- * @param[in] fapi::Target &l_targets reference to one centaur
+ * @param[in] fapi::Target &l_targets target type = centaur
*
* @return ReturnCode
*/
- fapi::ReturnCode mss_freq(fapi::Target & i_target);
+ fapi::ReturnCode mss_freq(const fapi::Target & i_target);
} // extern "C"
OpenPOWER on IntegriCloud