summaryrefslogtreecommitdiffstats
path: root/src/usr/hwpf/hwp/pstates/pstates
diff options
context:
space:
mode:
authorThi Tran <thi@us.ibm.com>2013-10-02 10:31:04 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-10-04 15:40:34 -0500
commit8cddf17c6fdc5810f7cf244012afe19a7bcbd77d (patch)
tree8c7495fd83697e5d2f9f7fdac70b8b51b93f3fc2 /src/usr/hwpf/hwp/pstates/pstates
parentf67e73208f2e6db20b35efaedaf15a4d669c2869 (diff)
downloadtalos-hostboot-8cddf17c6fdc5810f7cf244012afe19a7bcbd77d.tar.gz
talos-hostboot-8cddf17c6fdc5810f7cf244012afe19a7bcbd77d.zip
INITPROC: Hostboot - from defect SW224356 - PSTATE procedures
Change-Id: I5358dab2f24f26054fb004ff980c9fe4638cff6c CMVC-Coreq:896229 CQ:SW224356 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/6446 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/hwpf/hwp/pstates/pstates')
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/lab_pstates.c192
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/lab_pstates.h16
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.C776
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.H52
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml35
-rw-r--r--src/usr/hwpf/hwp/pstates/pstates/p8_ivrm.H110
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstate_tables.c634
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstate_tables.h47
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstates.c31
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstates.h112
10 files changed, 1691 insertions, 314 deletions
diff --git a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c
index 2e7767927..fe545b7a5 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c
+++ b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c
@@ -20,7 +20,7 @@
/* Origin: 30 */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: lab_pstates.c,v 1.7 2013/06/12 20:01:35 mjjones Exp $
+// $Id: lab_pstates.c,v 1.8 2013/08/13 17:12:54 jimyac Exp $
/// \file lab_pstates.c
/// \brief Lab-only (as opposed to product-procedure) support for Pstates.
@@ -97,7 +97,7 @@ vrm112vuv(uint8_t vrm11_vid, uint32_t *v_uv)
int
vuv2ivid(uint32_t v_uv, int round, uint8_t *ivid)
-{
+{
int rc;
int32_t offset, vid;
@@ -105,7 +105,7 @@ vuv2ivid(uint32_t v_uv, int round, uint8_t *ivid)
vid = offset / IVID_STEP_UV;
if (((offset % IVID_STEP_UV) != 0) && (round >= 0)) {
- vid++;
+ vid++;
}
*ivid = vid;
@@ -114,10 +114,9 @@ vuv2ivid(uint32_t v_uv, int round, uint8_t *ivid)
} else {
rc = 0;
}
- return rc;
+ return rc;
}
-
/// Convert an iVID code to a voltage in microvolts
int
@@ -141,21 +140,24 @@ sprintf_10uv(char *s, uint32_t v_uv)
return sprintf(s, "%d.%05d", v_uv / 1000000, (v_uv % 1000000) / 10);
}
-/// Format an IVID code as 10 microvolts into a user-supplied string. The
-/// string \a s must be able to store at least FORMAT_10UV_STRLEN characters.
+#ifdef FAPIECMD
+
+/// Format a voltage in microvolts as 10 microvolts to a stream.
int
-sprintf_ivid(char *s, uint8_t ivid)
+fprintf_10uv(FILE *stream, uint32_t v_uv)
{
int rc;
- uint32_t v_uv;
+ char s[FORMAT_10UV_STRLEN];
- if ((rc = ivid2vuv(ivid, &v_uv)) != 0) {
- return rc;
+ rc = sprintf_10uv(s, v_uv);
+ if (rc > 0) {
+ rc = fputs(s, stream);
}
- return sprintf_10uv(s, v_uv);
+ return rc;
}
+
/// Format a VRM-11 VID code as 10 microvolts into a user-supplied string. The
/// string \a s must be able to store at least FORMAT_10UV_STRLEN characters.
@@ -173,17 +175,16 @@ sprintf_vrm11(char *s, uint8_t vrm11)
return rc;
}
-#ifdef FAPIECMD
-/// Format a voltage in microvolts as 10 microvolts to a stream.
+/// Format a VRM-11 VID code as 10 microvolts to a stream.
int
-fprintf_10uv(FILE *stream, uint32_t v_uv)
+fprintf_vrm11(FILE *stream, uint8_t vrm11)
{
int rc;
char s[FORMAT_10UV_STRLEN];
- rc = sprintf_10uv(s, v_uv);
+ rc = sprintf_vrm11(s, vrm11);
if (rc > 0) {
rc = fputs(s, stream);
}
@@ -191,19 +192,19 @@ fprintf_10uv(FILE *stream, uint32_t v_uv)
}
-/// Format a VRM-11 VID code as 10 microvolts to a stream.
+/// Format an IVID code as 10 microvolts into a user-supplied string. The
+/// string \a s must be able to store at least FORMAT_10UV_STRLEN characters.
int
-fprintf_vrm11(FILE *stream, uint8_t vrm11)
+sprintf_ivid(char *s, uint8_t ivid)
{
int rc;
- char s[FORMAT_10UV_STRLEN];
+ uint32_t v_uv;
- rc = sprintf_vrm11(s, vrm11);
- if (rc > 0) {
- rc = fputs(s, stream);
- }
+ if ((rc = ivid2vuv(ivid, &v_uv)) != 0) {
return rc;
+ }
+ return sprintf_10uv(s, v_uv);
}
@@ -400,32 +401,154 @@ void
lpsa_print(FILE* stream, LocalPstateArray* lpsa)
{
int i;
+ uint8_t entries;
+ uint8_t entries_div4;
+ char ivid_vdd_str[FORMAT_10UV_STRLEN];
+ char ivid_vcs_str[FORMAT_10UV_STRLEN];
+ uint8_t ivid_vdd, ivid_vcs;
+ lpst_entry_t lpst_entry;
+ vdsvin_entry_t vdsvin_entry;
fprintf(stream,
"---------------------------------------------------------------------------------------------------------\n");
fprintf(stream, "Local Pstate Array @ %p\n", lpsa);
fprintf(stream,
"---------------------------------------------------------------------------------------------------------\n");
-
fprintf(stream, "%d Entries from %+d to %+d\n",
lpsa->entries, lpst_pmin(lpsa), lpst_pmax(lpsa));
fprintf(stream, "Step Delay Rising %u, Step Delay Falling %u\n",
- lpsa->stepdelay_rising,
+ lpsa->stepdelay_rising,
lpsa->stepdelay_lowering);
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream,
+ " I ivid_vdd(V) ivid_vcs(V) Core vdd Core vcs ECO vdd ECO vcs ps1 inc ps2 inc ps3 inc inc step dec step\n"
+ " pwrratio pwrratio pwrratio pwrratio \n"
+ "---------------------------------------------------------------------------------------------------------------------\n");
+
+ entries = lpsa->entries;
+ entries_div4 = entries/4;
+
+ if ( entries % 4 != 0)
+ entries_div4++;
+
+ for (i = entries_div4-1 ; i >= 0; i--) {
+ lpst_entry.value = revle64(lpsa->pstate[i].value);
+
+ ivid_vdd = lpst_entry.fields.ivid_vdd;
+ sprintf_ivid(ivid_vdd_str, ivid_vdd);
+
+ ivid_vcs = lpst_entry.fields.ivid_vcs;
+ sprintf_ivid(ivid_vcs_str, ivid_vcs);
+
+ fprintf(stream,
+ "%2u "
+ "0x%02x %s "
+ "0x%02x %s "
+ "%-9u %-9u %-9u %-9u "
+ "%-8u %-8u %-8u "
+ "%-9u %-9u \n",
+ i,
+ ivid_vdd, ivid_vdd_str,
+ ivid_vcs, ivid_vcs_str,
+ (uint8_t)lpst_entry.fields.vdd_core_pwrratio,
+ (uint8_t)lpst_entry.fields.vcs_core_pwrratio,
+ (uint8_t)lpst_entry.fields.vdd_eco_pwrratio,
+ (uint8_t)lpst_entry.fields.vcs_eco_pwrratio,
+ (uint8_t)lpst_entry.fields.ps1_vid_incr,
+ (uint8_t)lpst_entry.fields.ps2_vid_incr,
+ (uint8_t)lpst_entry.fields.ps3_vid_incr,
+ (uint8_t)lpst_entry.fields.inc_step,
+ (uint8_t)lpst_entry.fields.dec_step);
+ }
- fprintf(stream, "Array :\n");
- for (i = 0; i < LOCAL_PSTATE_ARRAY_ENTRIES; i+= 4) {
- fprintf(stream, " 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n",
- (unsigned long long)(lpsa->pstate[i].value),
- (unsigned long long)(lpsa->pstate[i + 1].value),
- (unsigned long long)(lpsa->pstate[i + 2].value),
- (unsigned long long)(lpsa->pstate[i + 3].value));
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------------------\n\n");
+
+ fprintf(stream,
+ "--------------------------------\n");
+ fprintf(stream,
+ "VDS\n");
+ fprintf(stream,
+ " I beg_offset end_offset \n"
+ "--------------------------------\n");
+
+ for (i = 15 ; i >= 0; i--) {
+ vdsvin_entry.value = revle64(lpsa->vdsvin[i].value);
+
+ fprintf(stream,
+ "%2u "
+ "%-10u "
+ "%-10u \n",
+ i,
+ (uint8_t)vdsvin_entry.fields.ivid0,
+ (uint8_t)vdsvin_entry.fields.ivid1);
}
fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
+ "--------------------------------\n\n");
+
+
+ fprintf(stream,
+ "-----------------------------------------------------\n");
+ fprintf(stream,
+ "VIN\n");
+ fprintf(stream,
+ " I ptef0 pfet1 pfet2 pfet3 pfet4 pfet5 pfet6 pfet7\n"
+ "-----------------------------------------------------\n");
+
+ for (i = 63 ; i >= 0; i--) {
+ vdsvin_entry.value = revle64(lpsa->vdsvin[i].value);
+
+ fprintf(stream,
+ "%2u "
+ "%-5u %-5u %-5u %-5u %-5u %-5u %-5u %-5u\n",
+ i,
+ (uint8_t)vdsvin_entry.fields.pfet0,
+ (uint8_t)vdsvin_entry.fields.pfet1,
+ (uint8_t)vdsvin_entry.fields.pfet2,
+ (uint8_t)vdsvin_entry.fields.pfet3,
+ (uint8_t)vdsvin_entry.fields.pfet4,
+ (uint8_t)vdsvin_entry.fields.pfet5,
+ (uint8_t)vdsvin_entry.fields.pfet6,
+ (uint8_t)vdsvin_entry.fields.pfet7);
+ }
+
+ fprintf(stream,
+ "-----------------------------------------------------\n\n");
}
+/// Print CPM Pstate Range structure on a given stream
+///
+/// \param stream The output stream
+///
+/// \param cpmrange The CPM Pstate Range structure to print
+
+void
+cpmrange_print(FILE* stream, CpmPstateModeRanges* cpmrange)
+{
+ int i;
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream, "CPM Pstate Range @ %p\n", cpmrange);
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+
+ fprintf(stream, "Valid Number of CPM Pstate Ranges : %u\n",
+ cpmrange->validRanges);
+
+ for (i == 0; i < 8; i++) {
+ fprintf(stream, " CPM Range %d Pstate : %d\n",
+ i, cpmrange->inflectionPoint[i]);
+ }
+
+ fprintf(stream, " CPM Pmax : %d\n",
+ cpmrange->pMax);
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+}
/// Print a Resonant Clocking Setup structure on a given stream
///
@@ -481,6 +604,5 @@ pss_print(FILE* stream, PstateSuperStructure* pss)
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
}
-#endif // FAPIECMD
-
+#endif // FAPIECMD
diff --git a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h
index 5a1b614ca..cc2252e8f 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h
+++ b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h
@@ -23,7 +23,7 @@
#ifndef __LAB_PSTATES_H__
#define __LAB_PSTATES_H__
-// $Id: lab_pstates.h,v 1.4 2013/06/12 20:01:48 mjjones Exp $
+// $Id: lab_pstates.h,v 1.5 2013/08/13 17:12:56 jimyac Exp $
/// \file lab_pstates.h
/// \brief Lab-only (as opposed to product-procedure) support for Pstates.
@@ -66,19 +66,19 @@ ivid2vuv(uint8_t ivid, uint32_t *v_uv);
int
sprintf_10uv(char *s, uint32_t v_uv);
+#ifdef FAPIECMD
+
int
-sprintf_ivid(char *s, uint8_t ivid);
+fprintf_10uv(FILE *stream, uint32_t v_uv);
int
sprintf_vrm11(char *s, uint8_t vrm11);
-#ifdef FAPIECMD
-
int
-fprintf_10uv(FILE *stream, uint32_t v_uv);
+fprintf_vrm11(FILE *stream, uint8_t vrm11);
int
-fprintf_vrm11(FILE *stream, uint8_t vrm11);
+sprintf_ivid(char *s, uint8_t ivid);
int
fprintf_ivid(FILE *stream, uint8_t ivid);
@@ -90,10 +90,14 @@ void
lpsa_print(FILE* stream, LocalPstateArray* lpsa);
void
+cpmrange_print(FILE* stream, CpmPstateModeRanges* cpmrange);
+
+void
resclk_print(FILE* stream, ResonantClockingSetup* resclk);
void
pss_print(FILE* stream, PstateSuperStructure* pss);
+
#endif // FAPIECMD
#endif // __ASSEMBLER__
diff --git a/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.C b/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.C
index ba0d6be88..03f926b2c 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.C
+++ b/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.C
@@ -20,7 +20,7 @@
/* Origin: 30 */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: p8_build_pstate_datablock.C,v 1.14 2013/06/12 20:05:23 mjjones Exp $
+// $Id: p8_build_pstate_datablock.C,v 1.22 2013/09/30 18:35:35 jimyac Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/p8_build_pstate_datablock.C,v $
//------------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2012
@@ -60,8 +60,12 @@ using namespace fapi;
// ----------------------------------------------------------------------
// Function prototypes
// ----------------------------------------------------------------------
-ReturnCode proc_get_mvpd_data (const Target& i_target, uint32_t attr_mvpd_data[PV_D][PV_W]);
-ReturnCode proc_get_attributes (const Target& i_target, AttributeList *attr_list);
+ReturnCode proc_get_mvpd_data (const Target& i_target, uint32_t attr_mvpd_data[PV_D][PV_W], ivrm_mvpd_t *ivrm_mvpd);
+ReturnCode proc_get_attributes (const Target& i_target, AttributeList *attr_list);
+ReturnCode proc_get_extint_bias (uint32_t attr_mvpd_data[PV_D][PV_W], const AttributeList *attr, double *volt_int_vdd_bias, double *volt_int_vcs_bias);
+ReturnCode proc_boost_gpst (PstateSuperStructure *pss, uint32_t attr_boost_percent);
+ReturnCode proc_upd_cpmrange (PstateSuperStructure *pss, const AttributeList *attr);
+
// ----------------------------------------------------------------------
// Function definitions
// ----------------------------------------------------------------------
@@ -72,87 +76,53 @@ ReturnCode proc_get_attributes (const Target& i_target, AttributeList *attr_list
/// \retval ERROR defined in xml
ReturnCode
-p8_build_pstate_datablock(const Target& i_target, PstateSuperStructure *io_pss)
+p8_build_pstate_datablock(const Target& i_target,
+ PstateSuperStructure *io_pss)
{
fapi::ReturnCode l_rc;
int rc;
-
+
AttributeList attr;
ChipCharacterization* characterization;
uint8_t i = 0;
- double freq_bias = 1.0;
- double volt_bias_vdd = 1.0;
- double volt_bias_vcs = 1.0;
+ double volt_int_vdd_bias = 1.0;
+ double volt_int_vcs_bias = 1.0;
+
+ uint32_t frequency_step_khz = 0;
+ uint32_t attr_mvpd_voltage_control[PV_D][PV_W];
+
+ ivrm_mvpd_t ivrm_mvpd;
- uint32_t frequency_step_khz = 0;
- uint32_t attr_mvpd_voltage_control[PV_D][PV_W];
-
FAPI_INF("Executing p8_build_pstate_datablock ....");
-
+
// -------------------------
// get all attributes needed
// -------------------------
l_rc = proc_get_attributes(i_target , &attr );
- if (l_rc)
+ if (l_rc)
return l_rc;
-
- // -----------
- // get #V data
- // -----------
+
+ // calculate pstate frequency step in Khz
+ frequency_step_khz = (attr.attr_freq_proc_refclock * 1000)/attr.attr_proc_dpll_divider;
+
+ // ----------------
+ // get #V & #M data
+ // ----------------
// clear array
memset(attr_mvpd_voltage_control, 0, sizeof(attr_mvpd_voltage_control));
-
- l_rc = proc_get_mvpd_data(i_target , attr_mvpd_voltage_control);
- if (l_rc)
- return l_rc;
-
- // ----------------------------------------------------
- // Check Valid Frequency and Voltage Biasing Attributes
- // - cannot have both up and down bias set
- // ----------------------------------------------------
- if (attr.attr_freq_bias_up > 0 && attr.attr_freq_bias_down > 0) {
- FAPI_ERR("**** ERROR : Frequency bias up and down both defined");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_FREQ_BIAS_ERROR);
- return l_rc;
- }
+ memset(&ivrm_mvpd, 0, sizeof(ivrm_mvpd));
- if (attr.attr_voltage_ext_bias_up > 0 && attr.attr_voltage_ext_bias_down > 0) {
- FAPI_ERR("**** ERROR : External Frequency bias up and down both defined");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_EXT_VOLTAGE_BIAS_ERROR);
+ l_rc = proc_get_mvpd_data(i_target, attr_mvpd_voltage_control, &ivrm_mvpd);
+ if (l_rc)
return l_rc;
- }
- if (attr.attr_voltage_int_bias_up > 0 && attr.attr_voltage_int_bias_down > 0) {
- FAPI_ERR("**** ERROR : Internal Frequency bias up and down both defined");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_INT_VOLTAGE_BIAS_ERROR);
+ // ---------------------------------------------
+ // process external and internal bias attributes
+ // ---------------------------------------------
+ l_rc = proc_get_extint_bias(attr_mvpd_voltage_control, &attr, &volt_int_vdd_bias, &volt_int_vcs_bias);
+ if (l_rc)
return l_rc;
- }
-
- // --------------------------------------------------------------------
- // Apply specified Frequency and Voltage Biasing to attr_mvpd_voltage_control
- // - convert freq/voltage to double
- // - compute biased freq/voltage and round
- // - convert back to integer
- // - align frequency to frequency_step_khz (attr_freq_proc_refclock/attr_proc_dpll_divider)
- // - are (double) and (int) required???
- // --------------------------------------------------------------------
- frequency_step_khz = (attr.attr_freq_proc_refclock*1000)/attr.attr_proc_dpll_divider;
-
- freq_bias = 1.0 + (0.01 * (double)attr.attr_freq_bias_up) - (0.01 * (double)attr.attr_freq_bias_down); // at least one bias value is guaranteed to be 0
- volt_bias_vdd = 1.0 + (0.01 * (double)attr.attr_voltage_ext_bias_up) - (0.01 * (double)attr.attr_voltage_ext_bias_down); // at least one bias value is guaranteed to be 0
- volt_bias_vcs = 1.0 + (0.01 * (double)attr.attr_voltage_ext_bias_up) - (0.01 * (double)attr.attr_voltage_ext_bias_down); // at least one bias value is guaranteed to be 0
-
- // loop over each bucket
- for (i=0; i <= 4; i++) {
- attr_mvpd_voltage_control[i][0] = (uint32_t) ((( (double)attr_mvpd_voltage_control[i][0]) * freq_bias) + 0.5);
-
- // align to frequency step as defined by attr_proc_refclk_frequency/attr_proc_dpll_divider
- // jwy FIXME:caused float exception attr_mvpd_voltage_control[i][0] = (attr_mvpd_voltage_control[i][0] + (frequency_step_khz - (attr_mvpd_voltage_control[i][0]%frequency_step_khz))%frequency_step_khz);
-
- attr_mvpd_voltage_control[i][1] = (uint32_t) ((( (double)attr_mvpd_voltage_control[i][1]) * volt_bias_vdd) + 0.5); // vdd
- attr_mvpd_voltage_control[i][3] = (uint32_t) ((( (double)attr_mvpd_voltage_control[i][3]) * volt_bias_vcs) + 0.5); // vcs
- }
// -----------------------------------------------
// populate VpdOperatingPoint with MVPD attributes
@@ -169,7 +139,7 @@ p8_build_pstate_datablock(const Target& i_target, PstateSuperStructure *io_pss)
s132a_vpd[i].ics_500ma = attr_mvpd_voltage_control[pv_op_order[i]][4];
s132a_vpd[i].vcs_maxreg_5mv = attr_mvpd_voltage_control[pv_op_order[i]][3] - DEAD_ZONE_5MV;
}
-
+
// -------------------------------------------------------------------
// Create s132a_points and filled in by chip_characterization_create()
// -------------------------------------------------------------------
@@ -182,13 +152,12 @@ p8_build_pstate_datablock(const Target& i_target, PstateSuperStructure *io_pss)
// package/header drop is 100uOhm for both Vdd and Vcs.
OperatingPointParameters s132a_parms;
- s132a_parms.pstate0_frequency_khz = s132a_vpd[S132A_POINTS-1].frequency_mhz * 1000; // pstate0 is turbo
- s132a_parms.frequency_step_khz = frequency_step_khz; // ATTR_REFCLK_FREQUENCY/ATTR_DPLL_DIVIDER
-
- s132a_parms.vdd_load_line_uohm = 570; // hardcoded values to use temporarily per Adrian 4/11
- s132a_parms.vcs_load_line_uohm = 570; // hardcoded values to use temporarily per Adrian 4/11
- s132a_parms.vdd_distribution_uohm = 500; // hardcoded values to use temporarily per Adrian 4/11
- s132a_parms.vcs_distribution_uohm = 800; // hardcoded values to use temporarily per Adrian 4/11
+ s132a_parms.pstate0_frequency_khz = ((s132a_vpd[S132A_POINTS-1].frequency_mhz * 1000) / frequency_step_khz) * frequency_step_khz; // pstate0 is turbo rounded down and forced to be a multiple of freq_step_khz
+ s132a_parms.frequency_step_khz = frequency_step_khz; // ATTR_REFCLK_FREQUENCY/ATTR_DPLL_DIVIDER
+ s132a_parms.vdd_load_line_uohm = attr.attr_proc_r_loadline_vdd;
+ s132a_parms.vcs_load_line_uohm = attr.attr_proc_r_loadline_vcs;
+ s132a_parms.vdd_distribution_uohm = attr.attr_proc_r_distloss_vdd;
+ s132a_parms.vcs_distribution_uohm = attr.attr_proc_r_distloss_vcs;
// --------------------------------------
// Create Chip characterization structure
@@ -200,12 +169,6 @@ p8_build_pstate_datablock(const Target& i_target, PstateSuperStructure *io_pss)
s132a_characterization.parameters = &s132a_parms;
s132a_characterization.points = S132A_POINTS;
- // ------------------------------
- // Clear the PstateSuperStructure and install the magic number
- // ------------------------------
- memset(io_pss, 0, sizeof(*io_pss));
- (*io_pss).magic = revle64(PSTATE_SUPERSTRUCTURE_MAGIC);
-
// ---------------------------
// Finish the characterization
// ---------------------------
@@ -224,151 +187,329 @@ p8_build_pstate_datablock(const Target& i_target, PstateSuperStructure *io_pss)
return l_rc;
}
+ // -----------------------------------------------------------
+ // Clear the PstateSuperStructure and install the magic number
+ // -----------------------------------------------------------
+ memset(io_pss, 0, sizeof(*io_pss));
+ (*io_pss).magic = revle64(PSTATE_SUPERSTRUCTURE_MAGIC);
+
// ------------------------------
// Create the Global Pstate table
// ------------------------------
rc = gpst_create(&((*io_pss).gpst),
- characterization,
- PSTATE_STEPSIZE,
- EVRM_DELAY_NS);
-
- FAPI_DBG("gpst pmin = %d gpst entries = %d", (*io_pss).gpst.pmin, (*io_pss).gpst.entries);
- FAPI_DBG("attr_freq_proc_refclock = %d khz", (attr.attr_freq_proc_refclock*1000));
- FAPI_DBG("pstate0_freq = %d frequency_step = %d", s132a_parms.pstate0_frequency_khz, s132a_parms.frequency_step_khz);
- FAPI_DBG("vpd pmin = %d vpd pmax = %d vpd points = %d", s132a_characterization.ops[0].pstate, s132a_characterization.ops[s132a_characterization.points - 1].pstate, s132a_characterization.points);
-
+ characterization,
+ PSTATE_STEPSIZE,
+ EVRM_DELAY_NS);
+
+ FAPI_DBG("GPST vpd pmin = %d vpd pmax = %d vpd points = %d", s132a_characterization.ops[0].pstate, s132a_characterization.ops[s132a_characterization.points - 1].pstate, s132a_characterization.points);
+ FAPI_DBG("GPST pmin = %d entries = %u", (*io_pss).gpst.pmin, (*io_pss).gpst.entries);
+ FAPI_DBG("GPST refclock(Mhz) = %d pstate0_freq(Khz) = %d frequency_step(Khz) = %d", attr.attr_freq_proc_refclock, s132a_parms.pstate0_frequency_khz, s132a_parms.frequency_step_khz);
+
if (rc) {
int & RETURN_CODE = rc;
FAPI_ERR("**** ERROR : Procedure gpst_create() returned %d", rc);
FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ERROR);
return l_rc;
}
-
-// jwy // ---------------------
-// jwy // calculate safe_pstate
-// jwy // ---------------------
-// jwy Pstate psafe_pstate;
-// jwy rc = freq2pState(&((*io_pss).gpst), (attr.attr_pm_safe_frequency * 1000), &psafe_pstate);
-// jwy
-// jwy if (rc) {
-// jwy fprintf(stderr, " freq2pState() returned %d\n", rc);
-// jwy exit(1);
-// jwy }
-// jwy
-// jwy // pstate bounds checking
-// jwy Pstate pmax;
-// jwy pmax = (*io_pss).gpst.pmin + (*io_pss).gpst.entries - 1;
-// jwy
-// jwy if (psafe_pstate > pmax) {
-// jwy fprintf(stderr, " safe frequency pstate(%d) is greater than max pstate(%d)\n", psafe_pstate, pmax);
-// jwy exit(1);
-// jwy }
-// jwy
-// jwy if (psafe_pstate < (*io_pss).gpst.pmin)
-// jwy psafe_pstate = (*io_pss).gpst.pmin;
-// jwy
-// jwy (*io_pss).gpst.psafe = psafe_pstate;
-// jwy
-// jwy // -----------------------
-// jwy // calculate pvsafe pstate
-// jwy // -----------------------
-// jwy Pstate pvsafe_pstate;
-// jwy Vid11 pvsafe_vrm11;
-// jwy gpst_entry_t entry;
-// jwy
-// jwy rc = vuv2vrm11((attr.attr_pm_safe_voltage*1000), 1, &pvsafe_vrm11); // assume attr_pm_safe_voltage is in millivolts
-// jwy rc = gpst_vdd2pstate(&((*io_pss).gpst), pvsafe_vrm11, &pvsafe_pstate, &entry);
-// jwy (*io_pss).gpst.pvsafe = pvsafe_pstate;
-
-
-
- // Force optional overrides
- (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) |
- PSTATE_NO_INSTALL_LPSA |
- PSTATE_NO_INSTALL_RESCLK |
- PSTATE_FORCE_INITIAL_PMIN);
- // ------------------------------
- // Create the Global Pstate table
- // ------------------------------
- rc = lpst_create( &((*io_pss).gpst), &((*io_pss).lpsa), DEAD_ZONE_5MV);
-
- if (rc) {
-// int & RETURN_CODE = rc;
+
+ // -----------------------------
+ // Boost the Global Pstate table
+ // -----------------------------
+ l_rc = proc_boost_gpst (io_pss, attr.attr_cpm_turbo_boost_percent);
+ if (l_rc)
+ return l_rc;
+
+ // -----------------------------------------------------------------
+ // calculate safe_pstate & pvsafe pstate from attr_pm_safe_frequency
+ // -----------------------------------------------------------------
+// jwy Pstate psafe_pstate;
+// jwy rc = freq2pState(&((*io_pss).gpst), (attr.attr_pm_safe_frequency * 1000), &psafe_pstate);
+// jwy
+// jwy if (rc) {
+// jwy fprintf(stderr, " freq2pState() returned %d\n", rc);
+// jwy exit(1);
+// jwy }
+// jwy
+// jwy rc = pstate_minmax_chk(&(pss->gpst), &psafe_pstate);
+// jwy
+// jwy (*io_pss).gpst.psafe = psafe_pstate;
+// jwy (*io_pss).gpst.pvsafe = psafe_pstate;
+
+ // -----------------------------
+ // Create the Local Pstate table
+ // -----------------------------
+ rc = lpst_create( &((*io_pss).gpst), &((*io_pss).lpsa), DEAD_ZONE_5MV, volt_int_vdd_bias, volt_int_vcs_bias);
+
+ if (rc == -LPST_INVALID_OBJECT) {
+ int & RETURN_CODE = rc;
FAPI_ERR("**** ERROR : Procedure lpst_create() returned %d", rc);
- // FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ERROR);
- // return l_rc;
- }
-
- // print global pstate table
-// jwy gpst_print(stdout, &(*io_pss).gpst);
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_ERROR);
+ return l_rc;
+ }
+
+ if (rc == -LPST_GPST_WARNING) {
+ FAPI_INF("No Local Pstate Generated due Global Pstate Table data" );
+ }
+
+ // -----------------------
+ // Create VDS & VIN tables
+ // -----------------------
+ ivrm_parm_data_t ivrm_parms;
+
+ // Set defaults
+ ivrm_parms.vin_min = 600; // Minimum input voltage
+ ivrm_parms.vin_max = 1375; // Maximum input voltage
+ ivrm_parms.vin_table_step_size = 25; // Granularity of Vin table entries
+ ivrm_parms.vin_table_setsperrow = 4; // Vin sets per Vds row
+ ivrm_parms.vin_table_pfetstrperset = 8; // PFET Strength values per Vin set
+ ivrm_parms.vout_min = 600; // Minimum regulated output voltage
+ ivrm_parms.vout_max = 1200; // Maximum regulated output voltage
+ ivrm_parms.vin_entries_per_vds = 32; // Vin array entries per vds region
+ ivrm_parms.vds_min_range_upper_bound = 100; // Starting point for vds regions
+ ivrm_parms.vds_step_percent = 25; // vds region step muliplier
+ ivrm_parms.vds_region_entries = 16; // vds region array entries (in hardware)
+ ivrm_parms.pfetstr_default = 0x11; // Default PFET Strength with no calibration
+ ivrm_parms.positive_guardband = 11; // Plus side guardband (%)
+ ivrm_parms.negative_guardband = 6; // Negative side guardband (%)
+ ivrm_parms.number_of_coefficients = 4; // Number of coefficents in cal data
+ ivrm_parms.force_pfetstr_values = 1; // 0 - calculated; 1 = forced
+ ivrm_parms.forced_pfetstr_value = 0x03;
+
+ // create vds
+ build_vds_region_table(&ivrm_parms, io_pss);
+
+ // loop over chiplets and find ones with valid data
+ // break after first valid chiplet since superstructure does not handle separate vin table for each chiplet
+ for (i = 0; i < CHIPLETS; i++) {
+
+ if (ivrm_mvpd.data.ex[i].point_valid > 0) {
+
+ // perform least squares fit to get coefficients & then fill in VIN table
+ fit_file(ivrm_parms.number_of_coefficients,
+ ivrm_mvpd.header.version,
+ ivrm_mvpd.data.ex[3].Coef,
+ &(ivrm_mvpd.data.ex[3]) );
+
+ write_HWtab_bin(&ivrm_parms,
+ ivrm_mvpd.data.ex[3].Coef,
+ io_pss);
+ break;
+ }
+ }
+
+ // ---------------------------------------
+ // Update CPM Range info in Superstructure
+ // ---------------------------------------
+ l_rc = proc_upd_cpmrange (io_pss, &attr);
+ if (l_rc)
+ return l_rc;
+
+ // ------------------------
+ // Force optional overrides
+ // ------------------------
+ (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) |
+ PSTATE_NO_INSTALL_RESCLK |
+ PSTATE_FORCE_INITIAL_PMIN);
// Attributes to write
// -------------------
// uint32_t ATTR_PM_PSTATE0_FREQUENCY // Binary in Khz
return l_rc;
-}
-
+} // end p8_build_pstate_datablock
+/// -----------------------------------------------------------------------
/// \brief Get needed attributes
/// \param[in] i_target => Chip Target
/// \param[inout] attr => pointer to attribute list structure
+/// -----------------------------------------------------------------------
-ReturnCode proc_get_attributes(const Target& i_target, AttributeList *attr) {
+ReturnCode proc_get_attributes(const Target& i_target,
+ AttributeList *attr)
+{
ReturnCode l_rc;
+ int i = 0;
+
+ do
+ {
+ // --------------------------
+ // attributes not yet defined
+ // --------------------------
+ attr->attr_dpll_bias = 0;
+ attr->attr_undervolting = 0;
+
+ // ---------------------------------------------------------------
+ // set ATTR_PROC_DPLL_DIVIDER to 4 and do not read attribute value
+ attr->attr_proc_dpll_divider = 4;
+ FAPI_INF("ATTR_PROC_DPLL_DIVIDER - set to 4");
+
+ // ----------------------------
+ // attributes currently defined
+ // ----------------------------
+ #define DATABLOCK_GET_ATTR(attr_name, target, attr_assign) \
+ l_rc = FAPI_ATTR_GET(attr_name, target, attr->attr_assign); \
+ if (l_rc) break; \
+ FAPI_INF("%s = 0x%08x %u", #attr_name, attr->attr_assign, attr->attr_assign);
+
+ DATABLOCK_GET_ATTR(ATTR_FREQ_EXT_BIAS_UP, &i_target, attr_freq_ext_bias_up);
+ DATABLOCK_GET_ATTR(ATTR_FREQ_EXT_BIAS_DOWN, &i_target, attr_freq_ext_bias_down);
+ DATABLOCK_GET_ATTR(ATTR_VOLTAGE_EXT_VDD_BIAS_UP, &i_target, attr_voltage_ext_vdd_bias_up);
+ DATABLOCK_GET_ATTR(ATTR_VOLTAGE_EXT_VCS_BIAS_UP, &i_target, attr_voltage_ext_vcs_bias_up);
+ DATABLOCK_GET_ATTR(ATTR_VOLTAGE_EXT_VDD_BIAS_DOWN, &i_target, attr_voltage_ext_vdd_bias_down);
+ DATABLOCK_GET_ATTR(ATTR_VOLTAGE_EXT_VCS_BIAS_DOWN, &i_target, attr_voltage_ext_vcs_bias_down);
+ DATABLOCK_GET_ATTR(ATTR_VOLTAGE_INT_VDD_BIAS_UP, &i_target, attr_voltage_int_vdd_bias_up);
+ DATABLOCK_GET_ATTR(ATTR_VOLTAGE_INT_VCS_BIAS_UP, &i_target, attr_voltage_int_vcs_bias_up);
+ DATABLOCK_GET_ATTR(ATTR_VOLTAGE_INT_VDD_BIAS_DOWN, &i_target, attr_voltage_int_vdd_bias_down);
+ DATABLOCK_GET_ATTR(ATTR_VOLTAGE_INT_VCS_BIAS_DOWN, &i_target, attr_voltage_int_vcs_bias_down);
+ DATABLOCK_GET_ATTR(ATTR_FREQ_PROC_REFCLOCK, NULL, attr_freq_proc_refclock);
+ // jwy DATABLOCK_GET_ATTR(ATTR_PROC_DPLL_DIVIDER, &i_target, attr_proc_dpll_divider);
+ DATABLOCK_GET_ATTR(ATTR_FREQ_CORE_MAX, NULL, attr_freq_core_max);
+ DATABLOCK_GET_ATTR(ATTR_PM_SAFE_FREQUENCY, NULL, attr_pm_safe_frequency);
+ DATABLOCK_GET_ATTR(ATTR_BOOT_FREQ_MHZ, NULL, attr_boot_freq_mhz);
+ DATABLOCK_GET_ATTR(ATTR_CPM_TURBO_BOOST_PERCENT, NULL, attr_cpm_turbo_boost_percent);
+ DATABLOCK_GET_ATTR(ATTR_PROC_R_LOADLINE_VDD, NULL, attr_proc_r_loadline_vdd);
+ DATABLOCK_GET_ATTR(ATTR_PROC_R_LOADLINE_VCS, NULL, attr_proc_r_loadline_vcs);
+ DATABLOCK_GET_ATTR(ATTR_PROC_R_DISTLOSS_VDD, NULL, attr_proc_r_distloss_vdd);
+ DATABLOCK_GET_ATTR(ATTR_PROC_R_DISTLOSS_VCS, NULL, attr_proc_r_distloss_vcs);
+ DATABLOCK_GET_ATTR(ATTR_PROC_VRM_VOFFSET_VDD, NULL, attr_proc_vrm_voffset_vdd);
+ DATABLOCK_GET_ATTR(ATTR_PROC_VRM_VOFFSET_VCS, NULL, attr_proc_vrm_voffset_vcs);
+ DATABLOCK_GET_ATTR(ATTR_PM_RESONANT_CLOCK_FULL_CLOCK_SECTOR_BUFFER_FREQUENCY, NULL, attr_pm_resonant_clock_full_clock_sector_buffer_frequency);
+ DATABLOCK_GET_ATTR(ATTR_PM_RESONANT_CLOCK_LOW_BAND_LOWER_FREQUENCY, NULL, attr_pm_resonant_clock_low_band_lower_frequency);
+ DATABLOCK_GET_ATTR(ATTR_PM_RESONANT_CLOCK_LOW_BAND_UPPER_FREQUENCY, NULL, attr_pm_resonant_clock_low_band_upper_frequency);
+ DATABLOCK_GET_ATTR(ATTR_PM_RESONANT_CLOCK_HIGH_BAND_LOWER_FREQUENCY, NULL, attr_pm_resonant_clock_high_band_lower_frequency);
+ DATABLOCK_GET_ATTR(ATTR_PM_RESONANT_CLOCK_HIGH_BAND_UPPER_FREQUENCY, NULL, attr_pm_resonant_clock_high_band_upper_frequency);
+
+ // Read array attribute
+ l_rc = FAPI_ATTR_GET(ATTR_CPM_INFLECTION_POINTS, &i_target, attr->attr_cpm_inflection_points); if (l_rc) break;
+
+ for (i = 0; i < 16; i++) {
+ FAPI_INF("ATTR_CPM_INFLECTION_POINTS(%d) = 0x%08x %u",i, attr->attr_cpm_inflection_points[i], attr->attr_cpm_inflection_points[i]);
+ }
+
+ // --------------------------------------------------------------
+ // do basic attribute value checking and generate error if needed
+ // --------------------------------------------------------------
+
+ // jwy FIXME Add this error check once attr_pm_safe_frequency attribute is updated to be uint32
+ // jwy if (attr->attr_pm_safe_frequency > attr->attr_boot_freq_mhz) {
+ // jwy FAPI_ERR("ATTR_PM_SAFE_FREQUENCY (%u) is greater than ATTR_BOOT_FREQ_MHZ (%u)", attr->attr_pm_safe_frequency, attr->attr_boot_freq_mhz);
+ // jwy FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_ERROR);
+ // jwy return l_rc;
+ // jwy }
+
+ // ----------------------------------------------------
+ // Check Valid Frequency and Voltage Biasing Attributes
+ // - cannot have both up and down bias set
+ // ----------------------------------------------------
+ if (attr->attr_freq_ext_bias_up > 0 && attr->attr_freq_ext_bias_down > 0) {
+ FAPI_ERR("**** ERROR : Frequency bias up and down both defined");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_FREQ_BIAS_ERROR);
+ break;
+ }
+
+ if (attr->attr_voltage_ext_vdd_bias_up > 0 && attr->attr_voltage_ext_vdd_bias_down > 0) {
+ FAPI_ERR("**** ERROR : External voltage bias up and down both defined");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_EXT_VOLTAGE_BIAS_ERROR);
+ break;
+ }
+
+ if (attr->attr_voltage_ext_vcs_bias_up > 0 && attr->attr_voltage_ext_vcs_bias_down > 0) {
+ FAPI_ERR("**** ERROR : External voltage bias up and down both defined");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_EXT_VOLTAGE_BIAS_ERROR);
+ break;
+ }
+
+ if (attr->attr_voltage_int_vdd_bias_up > 0 && attr->attr_voltage_int_vdd_bias_down > 0) {
+ FAPI_ERR("**** ERROR : Internal voltage bias up and down both defined");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_INT_VOLTAGE_BIAS_ERROR);
+ break;
+ }
+
+ if (attr->attr_voltage_int_vcs_bias_up > 0 && attr->attr_voltage_int_vcs_bias_down > 0) {
+ FAPI_ERR("**** ERROR : Internal voltage bias up and down both defined");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_INT_VOLTAGE_BIAS_ERROR);
+ break;
+ }
+
+ // print debug message if double biasing is enabled
+ if ( (attr->attr_voltage_ext_vdd_bias_up + attr->attr_voltage_ext_vdd_bias_down > 0) &&
+ (attr->attr_voltage_int_vdd_bias_up + attr->attr_voltage_int_vdd_bias_down > 0) )
+ {
+ FAPI_DBG("Double Biasing enabled on external and internal VDD");
+ }
+
+ if ( (attr->attr_voltage_ext_vcs_bias_up + attr->attr_voltage_ext_vcs_bias_down > 0) &&
+ (attr->attr_voltage_int_vcs_bias_up + attr->attr_voltage_int_vcs_bias_down > 0) )
+ {
+ FAPI_DBG("Double Biasing enabled on external and internal VCS");
+ }
+
+ // ------------------------------------------------------
+ // do attribute default value setting if the are set to 0
+ // ------------------------------------------------------
+ if (attr->attr_freq_proc_refclock == 0){
+ attr->attr_freq_proc_refclock = 133;
+ FAPI_DBG("Attribute value was 0 - setting to default value ATTR_FREQ_PROC_REFCLOCK = 133");
+ }
+
+ if (attr->attr_pm_safe_frequency == 0) {
+ attr->attr_pm_safe_frequency = attr->attr_boot_freq_mhz;
+ FAPI_DBG("Attribute value was 0 - setting to default value ATTR_PM_SAFE_FREQUENCY = ATTR_BOOT_FREQ_MHZ");
+ }
+
+ if (attr->attr_proc_r_loadline_vdd == 0) {
+ attr->attr_proc_r_loadline_vdd = 570;
+ FAPI_DBG("Attribute value was 0 - setting to default value ATTR_PROC_R_LOADLINE_VDD = 570");
+ }
+
+ if (attr->attr_proc_r_loadline_vcs == 0) {
+ attr->attr_proc_r_loadline_vcs = 570;
+ FAPI_DBG("Attribute value was 0 - setting to default value ATTR_PROC_R_LOADLINE_VCS = 570");
+ }
+
+ if (attr->attr_proc_r_distloss_vdd == 0) {
+ attr->attr_proc_r_distloss_vdd = 500;
+ FAPI_DBG("Attribute value was 0 - setting to default value ATTR_PROC_R_DISTLOSS_VDD = 500");
+ }
+
+ if (attr->attr_proc_r_distloss_vcs == 0) {
+ attr->attr_proc_r_distloss_vcs = 800;
+ FAPI_DBG("Attribute value was 0 - setting to default value ATTR_PROC_R_DISTLOSS_VCS = 800");
+ }
+ } while (0);
- // --------------------------
- // attributes not yet defined
- // --------------------------
- attr->attr_dpll_bias = 0;
- attr->attr_undervolting = 0;
- attr->attr_freq_bias_up = 0;
- attr->attr_freq_bias_down = 0;
- attr->attr_voltage_ext_bias_up = 0;
- attr->attr_voltage_ext_bias_down = 0;
- attr->attr_voltage_int_bias_up = 0;
- attr->attr_voltage_int_bias_down = 0;
-
- attr->attr_dpll_bias = 0;
- attr->attr_undervolting = 0;
- attr->attr_pm_safe_voltage = 925; // assume millivolts until it is defined in attraibute
- attr->attr_proc_dpll_divider = 4;
-
- l_rc = FAPI_ATTR_GET(ATTR_FREQ_PROC_REFCLOCK, NULL, attr->attr_freq_proc_refclock); if (l_rc) return l_rc;
-// jwy l_rc = FAPI_ATTR_GET(ATTR_PROC_DPLL_DIVIDER, NULL, attr->attr_proc_dpll_divider); if (l_rc) return l_rc;
- l_rc = FAPI_ATTR_GET(ATTR_FREQ_CORE_MAX, NULL, attr->attr_freq_core_max); if (l_rc) return l_rc;
- l_rc = FAPI_ATTR_GET(ATTR_PROC_R_LOADLINE, NULL, attr->attr_proc_r_loadline); if (l_rc) return l_rc;
- l_rc = FAPI_ATTR_GET(ATTR_PROC_R_DISTLOSS, NULL, attr->attr_proc_r_distloss); if (l_rc) return l_rc;
- l_rc = FAPI_ATTR_GET(ATTR_PROC_VRM_VOFFSET, NULL, attr->attr_proc_vrm_voffset); if (l_rc) return l_rc;
-
- l_rc = FAPI_ATTR_GET(ATTR_PM_SAFE_FREQUENCY, NULL, attr->attr_pm_safe_frequency); if (l_rc) return l_rc;
-
- l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_FULL_CLOCK_SECTOR_BUFFER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_full_clock_sector_buffer_frequency); if (l_rc) return l_rc;
- l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_LOW_BAND_LOWER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_low_band_lower_frequency); if (l_rc) return l_rc;
- l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_LOW_BAND_UPPER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_low_band_upper_frequency); if (l_rc) return l_rc;
- l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_HIGH_BAND_LOWER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_high_band_lower_frequency); if (l_rc) return l_rc;
- l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_HIGH_BAND_UPPER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_high_band_upper_frequency); if (l_rc) return l_rc;
-
return l_rc;
}
+/// ----------------------------------------------------------------
/// \brief Get #V data and put into array
/// \param[in] i_target => Chip Target
/// \param[inout] attr_mvpd_data => 5x5 array to hold the #V data
+/// ----------------------------------------------------------------
-ReturnCode proc_get_mvpd_data(const Target& i_target, uint32_t attr_mvpd_data[PV_D][PV_W]) {
+ReturnCode proc_get_mvpd_data(const Target& i_target,
+ uint32_t attr_mvpd_data[PV_D][PV_W],
+ ivrm_mvpd_t *ivrm_mvpd)
+{
ReturnCode l_rc;
std::vector<fapi::Target> l_exChiplets;
- uint8_t l_functional = 0;
- uint8_t * l_buffer = reinterpret_cast<uint8_t *>(malloc(512) );
- uint32_t l_bufferSize = 512;
- uint32_t l_record = 0;
- uint32_t chiplet_mvpd_data[PV_D][PV_W];
- uint8_t j = 0;
- uint8_t i = 0;
- uint8_t ii = 0;
- uint8_t first_chplt = 1;
+ uint8_t l_functional = 0;
+ uint8_t * l_buffer = reinterpret_cast<uint8_t *>(malloc(512) );
+ uint8_t * l_buffer_pdm = reinterpret_cast<uint8_t *>(malloc(512) );
+ uint8_t * l_buffer_inc;
+ uint8_t * l_buffer_pdm_inc;
+ uint32_t l_bufferSize = 512;
+ uint32_t l_bufferSize_pdm = 512;
+ uint32_t l_record = 0;
+ uint32_t chiplet_mvpd_data[PV_D][PV_W];
+ uint8_t j = 0;
+ uint8_t i = 0;
+ uint8_t ii = 0;
+ uint8_t first_chplt = 1;
+ uint8_t version_pdm = 0;
+ uint8_t bucket_id = 0;
+ uint16_t cal_data[4];
// -----------------------------------------------------------------
// get list of chiplets and loop over each and get #V data from each
@@ -393,7 +534,8 @@ ReturnCode proc_get_mvpd_data(const Target& i_target, uint32_t attr_mvpd_data[PV
else {
if ( l_functional ) {
- l_bufferSize = 512;
+ l_bufferSize = 512;
+ l_bufferSize_pdm = 512;
uint8_t l_chipNum = 0xFF;
l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &l_exChiplets[j], l_chipNum);
if (l_rc) {
@@ -416,9 +558,9 @@ ReturnCode proc_get_mvpd_data(const Target& i_target, uint32_t attr_mvpd_data[PV
}
// check buffer size
- if (l_bufferSize < MVPD_BUFFER_SIZE) {
- FAPI_ERR("**** ERROR : Worng size buffer returned from fapiGetMvpdField => %d", l_bufferSize );
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_MVPD_BUFFER_SIZE_ERROR);
+ if (l_bufferSize < PDV_BUFFER_SIZE) {
+ FAPI_ERR("**** ERROR : Wrong size buffer returned from fapiGetMvpdField for #V => %d", l_bufferSize );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDV_BUFFER_SIZE_ERROR);
return l_rc;
}
@@ -427,15 +569,22 @@ ReturnCode proc_get_mvpd_data(const Target& i_target, uint32_t attr_mvpd_data[PV
// fill chiplet_mvpd_data 2d array with data iN buffer (skip first byte - bucket id)
#define UINT16_GET(__uint8_ptr) ((uint16_t)( ( (*((const uint8_t *)(__uint8_ptr)) << 8) | *((const uint8_t *)(__uint8_ptr) + 1) ) ))
- l_buffer++;
+
+ // use copy of allocated buffer pointer to increment through buffer
+ l_buffer_inc = l_buffer;
+
+ bucket_id = *l_buffer_inc;
+ l_buffer_inc++;
+
+ FAPI_DBG("#V chiplet = %u bucket id = %u", l_chipNum, bucket_id);
for (i=0; i<=4; i++) {
for (ii=0; ii<=4; ii++) {
- chiplet_mvpd_data[i][ii] = (uint32_t) UINT16_GET(l_buffer);
- FAPI_DBG("%04X %-6d", chiplet_mvpd_data[i][ii], chiplet_mvpd_data[i][ii]);
+ chiplet_mvpd_data[i][ii] = (uint32_t) UINT16_GET(l_buffer_inc);
+ FAPI_DBG("#V data = 0x%04X %-6d", chiplet_mvpd_data[i][ii], chiplet_mvpd_data[i][ii]);
// increment to next MVPD value in buffer
- l_buffer+= 2;
+ l_buffer_inc+= 2;
}
}
@@ -475,16 +624,249 @@ ReturnCode proc_get_mvpd_data(const Target& i_target, uint32_t attr_mvpd_data[PV
attr_mvpd_data[i][4] = chiplet_mvpd_data[i][4];
}
}
+
+ // --------------------------------------------
+ // Process #M Data
+ // --------------------------------------------
+
+ // Get Chiplet #M MVPD data
+ l_rc = fapiGetMvpdField((fapi::MvpdRecord)l_record,
+ fapi::MVPD_KEYWORD_PDM,
+ i_target,
+ l_buffer_pdm,
+ l_bufferSize_pdm);
+ if (!l_rc.ok()) {
+ FAPI_ERR("**** ERROR : Unexpected error encountered in fapiGetMvpdField");
+ return l_rc;
+ }
+
+ // check buffer size
+ if (l_bufferSize_pdm < PDM_BUFFER_SIZE) {
+ FAPI_ERR("**** ERROR : Wrong size buffer returned from fapiGetMvpdField for #M => %d", l_bufferSize_pdm );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDM_BUFFER_SIZE_ERROR);
+ return l_rc;
+ }
+
+ // use copy of allocated buffer pointer to increment through buffer
+ l_buffer_pdm_inc = l_buffer_pdm;
+
+ // get #M version and advance pointer 1-byte to beginning of #M data
+ version_pdm = *l_buffer_pdm_inc;
+ ivrm_mvpd->header.version = version_pdm ;
+ l_buffer_pdm_inc++;
+
+ // loop over 13 entries of #M data with 4 measurements per entry
+ FAPI_DBG("#M chiplet = %u version = %u", l_chipNum, version_pdm);
+
+ for (i=0; i<13; i++) {
+
+ for (ii=0; ii<4; ii++) {
+ cal_data[ii] = UINT16_GET(l_buffer_pdm_inc);
+ l_buffer_pdm_inc+= 2;
+ }
+
+ ivrm_mvpd->data.ex[j].point[i].gate_voltage = cal_data[0];
+ ivrm_mvpd->data.ex[j].point[i].drain_voltage = cal_data[1];
+ ivrm_mvpd->data.ex[j].point[i].source_voltage = cal_data[2];
+ ivrm_mvpd->data.ex[j].point[i].drain_current = cal_data[3];
+
+ FAPI_DBG("#M data = %5u %5u %5u %5u", cal_data[0], cal_data[1], cal_data[2], cal_data[3]);
+ }
+
+ // set number of samples to 13
+ ivrm_mvpd->data.ex[j].point_valid = 13;
+
} // end if l_functional
else { // Not Functional so skip it
}
}
} // end for loop
+ free (l_buffer);
+ free (l_buffer_pdm);
+
return l_rc;
} // end proc_get_mvpd_data
+/// ---------------------------------------------------------------------------
+/// \brief Check and process #V bias attributes for external and internal
+/// \param[in] attr_mvpd_data => 5x5 array to hold the #V data
+/// \param[in] *attr => pointer to attribute list structure
+/// \param[inout] * volt_int_vdd_bias => pointer to internal vdd bias
+/// \param[inout] * volt_int_vcs_bias => pointer to internal vcs bias
+/// ---------------------------------------------------------------------------
+ReturnCode proc_get_extint_bias(uint32_t attr_mvpd_data[PV_D][PV_W],
+ const AttributeList *attr,
+ double *volt_int_vdd_bias,
+ double *volt_int_vcs_bias)
+{
+ ReturnCode l_rc;
+ int i = 0;
+ double freq_bias = 1.0;
+ double volt_ext_vdd_bias = 1.0;
+ double volt_ext_vcs_bias = 1.0;
+
+ // --------------------------------------------------------------------------
+ // Apply specified Frequency and Voltage Biasing to attr_mvpd_voltage_control
+ // - at least one bias value is guaranteed to be 0
+ // - convert freq/voltage to double
+ // - compute biased freq/voltage and round
+ // - convert back to integer
+ // --------------------------------------------------------------------------
+
+ freq_bias = 1.0 + (BIAS_PCT_UNIT * (double)attr->attr_freq_ext_bias_up) - (BIAS_PCT_UNIT * (double)attr->attr_freq_ext_bias_down);
+ volt_ext_vdd_bias = 1.0 + (BIAS_PCT_UNIT * (double)attr->attr_voltage_ext_vdd_bias_up) - (BIAS_PCT_UNIT * (double)attr->attr_voltage_ext_vdd_bias_down);
+ volt_ext_vcs_bias = 1.0 + (BIAS_PCT_UNIT * (double)attr->attr_voltage_ext_vcs_bias_up) - (BIAS_PCT_UNIT * (double)attr->attr_voltage_ext_vcs_bias_down);
+ *volt_int_vdd_bias = 1.0 + (BIAS_PCT_UNIT * (double)attr->attr_voltage_int_vdd_bias_up) - (BIAS_PCT_UNIT * (double)attr->attr_voltage_int_vdd_bias_down);
+ *volt_int_vcs_bias = 1.0 + (BIAS_PCT_UNIT * (double)attr->attr_voltage_int_vcs_bias_up) - (BIAS_PCT_UNIT * (double)attr->attr_voltage_int_vcs_bias_down);
+
+ // loop over each operating point
+ for (i=0; i <= 4; i++) {
+ attr_mvpd_data[i][0] = (uint32_t) ((( (double)attr_mvpd_data[i][0]) * freq_bias) + 0.5);
+ attr_mvpd_data[i][1] = (uint32_t) ((( (double)attr_mvpd_data[i][1]) * volt_ext_vdd_bias) + 0.5);
+ attr_mvpd_data[i][3] = (uint32_t) ((( (double)attr_mvpd_data[i][3]) * volt_ext_vcs_bias) + 0.5);
+ }
+
+ FAPI_DBG("BIAS freq = %f", freq_bias);
+ FAPI_DBG("BIAS vdd ext = %f vcs ext = %f", volt_ext_vdd_bias, volt_ext_vcs_bias);
+ FAPI_DBG("BIAS vdd int = %f vcs int = %f", *volt_int_vdd_bias, *volt_int_vcs_bias);
+
+ return l_rc;
+} // end proc_get_extint_bias
+
+
+/// ------------------------------------------------------------
+/// \brief Update CPM Range table
+/// \param[inout] *pss => pointer to pstate superstructure
+/// \param[in] *attr => pointer to attribute list structure
+/// ------------------------------------------------------------
+
+ReturnCode proc_upd_cpmrange (PstateSuperStructure *pss,
+ const AttributeList *attr)
+{
+ ReturnCode l_rc;
+ int rc = 0;
+ uint8_t i = 0;
+ uint8_t valid_points = 0;
+ Pstate pstate;
+ uint32_t freq_khz;
+
+ do
+ {
+ // extract valid points from attribute and put into superstructure
+ valid_points = attr->attr_cpm_inflection_points[8];
+ pss->cpmranges.validRanges = valid_points;
+
+ FAPI_DBG("CPM valid points = %u", valid_points);
+
+ // loop over valid points in attribute and convert to Khz and then convert to pstate value
+ for (i = 0; i < valid_points; i++) {
+ freq_khz = attr->attr_cpm_inflection_points[i] * revle32(pss->gpst.frequency_step_khz);
+ rc = freq2pState(&(pss->gpst), freq_khz, &pstate); if (rc) break;
+ rc = pstate_minmax_chk(&(pss->gpst), &pstate); if (rc) break;
+ pss->cpmranges.inflectionPoint[i] = pstate;
+
+ FAPI_DBG("CPM point freq_khz = %u pstate = %d",freq_khz, pstate);
+ }
+
+ if (rc) break;
+
+ // convert pMax attribute to Khz and then convert to pstate value
+ freq_khz = attr->attr_cpm_inflection_points[9] * revle32(pss->gpst.frequency_step_khz);
+ rc = freq2pState(&(pss->gpst), freq_khz, &pstate); if (rc) break;
+ rc = pstate_minmax_chk(&(pss->gpst), &pstate); if (rc) break;
+ pss->cpmranges.pMax = pstate;
+
+ FAPI_DBG("CPM pMax freq_khz = %u pstate = %d",freq_khz, pstate);
+ } while (0);
+
+ // ------------------------------------------------------
+ // check error code from freq2pState or pstate_minmax_chk
+ // ------------------------------------------------------
+ if (rc) {
+ int & RETURN_CODE = rc;
+
+ if (rc == -PSTATE_LT_PSTATE_MIN || rc == -PSTATE_LT_PSTATE_MIN) {
+ FAPI_ERR("**** ERROR : Computed pstate for freq (%d khz) out of bounds of MAX/MIN possible rc = %d", freq_khz, rc);
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PSTATE_MINMAX_BOUNDS_ERROR);
+ }
+ else if (rc == -GPST_PSTATE_GT_GPST_PMAX){
+ FAPI_ERR("**** ERROR : Computed pstate is greater than max pstate in gpst (max pstate = %d computed pstate = %d rc = %d", pstate, gpst_pmax(&(pss->gpst)), rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PSTATE_GT_GPSTPMAX_ERROR);
+ }
+ else {
+ FAPI_ERR("**** ERROR : Bad Return code rc = %d", rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_ERROR);
+ }
+ }
+
+ return l_rc;
+} // end proc_upd_cpmrange
+
+
+/// -------------------------------------------------------------------
+/// \brief Boost max frequency in pstate table based on boost attribute
+/// \param[inout] *pss => pointer to pstate superstructure
+/// \param[in] *attr => pointer to attribute list structure
+/// -------------------------------------------------------------------
+
+ReturnCode proc_boost_gpst (PstateSuperStructure *pss,
+ uint32_t attr_boost_percent)
+{
+ ReturnCode l_rc;
+ uint8_t i;
+ uint8_t idx;
+ double boosted_pct;
+ uint32_t boosted_freq_khz;
+ uint32_t pstate0_frequency_khz;
+ uint32_t frequency_step_khz;
+ uint32_t pstate_diff;
+ gpst_entry_t entry;
+ uint8_t gpsi_max;
+
+ // calculate percent to boost
+ boosted_pct = 1.0 + (BOOST_PCT_UNIT * (double)attr_boost_percent);
+
+ // get turbo frequency (pstate0 frequency)
+ pstate0_frequency_khz = revle32(pss->gpst.pstate0_frequency_khz);
+
+ // get pstate frequency step
+ frequency_step_khz = revle32(pss->gpst.frequency_step_khz);
+
+ // calculate boosted frequency
+ boosted_freq_khz = (uint32_t) ( (double)pstate0_frequency_khz * boosted_pct);
+
+ // if boosted frequency is <= turbo frequency, then no boost is to be done
+ if (boosted_freq_khz <= pstate0_frequency_khz)
+ return l_rc;
+
+ // calculate # pstates that boosted frequency is above turbo
+ pstate_diff = (boosted_freq_khz/frequency_step_khz) - (pstate0_frequency_khz/frequency_step_khz);
+
+ // pstate difference is 0 then no boost is to be done, else update global pstate table
+ if (pstate_diff == 0) {
+ return l_rc;
+ }
+ else {
+ gpsi_max = pss->gpst.entries - 1;
+ entry.value = revle64(pss->gpst.pstate[gpsi_max].value);
+
+ FAPI_DBG("Boosting Pstate Table : %% = %f num pstates added = %d", boosted_pct, pstate_diff);
+
+ for (i = 1; i <= pstate_diff; i++) {
+ idx = gpsi_max + i;
+ pss->gpst.pstate[idx].value = revle64(entry.value);
+ }
+
+ pss->gpst.entries += pstate_diff;
+
+ }
+
+ return l_rc;
+} // end proc_boost_gpst
+
+
} //end extern C
diff --git a/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.H b/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.H
index e883fc819..94a46f059 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.H
+++ b/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.H
@@ -20,7 +20,7 @@
/* Origin: 30 */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: p8_build_pstate_datablock.H,v 1.7 2013/05/03 15:57:32 jimyac Exp $
+// $Id: p8_build_pstate_datablock.H,v 1.9 2013/09/17 16:43:44 jimyac Exp $
#ifndef _P8_BUILD_PSTATE_DATABLOCK_H_
#define _P8_BUILD_PSTATE_DATABLOCK_H_
@@ -44,9 +44,12 @@ fapi::ReturnCode p8_build_pstate_datablock(const fapi::Target& i_target, PstateS
#define S132A_POINTS 3
#define PSTATE_STEPSIZE 1
-#define EVRM_DELAY_NS 100
-#define DEAD_ZONE_5MV 20
-#define MVPD_BUFFER_SIZE 51
+#define EVRM_DELAY_NS 100
+#define DEAD_ZONE_5MV 20
+#define PDV_BUFFER_SIZE 51
+#define PDM_BUFFER_SIZE 105
+#define BIAS_PCT_UNIT 0.005
+#define BOOST_PCT_UNIT 0.001
// #V 2 dimensional array values (5x5) - 5 operating point and 5 values per operating point
#define PV_D 5
@@ -55,18 +58,35 @@ fapi::ReturnCode p8_build_pstate_datablock(const fapi::Target& i_target, PstateS
// order of operating points from slow to fast in #V
// 1=pwrsave 0=nominal 2=turbo
const uint8_t pv_op_order[S132A_POINTS] = {1, 0, 2};
+#define PV_OP_ORDER {1, 0, 2}
typedef struct {
- uint32_t attr_freq_core_max; // = 0; // MHz
- uint32_t attr_proc_r_loadline; // = 0; // Impedance (binary in microOhms)
- uint32_t attr_proc_r_distloss; // = 0; // Impedance (binary in microOhms)
- uint32_t attr_proc_vrm_voffset; // = 0; // Offset voltage (binary in microvolts)
-
- uint32_t attr_freq_proc_refclock; // = 133 ; // Mhz
+ uint32_t attr_freq_core_max;
+ uint32_t attr_proc_r_loadline_vdd;
+ uint32_t attr_proc_r_loadline_vcs;
+ uint32_t attr_proc_r_distloss_vdd;
+ uint32_t attr_proc_r_distloss_vcs;
+ uint32_t attr_proc_vrm_voffset_vdd;
+ uint32_t attr_proc_vrm_voffset_vcs;
+ uint32_t attr_voltage_ext_vdd_bias_up;
+ uint32_t attr_voltage_ext_vcs_bias_up;
+ uint32_t attr_voltage_ext_vdd_bias_down;
+ uint32_t attr_voltage_ext_vcs_bias_down;
+ uint32_t attr_voltage_int_vdd_bias_up;
+ uint32_t attr_voltage_int_vcs_bias_up;
+ uint32_t attr_voltage_int_vdd_bias_down;
+ uint32_t attr_voltage_int_vcs_bias_down ;
+
+ uint32_t attr_proc_r_loadline; // = 0; // Impedance (binary in microOhms)
+ uint32_t attr_proc_r_distloss; // = 0; // Impedance (binary in microOhms)
+ uint32_t attr_proc_vrm_voffset; // = 0; // Offset voltage (binary in microvolts)
+
+ uint32_t attr_freq_proc_refclock; // = 133333 ; // Khz
uint32_t attr_proc_dpll_divider; // = 4;
-
- uint32_t attr_freq_bias_up; // = 0;
- uint32_t attr_freq_bias_down; // = 0;
+ uint32_t attr_cpm_turbo_boost_percent; // binary in 0.1 percent steps
+ uint32_t attr_cpm_inflection_points[16];
+ uint32_t attr_freq_ext_bias_up; // = 0;
+ uint32_t attr_freq_ext_bias_down; // = 0;
uint32_t attr_voltage_ext_bias_up; // = 0;
uint32_t attr_voltage_ext_bias_down; // = 0;
uint32_t attr_voltage_int_bias_up; // = 0;
@@ -74,9 +94,9 @@ typedef struct {
uint32_t attr_dpll_bias;
uint32_t attr_undervolting;
- uint32_t attr_pm_safe_voltage;
- uint8_t attr_pm_safe_frequency; // = 0; // pstate value -128 thru 127 *** FIXME - comes in as unsigned, how to I make signed???
-
+ uint8_t attr_pm_safe_frequency;
+ uint32_t attr_boot_freq_mhz;
+
uint32_t attr_pm_resonant_clock_full_clock_sector_buffer_frequency; // = 0; // Mhz
uint32_t attr_pm_resonant_clock_low_band_lower_frequency; // = 0; // Mhz
uint32_t attr_pm_resonant_clock_low_band_upper_frequency; // = 0; // Mhz
diff --git a/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml b/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml
index 04d3585c8..4acf8267d 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml
+++ b/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml
@@ -20,16 +20,21 @@
<!-- Origin: 30 -->
<!-- -->
<!-- IBM_PROLOG_END_TAG -->
-<!-- $Id: p8_build_pstate_datablock_errors.xml,v 1.5 2013/05/03 16:10:11 jimyac Exp $ -->
+<!-- $Id: p8_build_pstate_datablock_errors.xml,v 1.7 2013/09/17 16:37:19 jimyac Exp $ -->
<!-- Error definitions for p8_build_pstate_datablock procedure -->
<hwpErrors>
<!-- *********************************************************************** -->
<hwpError>
- <rc>RC_PROCPM_PSTATE_DATABLOCK_MVPD_BUFFER_SIZE_ERROR</rc>
- <description>MVPD Buffer returned is wrong size</description>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_PDV_BUFFER_SIZE_ERROR</rc>
+ <description>#V Buffer returned is wrong size</description>
</hwpError>
<!-- *********************************************************************** -->
<hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_PDM_BUFFER_SIZE_ERROR</rc>
+ <description>#M Buffer returned is wrong size</description>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
<rc>RC_PROCPM_PSTATE_MVPD_CHIPLET_VOLTAGE_NOT_EQUAL</rc>
<description>MVPD Bucket Frequency was not equal per chiplet</description>
</hwpError>
@@ -60,4 +65,28 @@
<description>Procedure gpst_create() returned an error</description>
<ffdc>RETURN_CODE</ffdc>
</hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_ERROR</rc>
+ <description>Procedure lpst_create() returned an error</description>
+ <ffdc>RETURN_CODE</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_PSTATE_MINMAX_BOUNDS_ERROR</rc>
+ <description>freq2pState returned error - computed pstate for freq is out of bounds of MAX/MIN possible</description>
+ <ffdc>RETURN_CODE</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_PSTATE_GT_GPSTPMAX_ERROR</rc>
+ <description>pstate_minmax_chk returned error - Computed pstate is greater than max pstate in gpst</description>
+ <ffdc>RETURN_CODE</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_ERROR</rc>
+ <description>Bad Return code</description>
+ <ffdc>RETURN_CODE</ffdc>
+ </hwpError>
</hwpErrors>
diff --git a/src/usr/hwpf/hwp/pstates/pstates/p8_ivrm.H b/src/usr/hwpf/hwp/pstates/pstates/p8_ivrm.H
new file mode 100644
index 000000000..3ab7f0fc9
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/p8_ivrm.H
@@ -0,0 +1,110 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/p8_ivrm.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: p8_ivrm.H,v 1.1 2013/08/13 17:13:00 jimyac Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/p8_ivrm.H,v $
+//------------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//------------------------------------------------------------------------------
+// *! OWNER NAME: Greg Still Email: stillgs@us.ibm.com
+// *!
+// *! General Description:
+// *! #M IVRM Vital Product Data Structure
+//------------------------------------------------------------------------------
+//
+//
+//
+// 4 x 2B = 8B per measurement
+typedef struct IVRM_MEASUREMENT {
+ uint16_t gate_voltage; // V1: mV, V2: uV
+ uint16_t drain_voltage; // V1: mV, V2: uV
+ uint16_t source_voltage; // V1: mV, V2: uV
+ uint16_t drain_current; // V1: mA, V2: uA
+} ivrm_measurement_t;
+
+// 8B x 32 measurements = 256B cal data
+#define IVRM_CAL_POINTS 32
+typedef struct IVRM_CAL_DATA {
+ uint32_t point_valid; // bit vector indicating valid points
+ double Coef[4];
+ ivrm_measurement_t point[IVRM_CAL_POINTS];
+} ivrm_cal_data_t;
+
+#define MURANO 1
+
+#ifdef MURANO
+#define CHIPLETS 6
+#elif VENICE
+#define CHIPLETS 12
+#endif
+
+// Murano: 256B x 6 = 1036B + 2 (temp) = 1038B
+// Venice: 256B x 12 = 2072B + 2 (temp) = 2074B
+
+typedef struct IVRM_EX_CAL_DATA
+{
+ uint16_t temp; // binary in degrees C
+ uint16_t ex_valid; // bit vector of valid chiplets, left justified
+ ivrm_cal_data_t ex[CHIPLETS];
+} ivrm_ex_cal_data_t;
+
+// 4 byte header
+typedef struct IVRM_MVPD_HEADER
+{
+ char name[2]; // Two character ID
+ uint8_t length; // Version 1: milli units; Version 2: micro units
+ uint8_t version;
+} ivrm_mvpd_header_t;
+
+
+typedef struct IVRM_MVPD
+{
+ ivrm_mvpd_header_t header;
+ ivrm_ex_cal_data_t data;
+} ivrm_mvpd_t;
+
+// Chiplet numbering to indexing needs translation if VPD is held "packed"
+// (eg 0:5 for Murano; 0:11 for Venice)
+//
+// Murano translation
+// Index 0 <> EX 4
+// Index 1 <> EX 5
+// Index 2 <> EX 6
+// Index 3 <> EX C (12)
+// Index 4 <> EX D (13)
+// Index 5 <> EX E (14)
+//
+// Venice translation
+// Index 0 <> EX 1
+// Index 1 <> EX 2
+// Index 2 <> EX 3
+// Index 3 <> EX 4
+// Index 4 <> EX 5
+// Index 5 <> EX 6
+// Index 6 <> EX 9
+// Index 7 <> EX A (10)
+// Index 8 <> EX B (11)
+// Index 9 <> EX C (12)
+// Index 10 <> EX D (13)
+// Index 11 <> EX E (14)
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c
index 5212b1a76..a299e5fb7 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c
@@ -20,7 +20,7 @@
/* Origin: 30 */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: pstate_tables.c,v 1.8 2013/06/12 20:02:07 mjjones Exp $
+// $Id: pstate_tables.c,v 1.10 2013/09/17 16:36:39 jimyac Exp $
/// \file pstate_tables.c
/// \brief This file contains code used to generate Pstate tables from real or
@@ -30,12 +30,12 @@
/// always "given" to OCC either from the FSP (OCC product firmware), or by
/// being built-in the image (lab images).
+#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include "lab_pstates.h"
#include "pstate_tables.h"
-
#define MAX(X, Y) \
({ \
typeof (X) __x = (X); \
@@ -209,7 +209,7 @@ chip_characterization_create(ChipCharacterization *characterization,
ops[gpst_points].idd_ma = vpd[i].idd_500ma * 500;
ops[gpst_points].ics_ma = vpd[i].ics_500ma * 500;
-
+
ops[gpst_points].frequency_khz = vpd[i].frequency_mhz * 1000;
// 'Corrected' voltages values add in the load-line & distribution IR drop
@@ -268,7 +268,9 @@ chip_characterization_create(ChipCharacterization *characterization,
//
// \retval -GPST_INVALID_ARGUMENT Either argument was invalid in some way.
-#define NEST_FREQUENCY_KHZ 2400000
+// jwy if we use this proc in future, do not use this value for nest freq
+// instead, use the value of attribute ATTR_FREQ_PB
+#define NEST_FREQ_KHZ 2400000
int
gpst_stepping_setup(GlobalPstateTable* gpst,
@@ -293,13 +295,15 @@ gpst_stepping_setup(GlobalPstateTable* gpst,
// This is the frequency of the VRM stepper 'tick'. The base time
// source for VRM stepping is therefore nest clock / 8.
- cycles = (((NEST_FREQUENCY_KHZ / 1000) * vrm_delay_ns) / 1000) /
+ cycles = (((NEST_FREQ_KHZ / 1000) * vrm_delay_ns) / 1000) /
(1 << LOG2_VRM_STEPDELAY_DIVIDER);
// Normalize the exponential encoding
sigbits = 32 - cntlz32(cycles);
- stepdelay_range = (sigbits - VRM_STEPDELAY_RANGE_BITS);
+// jwy stepdelay_range = MAX(0, sigbits - VRM_STEPDELAY_RANGE_BITS);
+
+ stepdelay_range = (sigbits - VRM_STEPDELAY_RANGE_BITS);
if (stepdelay_range < 0)
{
@@ -364,12 +368,14 @@ gpst_entry_create(gpst_entry_t *entry, OperatingPoint *op)
gpe.fields.gpe_field = vid;
__SET(vrm11, ROUND_VOLTAGE_UP, evid_vdd, vdd_corrected_uv);
- __SET(vrm11, ROUND_VOLTAGE_UP, evid_vcs, vcs_corrected_uv);
- __SET(ivid, ROUND_VOLTAGE_DOWN, evid_vdd_eff, vdd_ivrm_effective_uv);
- __SET(ivid, ROUND_VOLTAGE_DOWN, evid_vcs_eff, vcs_ivrm_effective_uv);
- __SET(ivid, ROUND_VOLTAGE_DOWN, maxreg_vdd, vdd_maxreg_uv);
- __SET(ivid, ROUND_VOLTAGE_DOWN, maxreg_vcs, vcs_maxreg_uv);
+ __SET(vrm11, ROUND_VOLTAGE_UP, evid_vcs, vcs_corrected_uv);
+ __SET(ivid, ROUND_VOLTAGE_DOWN, evid_vdd_eff, vdd_ivrm_effective_uv);
+ __SET(ivid, ROUND_VOLTAGE_DOWN, evid_vcs_eff, vcs_ivrm_effective_uv);
+ __SET(ivid, ROUND_VOLTAGE_DOWN, maxreg_vdd, vdd_maxreg_uv);
+ __SET(ivid, ROUND_VOLTAGE_DOWN, maxreg_vcs, vcs_maxreg_uv);
+ ;
+
// Add the check byte
uint8_t gpstCheckByte(uint64_t gpstEntry);
@@ -510,6 +516,8 @@ gpst_create(GlobalPstateTable *gpst,
// Set the Pmin Pstate
+ for (i = 0; i < points; i++)
+
entry = 0;
if (gpst_entry_create(&(gpst->pstate[entry]), &(ops[0]))) {
rc = -GPST_INVALID_ENTRY;
@@ -576,52 +584,101 @@ gpst_create(GlobalPstateTable *gpst,
}
+/// Create a local Pstate table
+///
+/// \param gpst A pointer to a GlobalPstateTable structure for lookup.
+///
+/// \param lpsa Apointer to a LocalPstateArray structure to populate
+///
+/// \param dead_zone_5mv dead zone value
+///
+/// \param evrm_delay_ns External VRM delay in nano-seconds
+///
+/// This routine creates a LocalPstateArray by using the dead zone value and
+/// data in the GlobalPstateTable
+///
+/// \retval 0 Success
+///
+/// \retval -LPST_INVALID_OBJECT Either the \a gpst or \a lpsa were NULL (0) or
+/// obviously invalid or incorrectly initialized.
+///
+/// \retval -LPST_INVALID_ARGUMENT indicates that the difference between
+/// pmax & pmin in gpst is less than deadzone voltage (ie. no data to build lpsa)
int
-lpst_create(const GlobalPstateTable *gpst, LocalPstateArray *lpsa, const uint8_t dead_zone_5mv)
+lpst_create(const GlobalPstateTable *gpst,
+ LocalPstateArray *lpsa,
+ const uint8_t dead_zone_5mv,
+ double volt_int_vdd_bias,
+ double volt_int_vcs_bias)
{
- int rc = 0;
+ int rc = 0;
int i,j;
gpst_entry_t entry;
uint32_t turbo_uv;
+ uint32_t gpst_uv;
uint32_t v_uv;
uint32_t vdd_uv;
- uint8_t v_ivid;
+ uint8_t v_ivid;
+ uint8_t gpst_ivid;
+ int lpst_max_found = 0;
uint32_t lpst_max_uv;
uint8_t lpst_entries;
uint8_t lpst_entries_div4;
uint8_t gpst_index;
- Pstate lpst_pmin;
+ Pstate lpst_pmin;
+ Pstate lpst_pstate;
+ Pstate lpst_max_pstate = 0;
uint8_t vid_incr[3] = {0,0,0};
+ uint8_t steps_above_curr;
+ uint8_t steps_below_curr;
+ uint8_t inc_step;
+ uint8_t dec_step;
do {
// Basic pointer checks
- if (lpsa == 0) {
+ if ((gpst == 0) || (lpsa == 0)) {
rc = -LPST_INVALID_OBJECT;
break;
}
-
+
// ------------------------------------------------------------------
// find lspt_max in gpst
// - lpst_max is gpst entry that is equal to (turbo_vdd - deadzone)
// ------------------------------------------------------------------
entry.value = revle64(gpst->pstate[(gpst->entries)-1].value);
- rc = vrm112vuv(entry.fields.evid_vdd, &turbo_uv);
+ rc = vrm112vuv(entry.fields.evid_vdd, &turbo_uv); if (rc) break;
+
+ turbo_uv = (uint32_t) (turbo_uv * volt_int_vdd_bias);
lpst_max_uv = turbo_uv - (dead_zone_5mv * 5000);
- for (i = gpst->entries -1 ; i >= 0; i--) {
- entry.value = revle64(gpst->pstate[i].value);
- vrm112vuv(entry.fields.evid_vdd, &v_uv);
+ for (i = gpst->entries - 1 ; i >= 0; i--) {
+ entry.value = revle64(gpst->pstate[i].value);
+ rc = vrm112vuv(entry.fields.evid_vdd, &v_uv); if (rc) break;
+ v_uv = (uint32_t) (v_uv * volt_int_vdd_bias);
- if (lpst_max_uv >= v_uv)
- break;
+ if (lpst_max_uv >= v_uv) {
+ lpst_max_found = 1;
+ lpst_max_pstate = gpst_pmax(gpst) - (gpst->entries - i - 1);
+ break;
+ }
+ }
+
+ if (rc) break;
+
+ // generate a warning if lpst max not found
+ // - indicates that the difference between pmax & pmin in gpst is less than deadzone voltage
+ // - no data will be in lpst (lpst entries = 0)
+ if (lpst_max_found == 0) {
+ rc = -LPST_GPST_WARNING;
+ break;
}
-
- lpst_entries = i + 1;
- lpst_pmin = 0 - lpst_entries + 1;
-// jwy printf("turbo_uv = %d lpst_max_uv = %d entries = %d lpst_pmin = %d\n", turbo_uv, lpst_max_uv, lpst_entries, lpst_pmin);
+ lpst_entries = gpst->entries;
+ lpst_pmin = gpst->pmin;
+
+// jwy printf("turbo_uv = %d lpst_max_uv = %d entries = %d lpst_pmin = %d lpst_max_pstate = %d i = %d\n", turbo_uv, lpst_max_uv, lpst_entries, lpst_pmin, lpst_max_pstate, i);
// ----------------------------------------------------------------------------
// now loop over gpst from 0 to lpst_entries and fill in lpst from data in gpst
@@ -631,18 +688,23 @@ lpst_create(const GlobalPstateTable *gpst, LocalPstateArray *lpsa, const uint8_t
lpst_entries_div4 = lpst_entries/4;
if ( lpst_entries % 4 != 0)
lpst_entries_div4++;
-
+
+ // current lpst pstate value as table is created
+ lpst_pstate = gpst_pmin(gpst);
+
for (i = 0 ; i < lpst_entries_div4; i++) {
entry.value = revle64(gpst->pstate[gpst_index].value);
// compute ivid_vdd
- rc = vrm112vuv(entry.fields.evid_vdd, &vdd_uv);
- rc = vuv2ivid(vdd_uv, ROUND_VOLTAGE_DOWN, &v_ivid);
+ rc = vrm112vuv(entry.fields.evid_vdd, &vdd_uv); if (rc) break;
+ vdd_uv = (uint32_t) (vdd_uv * volt_int_vdd_bias);
+ rc = vuv2ivid(vdd_uv, ROUND_VOLTAGE_DOWN, &v_ivid); if (rc) break;
lpsa->pstate[i].fields.ivid_vdd = v_ivid;
// compute ivid_vcs
- rc = vrm112vuv(entry.fields.evid_vcs, &v_uv);
- rc = vuv2ivid(v_uv, ROUND_VOLTAGE_DOWN, &v_ivid);
+ rc = vrm112vuv(entry.fields.evid_vcs, &v_uv); if (rc) break;
+ v_uv = (uint32_t) (v_uv * volt_int_vcs_bias);
+ rc = vuv2ivid(v_uv, ROUND_VOLTAGE_DOWN, &v_ivid); if (rc) break;
lpsa->pstate[i].fields.ivid_vcs = v_ivid;
// --------------------------------------------------------------
@@ -654,14 +716,37 @@ lpst_create(const GlobalPstateTable *gpst, LocalPstateArray *lpsa, const uint8_t
for (j = 0; j <= 2; j++) {
gpst_index++;
- if (gpst_index > lpst_entries)
- break;
+ if (gpst_index >= lpst_entries)
+ break;
entry.value = revle64(gpst->pstate[gpst_index].value);
- rc = vrm112vuv(entry.fields.evid_vdd, &vdd_uv);
- rc = vuv2ivid(vdd_uv, ROUND_VOLTAGE_DOWN, &v_ivid);
+ rc = vrm112vuv(entry.fields.evid_vdd, &vdd_uv); if (rc) break;
+ vdd_uv = (uint32_t) (vdd_uv * volt_int_vdd_bias);
+ rc = vuv2ivid(vdd_uv, ROUND_VOLTAGE_DOWN, &v_ivid); if (rc) break;
vid_incr[j] = v_ivid - lpsa->pstate[i].fields.ivid_vdd;
+
+ // point to next lpst pstate
+ lpst_pstate++;
+
+ // the max for this field is 7, so clip to 7 if it's > 7
+ if (vid_incr[j] > 7) {
+ vid_incr[j] = 7;
+
+ // if in regulation, return an error
+ if (lpst_pstate <= lpst_max_pstate) {
+ rc = -LPST_INCR_CLIP_ERROR ;
+ break;
+ }
+
+ // if not in regulation, return a warning
+ if (lpst_pstate > lpst_max_pstate) {
+// rc = 2;
+// break;
+ }
+ }
+
}
+ if (rc) break;
lpsa->pstate[i].fields.ps1_vid_incr = vid_incr[0];
lpsa->pstate[i].fields.ps2_vid_incr = vid_incr[1];
@@ -682,18 +767,78 @@ lpst_create(const GlobalPstateTable *gpst, LocalPstateArray *lpsa, const uint8_t
// equations from Josh
iac_wc = 1.25 * ( 28.5 * 1.25 - 16 ) * ( 1 - 0.05 * 2) * 40/71; // testsite equation & ratio of testsite to anticipated produ
- iac = 1.25 * (-15.78 -0.618 * sigma + 27.6 * vout/1000) * 40/64; // product equation & ratio of testsite to actual product
+ iac = 1.25 * (-15.78 -0.618 * sigma + 27.6 * vout/1000) * 40/64; // product equation & ratio of testsite to actual product
pwrratio_f = iac / iac_wc;
- pwrratio = (uint8_t)((pwrratio_f*64) + 0.5);
+
+ if (pwrratio_f >= 1.0)
+ pwrratio = 63;
+ else
+ pwrratio = (uint8_t)((pwrratio_f*64) + 0.5);
lpsa->pstate[i].fields.vdd_core_pwrratio = pwrratio;
lpsa->pstate[i].fields.vcs_core_pwrratio = pwrratio;
lpsa->pstate[i].fields.vdd_eco_pwrratio = pwrratio;
lpsa->pstate[i].fields.vcs_eco_pwrratio = pwrratio;
+
+ // ------------------------------------
+ // compute increment step and decrement
+ // ------------------------------------
+ // - look above current pstate to pstate that is >= 25 mV for inc_step
+ // - look below current pstate to pstate that is >= 25 mV for dec_step
+
+ // find # steps above and below current lpst pstate
+ steps_above_curr = gpst_pmax(gpst) - lpst_pstate;
+ steps_below_curr = lpst_pstate - gpst_pmin(gpst);
+
+
+ // start looking above in gpst to find inc_step
+ inc_step = 0; // default
+
+ for (j = 1; j <= steps_above_curr; j++) {
+ inc_step = j - 1;
+// jwy printf("%d %d %d\n", lpst_pstate,j, steps_above_curr);
+ entry.value = revle64(gpst->pstate[lpst_pstate - gpst_pmin(gpst) + j].value);
+ rc = vrm112vuv(entry.fields.evid_vdd, &gpst_uv); if (rc) break;
+ gpst_uv = (uint32_t) (gpst_uv * volt_int_vdd_bias);
+ rc = vuv2ivid(gpst_uv, ROUND_VOLTAGE_DOWN, &gpst_ivid); if (rc) break;
+
+ if ( (gpst_ivid - v_ivid) >= 4)
+ break;
+ }
+
+ if (rc) break;
+
+ // clip inc_step
+ if (inc_step > 7)
+ inc_step = 7;
+
+
+ lpsa->pstate[i].fields.inc_step = inc_step;
+// jwy lpsa->pstate[i].fields.inc_step = 0; // FIXME - temporary patch!
- // ??? what should these be ??? set to 1 for now
- lpsa->pstate[i].fields.inc_step = 1;
- lpsa->pstate[i].fields.dec_step = 1;
+ // start looking below in gpst to find dec_step
+ dec_step = 0; // default
+
+ for (j = 1; j <= steps_below_curr; j++) {
+ dec_step = j - 1;
+// jwy printf("%d %d %d\n", lpst_pstate,j, steps_below_curr);
+ entry.value = revle64(gpst->pstate[lpst_pstate - gpst_pmin(gpst) - j].value);
+ rc = vrm112vuv(entry.fields.evid_vdd, &gpst_uv); if (rc) break;
+ gpst_uv = (uint32_t) (gpst_uv * volt_int_vdd_bias);
+ rc = vuv2ivid(gpst_uv, ROUND_VOLTAGE_DOWN, &gpst_ivid); if (rc) break;
+
+ if ( (v_ivid - gpst_ivid ) >= 4)
+ break;
+ }
+
+ if (rc) break;
+
+ // clip dec_step
+ if (dec_step > 7)
+ dec_step = 7;
+
+ lpsa->pstate[i].fields.dec_step = dec_step;
+// jwy lpsa->pstate[i].fields.dec_step = 0; // FIXME - temporary patch!
// jwy printf (" %d %X %X %f %d %d %d %d\n", i, (uint32_t)lpsa->pstate[i].fields.ivid_vdd, (uint32_t)lpsa->pstate[i].fields.ivid_vcs, pwrratio_f, pwrratio, vid_incr[0], vid_incr[1], vid_incr[2]);
@@ -703,14 +848,413 @@ lpst_create(const GlobalPstateTable *gpst, LocalPstateArray *lpsa, const uint8_t
gpst_index++;
if (gpst_index > lpst_entries)
break;
+
+ // point to next lpst pstate
+ lpst_pstate++;
}
// set these fields in lpst structure
- lpsa->pmin = lpst_pmin;
- lpsa->entries = lpst_entries;
-
+ if (lpst_max_found == 0) {
+ lpsa->pmin = 0;
+ lpsa->entries = 0;
+ }
+ else {
+ lpsa->pmin = lpst_pmin;
+ lpsa->entries = lpst_entries;
+ }
+
} while (0);
return rc;
-} // end lpst_create
+} // end lpst_create
+
+// This routine will fully fill out the VDS region table even if
+// some of the upper entries are not used.
+void
+build_vds_region_table( ivrm_parm_data_t* i_ivrm_parms,
+ PstateSuperStructure* pss)
+{
+ int i;
+ uint32_t vds;
+ uint64_t beg_offset = 0;
+ uint64_t end_offset = 0;
+
+ vds = (i_ivrm_parms->vds_min_range_upper_bound*1000)/IVID_STEP_UV;
+ end_offset = (uint64_t)vds;
+
+ for (i = 0; i < i_ivrm_parms->vds_region_entries; i++)
+ {
+ pss->lpsa.vdsvin[i].fields.ivid0 = beg_offset;
+ pss->lpsa.vdsvin[i].fields.ivid1 = end_offset;
+// jwy printf(" Vds_region[%x]: begin - %02llX, end - %02llX\n", i, beg_offset, end_offset);
+
+ // Calculate offsets for next entry
+ beg_offset = end_offset + 1;
+
+ // clip at 127
+ if (beg_offset >= 127)
+ beg_offset = 127;
+
+ vds =(uint32_t)( (float)end_offset * (1 + ( (float)i_ivrm_parms->vds_step_percent/100)));
+ end_offset = (uint64_t)vds;
+
+ // clip at 127
+ if (end_offset >= 127)
+ end_offset = 127;
+ }
+}
+
+// This routine will fully fill out the VDS region table even if
+// some of the upper entries are not used.
+void
+fill_vin_table( ivrm_parm_data_t* i_ivrm_parms,
+ PstateSuperStructure* pss)
+{
+ int s;
+ int i;
+ int idx;
+// uint8_t pfetstr = 17;
+
+ i = i_ivrm_parms->vin_table_setsperrow;
+ for (i = 0; i < i_ivrm_parms->vds_region_entries; i++)
+ {
+ for (s = 0; s < i_ivrm_parms->vin_table_setsperrow; s++) {
+ idx = (i*4) + s;
+ pss->lpsa.vdsvin[idx].fields.pfet0 = i_ivrm_parms->forced_pfetstr_value;
+ pss->lpsa.vdsvin[idx].fields.pfet1 = i_ivrm_parms->forced_pfetstr_value;
+ pss->lpsa.vdsvin[idx].fields.pfet2 = i_ivrm_parms->forced_pfetstr_value;
+ pss->lpsa.vdsvin[idx].fields.pfet3 = i_ivrm_parms->forced_pfetstr_value;
+ pss->lpsa.vdsvin[idx].fields.pfet4 = i_ivrm_parms->forced_pfetstr_value;
+ pss->lpsa.vdsvin[idx].fields.pfet5 = i_ivrm_parms->forced_pfetstr_value;
+ pss->lpsa.vdsvin[idx].fields.pfet6 = i_ivrm_parms->forced_pfetstr_value;
+ pss->lpsa.vdsvin[idx].fields.pfet7 = i_ivrm_parms->forced_pfetstr_value;
+
+// jwy pss->lpsa.vdsvin[idx].fields.pfet0 = pfetstr; pfetstr++; if (pfetstr%32 == 0) pfetstr = 17;
+// jwy pss->lpsa.vdsvin[idx].fields.pfet1 = pfetstr; pfetstr++; if (pfetstr%32 == 0) pfetstr = 17;
+// jwy pss->lpsa.vdsvin[idx].fields.pfet2 = pfetstr; pfetstr++; if (pfetstr%32 == 0) pfetstr = 17;
+// jwy pss->lpsa.vdsvin[idx].fields.pfet3 = pfetstr; pfetstr++; if (pfetstr%32 == 0) pfetstr = 17;
+// jwy pss->lpsa.vdsvin[idx].fields.pfet4 = pfetstr; pfetstr++; if (pfetstr%32 == 0) pfetstr = 17;
+// jwy pss->lpsa.vdsvin[idx].fields.pfet5 = pfetstr; pfetstr++; if (pfetstr%32 == 0) pfetstr = 17;
+// jwy pss->lpsa.vdsvin[idx].fields.pfet6 = pfetstr; pfetstr++; if (pfetstr%32 == 0) pfetstr = 17;
+// jwy pss->lpsa.vdsvin[idx].fields.pfet7 = pfetstr; pfetstr++; if (pfetstr%32 == 0) pfetstr = 17;
+
+// jwy printf(" Vin[%d]{%d,%d}: %016llX\n", idx, i, s, pss->lpsa.vdsvin[idx].value);
+
+ // Byte reverse the entry into the image.
+ pss->lpsa.vdsvin[idx].value = revle64(pss->lpsa.vdsvin[idx].value);
+ }
+ }
+}
+
+#undef abs
+#define abs(x) (((x)<0.0)?(-(x)):(x))
+
+void simeq(int n, double A[], double Y[], double X[])
+{
+
+/* PURPOSE : SOLVE THE LINEAR SYSTEM OF EQUATIONS WITH REAL */
+/* COEFFICIENTS [A] * |X| = |Y| */
+/* */
+/* INPUT : THE NUMBER OF EQUATIONS n */
+/* THE REAL MATRIX A should be A[i][j] but A[i*n+j] */
+/* THE REAL VECTOR Y */
+/* OUTPUT : THE REAL VECTOR X */
+/* */
+/* METHOD : GAUSS-JORDAN ELIMINATION USING MAXIMUM ELEMENT */
+/* FOR PIVOT. */
+/* */
+/* USAGE : simeq(n,A,Y,X); */
+/* */
+/* */
+/* WRITTEN BY : JON SQUIRE , 28 MAY 1983 */
+/* ORIGINAL DEC 1959 for IBM 650, TRANSLATED TO OTHER LANGUAGES */
+/* e.g. FORTRAN converted to Ada converted to C */
+
+ double *B; /* [n][n+1] WORKING MATRIX */
+ int *ROW; /* ROW INTERCHANGE INDICES */
+ int HOLD , I_PIVOT; /* PIVOT INDICES */
+ double PIVOT; /* PIVOT ELEMENT VALUE */
+ double ABS_PIVOT;
+ int i,j,k,m;
+
+ B = (double *)calloc((n+1)*(n+1), sizeof(double));
+ ROW = (int *)calloc(n, sizeof(int));
+ m = n+1;
+
+ /* BUILD WORKING DATA STRUCTURE */
+ for(i=0; i<n; i++){
+ for(j=0; j<n; j++){
+ B[i*m+j] = A[i*n+j];
+ }
+ B[i*m+n] = Y[i];
+ }
+ /* SET UP ROW INTERCHANGE VECTORS */
+ for(k=0; k<n; k++){
+ ROW[k] = k;
+ }
+
+ /* BEGIN MAIN REDUCTION LOOP */
+ for(k=0; k<n; k++){
+
+ /* FIND LARGEST ELEMENT FOR PIVOT */
+ PIVOT = B[ROW[k]*m+k];
+ ABS_PIVOT = abs(PIVOT);
+ I_PIVOT = k;
+ for(i=k; i<n; i++){
+ if( abs(B[ROW[i]*m+k]) > ABS_PIVOT){
+ I_PIVOT = i;
+ PIVOT = B[ROW[i]*m+k];
+ ABS_PIVOT = abs ( PIVOT );
+ }
+ }
+
+ /* HAVE PIVOT, INTERCHANGE ROW POINTERS */
+ HOLD = ROW[k];
+ ROW[k] = ROW[I_PIVOT];
+ ROW[I_PIVOT] = HOLD;
+
+ /* CHECK FOR NEAR SINGULAR */
+ if( ABS_PIVOT < 1.0E-10 ){
+ for(j=k+1; j<n+1; j++){
+ B[ROW[k]*m+j] = 0.0;
+ }
+// jwy printf("redundant row (singular) %d \n", ROW[k]);
+ } /* singular, delete row */
+ else{
+
+ /* REDUCE ABOUT PIVOT */
+ for(j=k+1; j<n+1; j++){
+ B[ROW[k]*m+j] = B[ROW[k]*m+j] / B[ROW[k]*m+k];
+ }
+
+ /* INNER REDUCTION LOOP */
+ for(i=0; i<n; i++){
+ if( i != k){
+ for(j=k+1; j<n+1; j++){
+ B[ROW[i]*m+j] = B[ROW[i]*m+j] - B[ROW[i]*m+k] * B[ROW[k]*m+j];
+ }
+ }
+ }
+ }
+ /* FINISHED INNER REDUCTION */
+ }
+
+ /* END OF MAIN REDUCTION LOOP */
+ /* BUILD X FOR RETURN, UNSCRAMBLING ROWS */
+ for(i=0; i<n; i++){
+ X[i] = B[ROW[i]*m+n];
+ }
+ free(B);
+ free(ROW);
+} /* end simeq */
+
+
+void fit_file(int n, uint8_t version, double C[], ivrm_cal_data_t* cal_data)
+{
+ int i, j, k;
+ int points;
+ double y;
+ double Vd, Vs;
+// jwy double Vg;
+ double x[30]; /* at least 2n */
+ double A[2500];
+ double Y[50];
+
+ // -----------------------------------------------------------------------------------------
+ // initialize harcoded values to use for Vs & Vg for version1
+ // version1 specifies Vd &Vs as uV and 16 bits is not enough to specify values about 65 mV
+ // -----------------------------------------------------------------------------------------
+ double Vs_v1[13];
+ double Vd_v1[13];
+ Vd_v1[0] = 700; Vs_v1[0] = 888;
+ Vd_v1[1] = 831; Vs_v1[1] = 1033;
+ Vd_v1[2] = 787; Vs_v1[2] = 1033;
+ Vd_v1[3] = 718; Vs_v1[3] = 1033;
+ Vd_v1[4] = 962; Vs_v1[4] = 1179;
+ Vd_v1[5] = 918; Vs_v1[5] = 1179;
+ Vd_v1[6] = 850; Vs_v1[6] = 1179;
+ Vd_v1[7] = 750; Vs_v1[7] = 1179;
+ Vd_v1[8] = 1093; Vs_v1[8] = 1325;
+ Vd_v1[9] = 1050; Vs_v1[9] = 1325;
+ Vd_v1[10] = 981; Vs_v1[10] = 1325;
+ Vd_v1[11] = 881; Vs_v1[11] = 1325;
+ Vd_v1[12] = 731; Vs_v1[12] = 1325;
+
+ points = cal_data->point_valid;
+
+ for(i=0; i<n; i++)
+ {
+ for(j=0; j<n; j++)
+ {
+ A[i*n+j] = 0.0;
+ }
+ Y[i] = 0.0;
+ }
+
+ x[0]=1.0;
+
+ for (k = 0; k <= points-1; k++) {
+
+ if (version == 0) {
+ Vd = Vd_v1[k];
+ Vs = Vs_v1[k];
+// jwy Vg = (double)cal_data->point[k].gate_voltage/1000; // uV
+ y = ((double)cal_data->point[k].drain_current)/1000; // uA
+ }
+ else if (version == 1 || version == 2){
+ Vd = (double)cal_data->point[k].drain_voltage; // mV
+ Vs = (double)cal_data->point[k].source_voltage; // mV
+// jwy Vg = (double)cal_data->point[k].gate_voltage/1000; // uV
+ y = ((double)cal_data->point[k].drain_current)/1000; // uA
+ }
+ else { //simulation data
+ Vd = (double)cal_data->point[k].drain_voltage; // mV
+ Vs = (double)cal_data->point[k].source_voltage; // mV
+// jwy Vg = (double)cal_data->point[k].gate_voltage; // mV
+ y = ((double)cal_data->point[k].drain_current)/1000; // uA
+ }
+
+// jwy printf (" %f %f %f %f\n", Vd, Vs, Vg, y );
+
+ x[1]=Vs/1.11; // x[1] = target Vin = Vgs / 1.11
+ x[2]=Vs/1.11-Vd; // x[2] = target Vds = Vin/1.11 - Vout = Vs/1.11 - Vd
+ x[3]=x[1]*x[2]; // x[3] = Vin*Vds
+
+// jwy if (Vg>20) { printf("ERROR: gate voltage > 20mV: current=%lf, Vd=%lf, Vs=%lf, Vg=%lf\n", y, Vd, Vs, Vg); }
+
+ for(i=0; i<n; i++) {
+ for(j=0; j<n; j++) {
+ A[i*n+j] = A[i*n+j] + x[i]*x[j];
+ }
+ Y[i] = Y[i] + y*x[i];
+ }
+ }
+
+ simeq(n, A, Y, C);
+
+// jwy for(i=0; i<n; i++) printf("C[%d]=%g \n", i, C[i]);
+} /* end fit_file */
+
+// jwy void dec2bin(int h, int n) {
+// jwy int i;
+// jwy char b[12];
+// jwy if (n>12) { n = 12; }
+// jwy for( i = n-1; i >= 0; i--) {
+// jwy if( (1 << i) & h) {
+// jwy b[n - i] = '1';
+// jwy printf("%c",b[n-i]);
+// jwy } else {
+// jwy b[n - i] = '0';
+// jwy printf("%c",b[n-i]);
+// jwy }
+// jwy }
+// jwy
+// jwy b[n] = 0; // ascii terminating character
+// jwy }
+
+
+void write_HWtab_bin(ivrm_parm_data_t* i_ivrm_parms,
+ double C[],
+ PstateSuperStructure* pss)
+{
+ int i, j;
+ double VIN_MIN;
+ double VDS_MIN;
+ double Vin[40]; /* at least 2n */
+ double Vds[40];
+ int NUM_VIN;
+ int NUM_VDS;
+ double LSB_CURRENT;
+ double TEMP_UPLIFT;
+ double Ical[40][40];
+ double Iratio[40][40];
+ uint8_t Iratio_int[40][40];
+ int temp;
+ uint8_t ratio_val;
+ uint8_t idx;
+
+ NUM_VIN = i_ivrm_parms->vin_entries_per_vds;
+ NUM_VDS = i_ivrm_parms->vds_region_entries;
+ VIN_MIN = 800;
+ VDS_MIN = 100;
+ LSB_CURRENT = 4.1;
+ TEMP_UPLIFT = 1.1;
+
+ for(i=0; i<NUM_VIN; i++) { Vin[i] = VIN_MIN + i * 25; }
+
+ Vds[0]=VDS_MIN;
+ for(i=1; i<NUM_VDS; i++) {
+ temp=(int) (Vds[i-1]*1.25/6.25);
+ Vds[i] = temp*6.25 ;
+ }
+
+// jwy printf("\t");
+// jwy for(i=0; i<NUM_VDS; i++) { printf("%lf\t", Vds[i]); }
+// jwy printf("\n");
+
+ for(i=0; i<NUM_VIN; i++) {
+// jwy printf("%lf\t", Vin[i]);
+
+ for (j=0; j<NUM_VDS; j++) {
+ if(Vin[i]-Vds[j]>=700) {
+ Ical[i][j] = C[0] + C[1]*Vin[i] + C[2]*Vds[j] + C[3]*Vin[i]*Vds[j]; // compute cal current
+ Iratio[i][j] = TEMP_UPLIFT * LSB_CURRENT / Ical[i][j];
+
+ temp = (int) (Iratio[i][j]+1/16>3.875 ? 3.875 : Iratio[i][j]+1/16);
+// jwy dec2bin(temp, 2);
+ ratio_val = 0;
+ ratio_val = (temp << 3) & 0x018; // jwy shift temp left 3 and clear out lower 3 bits - this gets bits 0:1 of value
+ //printf(".");
+
+ temp = (int) ((Iratio[i][j] - temp)*8 + 0.5);
+// jwy dec2bin(temp, 3);
+ ratio_val = (temp & 0x07)| ratio_val; // jwy OR lower 3 bits of temp with upper 2 bits already in 0:1 - this merges bits 2:4 with 0:1 for final value
+ Iratio_int[i][j] = ratio_val;
+// printf(" %u",ratio_val);
+// jwy printf("\t");
+ } else {
+ Iratio[i][j] = 0;
+ Iratio_int[i][j] = 0;
+// jwy printf("0*\t");
+ }
+ //printf("%lf\t", Iratio[i][j]);
+ }
+// jwy printf("\n");
+ }
+
+// jwy for (i=0; i<NUM_VDS; i++) {
+// jwy
+// jwy for(j=0; j<NUM_VIN; j++) {
+// jwy printf("%u ",Iratio_int[i][j]);
+// jwy }
+// jwy printf("\n");
+// jwy }
+
+
+ // fill in Vin table with Iratio data
+ for (i=0; i<NUM_VDS; i++) { // 16 rows
+
+ for(j=0; j<4; j++) { // 32 cols
+ idx = (i*4) + j;
+ pss->lpsa.vdsvin[idx].fields.pfet0 = Iratio_int[j*8][i];
+ pss->lpsa.vdsvin[idx].fields.pfet1 = Iratio_int[(j*8)+1][i];
+ pss->lpsa.vdsvin[idx].fields.pfet2 = Iratio_int[(j*8)+2][i];
+ pss->lpsa.vdsvin[idx].fields.pfet3 = Iratio_int[(j*8)+3][i];
+ pss->lpsa.vdsvin[idx].fields.pfet4 = Iratio_int[(j*8)+4][i];
+ pss->lpsa.vdsvin[idx].fields.pfet5 = Iratio_int[(j*8)+5][i];
+ pss->lpsa.vdsvin[idx].fields.pfet6 = Iratio_int[(j*8)+6][i];
+ pss->lpsa.vdsvin[idx].fields.pfet7 = Iratio_int[(j*8)+7][i];
+
+// jwy for (k=0; k<8; k++) {
+// jwy printf("%u ", Iratio_int[(j*8)+k][i]);
+// jwy }
+// jwy printf("\n");
+// jwy printf(" Vin[%d]{%d,%d}: %016llX\n", idx, i, j, pss->lpsa.vdsvin[idx].value);
+
+
+ // Byte reverse the entry into the image.
+ pss->lpsa.vdsvin[idx].value = revle64(pss->lpsa.vdsvin[idx].value);
+ }
+ }
+} /* end fit_file */
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h
index f4dd6b275..02081e5a4 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h
@@ -23,7 +23,7 @@
#ifndef __PSTATE_TABLES_H__
#define __PSTATE_TABLES_H__
-// $Id: pstate_tables.h,v 1.6 2013/05/02 17:33:31 jimyac Exp $
+// $Id: pstate_tables.h,v 1.7 2013/08/13 17:13:03 jimyac Exp $
/// \file pstate_tables.h
/// \brief Code used to generate Pstate tables from real or imagined chip
@@ -149,8 +149,49 @@ gpst_create(GlobalPstateTable *gpst,
int
lpst_create(const GlobalPstateTable *gpst,
LocalPstateArray *lpsa,
- const uint8_t dead_zone_5mv);
-
+ const uint8_t dead_zone_5mv,
+ double volt_int_vdd_bias,
+ double volt_int_vcs_bias);
+
+typedef struct IVRM_PARM_DATA {
+ uint32_t vin_min; // Minimum input voltage
+ uint32_t vin_max; // Maximum input voltage
+ uint32_t vin_table_step_size; // Granularity of Vin table entries
+ uint32_t vin_table_setsperrow; // Vin sets per Vds row
+ uint32_t vin_table_pfetstrperset; // PFET Strength values per Vin set
+ uint32_t vout_min; // Minimum regulated output voltage
+ uint32_t vout_max; // Maximum regulated output voltage
+ uint32_t vin_entries_per_vds; // Vin array entries per vds region
+ uint32_t vds_min_range_upper_bound; // Starting point for vds regions
+ uint32_t vds_step_percent; // vds region step muliplier
+ uint32_t vds_region_entries; // vds region array entries (in hardware)
+ uint32_t pfetstr_default; // Default PFET Strength with no calibration
+ uint32_t positive_guardband; // Plus side guardband (%)
+ uint32_t negative_guardband; // Negative side guardband (%)
+ uint32_t number_of_coefficients; // Number of coefficents in cal data
+ uint32_t force_pfetstr_values; // 0 - calculated; 1 = forced
+ uint32_t forced_pfetstr_value; // If force_pfetstr_values = 1, use this value
+ // 5b value used as it to fill in all entries
+} ivrm_parm_data_t;
+
+void
+build_vds_region_table(ivrm_parm_data_t* i_ivrm_parms,
+ PstateSuperStructure* pss);
+
+
+void
+fill_vin_table(ivrm_parm_data_t* i_ivrm_parms,
+ PstateSuperStructure* pss);
+
+
+void fit_file(int n,
+ uint8_t version,
+ double C[],
+ ivrm_cal_data_t* cal_data);
+
+void write_HWtab_bin(ivrm_parm_data_t* i_ivrm_parms,
+ double C[],
+ PstateSuperStructure* pss);
#endif // __ASSEMBLER__
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstates.c b/src/usr/hwpf/hwp/pstates/pstates/pstates.c
index 32ee1ec94..8ef039c56 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/pstates.c
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstates.c
@@ -20,7 +20,7 @@
/* Origin: 30 */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: pstates.c,v 1.4 2013/06/12 20:02:12 mjjones Exp $
+// $Id: pstates.c,v 1.6 2013/09/17 16:36:39 jimyac Exp $
/// \file pstates.c
/// \brief Pstate routines required by OCC product firmware
@@ -237,6 +237,10 @@ gpst_entry(const GlobalPstateTable *gpst,
int rc, index;
Pstate biased_pstate;
+// jwy if (SSX_ERROR_CHECK_API) {
+// jwy SSX_ERROR_IF(gpst == 0, GPST_INVALID_OBJECT);
+// jwy }
+
if (gpst == 0) {
return -GPST_INVALID_OBJECT;
}
@@ -325,8 +329,12 @@ gpst_vdd2pstate(const GlobalPstateTable* gpst,
gpst_entry_t entry_rev; // jwy
+// jwy if (SSX_ERROR_CHECK_API) {
+// jwy SSX_ERROR_IF(gpst == 0, GPST_INVALID_OBJECT);
+// jwy }
+
if (gpst == 0) {
- return -GPST_INVALID_OBJECT;
+ return -GPST_INVALID_OBJECT;
}
do {
@@ -393,3 +401,22 @@ int freq2pState (const GlobalPstateTable* gpst,
return rc;
}
+
+
+
+int pstate_minmax_chk (const GlobalPstateTable* gpst,
+ Pstate* pstate)
+{
+ int rc = 0;
+
+ // if pstate is greater than pmax, generate an error
+ if (*pstate > gpst_pmax(gpst))
+ rc = -GPST_PSTATE_GT_GPST_PMAX;
+
+ // if pstate is less than than pmin, clip pstate to pmin
+ if (*pstate < gpst_pmin(gpst) )
+ *pstate = gpst_pmin(gpst);
+
+ return rc;
+}
+
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstates.h b/src/usr/hwpf/hwp/pstates/pstates/pstates.h
index b0f8e77d4..db4f25174 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/pstates.h
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstates.h
@@ -23,7 +23,7 @@
#ifndef __PSTATES_H__
#define __PSTATES_H__
-// $Id: pstates.h,v 1.6 2013/05/02 17:33:33 jimyac Exp $
+// $Id: pstates.h,v 1.8 2013/09/17 16:36:40 jimyac Exp $
/// \file pstates.h
/// \brief Pstate structures and support routines for OCC product firmware
@@ -41,8 +41,11 @@
/// The Global Pstate table has 128 * 8-byte entries
#define GLOBAL_PSTATE_TABLE_ENTRIES 128
-/// The Local Pstate array has 96 x 64-bit entries
-#define LOCAL_PSTATE_ARRAY_ENTRIES 96
+/// The Local Pstate table has 32 x 64-bit entries
+#define LOCAL_PSTATE_ARRAY_ENTRIES 32
+
+/// The VDS/VIN table has 32 x 64-bit entries
+#define VDSVIN_ARRAY_ENTRIES 64
/// The VRM-11 VID base voltage in micro-Volts
#define VRM11_BASE_UV 1612500
@@ -56,6 +59,9 @@
/// The iVID step as an unsigned number (micro-Volts)
#define IVID_STEP_UV 6250
+/// CPM Inflection Points
+#define CPM_RANGES 8
+
// Error/Panic codes for support routines
#define VRM11_INVALID_VOLTAGE 0x00876101
@@ -78,10 +84,11 @@
#define GPST_PSTATE_CLIPPED_LOW 0x00477804
#define GPST_PSTATE_CLIPPED_HIGH 0x00477805
#define GPST_BUG 0x00477806
+#define GPST_PSTATE_GT_GPST_PMAX 0x00477807
#define LPST_INVALID_OBJECT 0x00477901
-
-
+#define LPST_GPST_WARNING 0x00477902
+#define LPST_INCR_CLIP_ERROR 0x00477903
/// PstateSuperStructure Magic Number
///
@@ -127,6 +134,8 @@
#include <stdint.h>
+#include <p8_ivrm.H>
+
/// A Global Pstate Table Entry, in the form of a packed 'firmware register'
///
/// Global Pstate table entries are referenced by OCC firmware, for example
@@ -230,6 +239,50 @@ typedef union lpst_entry {
} lpst_entry_t;
+/// A VDS/VIN table Entry
+
+typedef union vdsvin_entry {
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ivid0 : 7;
+ uint64_t ivid1 : 7;
+ uint64_t reserved14 : 2;
+ uint64_t pfet0 : 5;
+ uint64_t pfet1 : 5;
+ uint64_t pfet2 : 5;
+ uint64_t pfet3 : 5;
+ uint64_t pfet4 : 5;
+ uint64_t pfet5 : 5;
+ uint64_t pfet6 : 5;
+ uint64_t pfet7 : 5;
+ uint64_t reserved_56 : 8;
+#else
+ uint64_t reserved_56 : 8;
+ uint64_t pfet7 : 5;
+ uint64_t pfet6 : 5;
+ uint64_t pfet5 : 5;
+ uint64_t pfet4 : 5;
+ uint64_t pfet3 : 5;
+ uint64_t pfet2 : 5;
+ uint64_t pfet1 : 5;
+ uint64_t pfet0 : 5;
+ uint64_t reserved14 : 2;
+ uint64_t ivid1 : 7;
+ uint64_t ivid0 : 7;
+#endif // _BIG_ENDIAN
+ } fields;
+} vdsvin_entry_t;
+
/// Standard options controlling Pstate setup and GPSM procedures
typedef struct {
@@ -366,7 +419,10 @@ typedef struct {
typedef struct {
- /// The array contents
+ /// The vdsvin table contents
+ vdsvin_entry_t vdsvin[VDSVIN_ARRAY_ENTRIES];
+
+ /// The local pstate table contents
lpst_entry_t pstate[LOCAL_PSTATE_ARRAY_ENTRIES];
/// The number of entries defined in the Local Pstate Table
@@ -416,6 +472,42 @@ typedef struct {
} ResonantClockingSetup;
+/// CPM Pstate ranges per mode
+///
+/// These Pstate range specifications apply to all chiplets operating in the
+/// same mode.
+
+typedef union {
+
+ /// Forces alignment
+ uint64_t quad[2];
+
+ struct {
+
+ /// Lower limit of each CPM calibration range
+ ///
+ /// The entries in this table are Pstates representing the
+ /// lowest-numbered (lowest-voltage) Pstate of each range. This is the
+ /// inflection point between range N and range N+1.
+ Pstate inflectionPoint[CPM_RANGES];
+
+ /// The number of ranges valid in the \a inflectionPoint table
+ ///
+ /// Validity here is defined by the original characterization
+ /// data. Whether or not OCC will use any particular range is managed
+ /// by OCC.
+ uint8_t validRanges;
+
+ /// The Pstate corresponding to the upper limit of range 0.
+ ///
+ /// This is the "CPmax" for the mode. The "CPmin" for this
+ /// mode is the value of inflectionPoint[valid_ranges - 1].
+ Pstate pMax;
+
+ uint8_t pad[6];
+ };
+
+} CpmPstateModeRanges;
/// The layout of the data created by the Pstate table creation firmware
@@ -442,7 +534,10 @@ typedef struct {
/// Resonant Clocking Setup
ResonantClockingSetup resclk;
-
+
+ /// CPM Pstate ranges
+ CpmPstateModeRanges cpmranges;
+
} PstateSuperStructure;
@@ -476,6 +571,9 @@ gpst_vdd2pstate(const GlobalPstateTable* gpst,
Pstate* pstate,
gpst_entry_t* entry);
+int
+pstate_minmax_chk (const GlobalPstateTable* gpst,
+ Pstate* pstate);
/// Return the Pmin value associated with a GlobalPstateTable
static inline Pstate
OpenPOWER on IntegriCloud