From 8277968ad48681189bf58cb785ebf01c5d6fdf37 Mon Sep 17 00:00:00 2001 From: Mike Jones Date: Fri, 11 May 2012 08:21:51 -0500 Subject: 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 --- src/usr/hwpf/hwp/dram_training/memory_errors.xml | 15 ++ src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.C | 244 ++++++++++++++++++----- src/usr/hwpf/hwp/mc_init/mss_freq/mss_freq.H | 7 +- 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 @@ Invalid to use ECC spare in x8 mode. + + RC_MSS_UNSUPPORTED_SPD_DATA + Invalid SPD data returned. + + + + RC_MSS_NO_COMMON_SUPPORTED_CL + Current Configuration has no common supported CL Values. + + + + RC_MSS_EXCEED_TAA_MAX_NO_CL + Exceeded TAA MAX with Lowest frequency. No compatable CL. + + 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 l_mbaChiplets; std::vector 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 -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" -- cgit v1.2.1