summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBill Schwartz <whs@us.ibm.com>2015-09-08 15:02:45 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2015-09-16 11:05:54 -0500
commit52cdccf5cb1bed63f31036c79b1cb5f2c83e7220 (patch)
treee533caab69a0dc6bd61abee180541e8bc82a525a /src
parentdf5c383842ed36306c537b22f7ac23971ed04b1d (diff)
downloadblackbird-hostboot-52cdccf5cb1bed63f31036c79b1cb5f2c83e7220.tar.gz
blackbird-hostboot-52cdccf5cb1bed63f31036c79b1cb5f2c83e7220.zip
WOF HWPs
Add support for UltraTurbo and related WOF Elements to Pstate CQ:SW308304 Change-Id: I4ef70a1262c1a952a15c251371af8a1f7e8d407d Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/19718 Reviewed-by: Thi N. Tran <thi@us.ibm.com> Reviewed-by: William H. Schwartz <whs@us.ibm.com> Tested-by: William H. Schwartz <whs@us.ibm.com> Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/20373 Tested-by: Jenkins Server Tested-by: Jenkins OP Build CI Tested-by: FSP CI Jenkins Tested-by: Jenkins OP HW Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C406
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c13
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/lab_pstates.c524
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/lab_pstates.h21
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.C3256
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.H36
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml110
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstate_tables.c1003
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstate_tables.h60
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstates.c13
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstates.h337
-rw-r--r--src/usr/hwpf/hwp/pstates/pstates_common.mk4
12 files changed, 3965 insertions, 1818 deletions
diff --git a/src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C b/src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C
index 438ddfc4f..28575ef0f 100644
--- a/src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C
+++ b/src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -22,7 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: p8_pm_prep_for_reset.C,v 1.30 2014/04/21 14:27:53 bcbrock Exp $
+// $Id: p8_pm_prep_for_reset.C,v 1.31 2015/05/13 03:12:36 stillgs Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/p8_pm_prep_for_reset.C,v $
//------------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2011
@@ -33,41 +33,41 @@
// *! OWNER NAME: Ralf Maier Email: ralf.maier@de.ibm.com
// *!
/// \file p8_pm_prep_for_reset.C
-/// \brief Initialize powermanagement
-///
+/// \brief Reset Power Management function
+///
//------------------------------------------------------------------------------
///
/// High-level procedure flow:
///
/// \verbatim
-/// - call p8_pm_firinit *chiptarget,
-/// - Mask the PM FIRs
///
-/// - call p8_occ_control.C *chiptarget, ENUM:OCC_STOP ppc405_reset_ctrl = PPC405_RESET_SEQUENCE
-/// - OCC PPC405 put into reset safely
+/// do {
+/// - Clear the Deep Exit Masks to allow Special Wake-up to occur
+/// - Put all EX chiplets in special wakeup
+/// - Mask the PM FIRs
+/// - Disable PMC OCC HEARTBEAT before halting and reset OCC
+/// - Halt and then Reset the PPC405
/// - PMC moves to Vsafe value due to heartbeat loss
+/// - Force Vsafe value into voltage controller to cover the case that the
+/// Pstate hardware didn't move correctly
+/// - Reset PCBS-PM
+/// - Reset PMC
+/// As the PMC reset kills ALL of the configuration, the idle portion
+/// must be reestablished to allow that portion to operate.
+/// - Run SLW Initialiation
+/// - This allows special wake-up removal before exit
+/// - Reset PSS
+/// - Reset GPEs
+/// - Reset PBA
+/// - Reset SRAM Controller
+/// - Reset OCB
+/// - Clear special wakeups
+/// } while(0);
///
-/// - call p8_cpu_special_wakeup.C *chiptarget, ENUM:OCC_SPECIAL_WAKEUP
-/// - For each chiplet, put into Special Wake-up via the OCC special wake-up bit
-///
-/// - call p8_pmc_force_vsafe.C *chiptarget,
-/// - Forces the Vsafe value into the voltage controller
-///
-/// - call p8_pcbs_init.C *chiptarget, ENUM:PCBSPM_RESET
-///
-/// - call p8_pmc_init.C *chiptarget, ENUM:PMC_RESET
-/// - Issue reset to the PMC
-///
-/// - call p8_poregpe_init.C *chiptarget, ENUM:POREGPE_RESET
-///
-/// - call p8_pba_init.C *chiptarget, ENUM:PBA_RESET
-///
-/// - call p8_occ_sram_init.C *chiptarget, ENUM:OCC_SRAM_RESET
-///
-/// - call p8_ocb_init .C *chiptarget, ENUM:OCC_OCB_RESET
+/// if error, clear special wakeups to leave this procedure clean
///
/// SLW engine reset is not done here as this will blow away all setup
-/// in istep 15. Thus, ALL manipulation of this is via calls to
+/// in istep 15. Thus, ALL manipulation of this is via calls to
/// p8_poreslw_ioit or by p8_poreslw_recovery.
///
/// \endverbatim
@@ -101,12 +101,15 @@ using namespace fapi;
fapi::ReturnCode
special_wakeup_all (const fapi::Target &i_target, bool i_action);
-// FSM trace wrapper
+fapi::ReturnCode
+clear_deep_exit_mask (const fapi::Target &i_target);
+
+// FSM trace wrapper
fapi::ReturnCode
p4rs_pcbs_fsm_trace (const fapi::Target& i_primary_target,
- const fapi::Target& i_secondary_target,
+ const fapi::Target& i_secondary_target,
const char * i_msg);
-
+
// ----------------------------------------------------------------------
// Function definitions
// ----------------------------------------------------------------------
@@ -138,11 +141,11 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
uint32_t e_rc = 0;
std::vector<fapi::Target> l_exChiplets;
ecmdDataBufferBase data(64);
- ecmdDataBufferBase mask(64);
+ ecmdDataBufferBase mask(64);
uint64_t address = 0;
const char * PM_MODE_NAME_VAR; // Defines storage for PM_MODE_NAME
-
+
bool b_special_wakeup_pri = false;
bool b_special_wakeup_sec = false;
@@ -160,7 +163,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
FAPI_ERR("fapiGetAttribute of ATTR_IS_MPIPL rc = 0x%x", (uint32_t)rc);
break;
}
-
+
FAPI_INF("IPL mode = %s", ipl_mode ? "MPIPL" : "NORMAL");
@@ -195,58 +198,84 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
{
FAPI_INF("Running on DCM");
}
+
+ // ******************************************************************
+ // Clear the Deep Exit Masks to allow Special Wake-up to occur
+ // ******************************************************************
+ // Primary
+ rc = clear_deep_exit_mask(i_primary_chip_target);
+ if (rc)
+ {
+ FAPI_ERR("clear_deep_exit_mask: Failed for Primary Target %s",
+ i_primary_chip_target.toEcmdString());
+ break;
+ }
+
+ // Secondary
+ if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
+ {
+ rc = clear_deep_exit_mask(i_secondary_chip_target);
+ if (rc)
+ {
+ FAPI_ERR("clear_deep_exit_mask: Failed for Secondary Target %s",
+ i_secondary_chip_target.toEcmdString());
+ break;
+ }
+ }
+
+
// ******************************************************************
// FSM trace
// ******************************************************************
rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "start of prep for reset");
- if (!rc.ok())
+ if (!rc.ok())
{
break;
}
-
+
// ******************************************************************
- // Put all EX chiplets in special wakeup
+ // Put all EX chiplets in special wakeup
// *****************************************************************
// This is done before FIR masking to ensure that idle functions
// are properly monitored
-
+
// Primary
rc = special_wakeup_all (i_primary_chip_target, true);
if (rc)
{
- FAPI_ERR("special_wakeup_all - Enable: Failed for Target %s",
+ FAPI_ERR("special_wakeup_all - Enable: Failed for Target %s",
i_primary_chip_target.toEcmdString());
break;
- }
+ }
b_special_wakeup_pri = true;
-
+
rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after SPWKUP");
- if (!rc.ok()) { break; }
-
+ if (!rc.ok()) { break; }
+
// Secondary
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
{
rc = special_wakeup_all (i_secondary_chip_target, true);
if (rc)
{
- FAPI_ERR("special_wakeup_all - Enable: Failed for Target %s",
+ FAPI_ERR("special_wakeup_all - Enable: Failed for Target %s",
i_secondary_chip_target.toEcmdString());
break;
}
- b_special_wakeup_sec = true;
-
+ b_special_wakeup_sec = true;
+
rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after SPWKUP");
- if (!rc.ok()) { break; }
-
- }
-
+ if (!rc.ok()) { break; }
+
+ }
+
// ******************************************************************
// FSM trace
// ******************************************************************
- rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
+ rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
"after special wake-up setting");
- if (!rc.ok())
+ if (!rc.ok())
{
break;
}
@@ -264,8 +293,8 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
}
rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after Masking");
- if (!rc.ok()) { break; }
-
+ if (!rc.ok()) { break; }
+
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
{
@@ -275,24 +304,24 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
FAPI_ERR("ERROR: p8_pm_firinit detected failed result");
break;
}
-
+
rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after Masking");
- if (!rc.ok()) { break; }
+ if (!rc.ok()) { break; }
}
-
+
// ******************************************************************
// FSM trace
// ******************************************************************
- rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
+ rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
"after FIR masking");
- if (!rc.ok())
+ if (!rc.ok())
{
break;
}
// ******************************************************************
// Disable PMC OCC HEARTBEAT before reset OCC
- // ******************************************************************
+ // ******************************************************************
// Primary
rc = fapiGetScom(i_primary_chip_target, PMC_OCC_HEARTBEAT_REG_0x00062066 , data );
if (rc)
@@ -344,7 +373,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
// ******************************************************************
// Put OCC PPC405 into reset safely
- // ******************************************************************
+ // ******************************************************************
FAPI_INF("Put OCC PPC405 into reset safely");
FAPI_DBG("Executing: p8_occ_control.C");
@@ -364,28 +393,28 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
break;
}
}
-
+
// ******************************************************************
// FSM trace
// ******************************************************************
- rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
+ rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
"after OCC Reset");
- if (!rc.ok())
+ if (!rc.ok())
{
break;
}
-
+
// Check for xstops and recoverables
rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after OCC Reset");
- if (!rc.ok()) { break; }
-
+ if (!rc.ok()) { break; }
+
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
- {
+ {
rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after OCC Reset");
- if (!rc.ok()) { break; }
+ if (!rc.ok()) { break; }
}
-
+
// ******************************************************************
// Force Vsafe value into voltage controller
// ******************************************************************
@@ -400,7 +429,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
FAPI_ERR("Failed to force Vsafe value into voltage controller. With rc = 0x%x", (uint32_t)rc);
break;
}
-
+
// Secondary
// Primary passed in for FFDC reasons upon error
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
@@ -410,31 +439,31 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
{
FAPI_ERR("Failed to force Vsafe value into voltage controller. With rc = 0x%x", (uint32_t)rc);
break;
- }
+ }
}
-
+
// ******************************************************************
// FSM trace
// ******************************************************************
- rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
+ rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
"after force Vsafe");
- if (!rc.ok())
+ if (!rc.ok())
{
break;
}
-
+
// Check for xstops and recoverables
rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after Force Vsafe");
- if (!rc.ok()) { break; }
-
+ if (!rc.ok()) { break; }
+
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
- {
+ {
rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after Force Vsafe");
- if (!rc.ok()) { break; }
- }
-
+ if (!rc.ok()) { break; }
+ }
+
// ******************************************************************
- // Prepare PCBSLV_PM for RESET
+ // Prepare PCBS_PM for RESET
// ******************************************************************
// - p8_pcbs_init internally loops over all enabled chiplets
FAPI_INF("Prepare PCBSLV_PM for RESET");
@@ -454,7 +483,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
{
FAPI_INF("Recoverable attention is **ACTIVE** in prep_for_reset after PCBS reset");
}
-
+
// Secondary
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
{
@@ -465,32 +494,32 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
FAPI_ERR("p8_pcbs_init: Failed to prepare PCBSLV_PM for RESET. With rc = 0x%x", (uint32_t)rc);
break;
}
-
+
GETSCOM(rc, i_secondary_chip_target, address, data);
if (data.getNumBitsSet(0,64))
{
FAPI_INF("Recoverable attention is **ACTIVE** in prep_for_reset after PCBS reset");
}
}
-
+
// ******************************************************************
// FSM trace
// ******************************************************************
rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "after PCBS reset");
- if (!rc.ok())
+ if (!rc.ok())
{
break;
}
-
+
// Check for xstops and recoverables
rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after PCBS reset");
- if (!rc.ok()) { break; }
-
+ if (!rc.ok()) { break; }
+
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
- {
+ {
rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after PCBS reset");
- if (!rc.ok()) { break; }
- }
+ if (!rc.ok()) { break; }
+ }
// ******************************************************************
// Reset PMC
@@ -504,21 +533,21 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
FAPI_ERR("p8_pmc_init: Failed to issue PMC reset. With rc = 0x%x", (uint32_t)rc);
break;
}
-
+
// ******************************************************************
// FSM trace
// ******************************************************************
- rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
+ rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
"after PMC reset");
- if (!rc.ok())
+ if (!rc.ok())
{
break;
}
-
+
// ******************************************************************
// As the PMC reset kills ALL of the configuration, the idle portion
- // must be reestablished to allow that portion to operate. This is
- // what p8_poreslw_init -init does. Additionally, this lets us drop
+ // must be reestablished to allow that portion to operate. This is
+ // what p8_poreslw_init -init does. Additionally, this lets us drop
// special wake-up before exiting.
// ******************************************************************
// - call p8_poreslw_init.C *chiptarget, ENUM:PM_INIT
@@ -526,7 +555,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
FAPI_INF("Re-establish PMC Idle configuration");
FAPI_DBG("Executing: p8_poreslw_init in mode %s", PM_MODE_NAME(PM_INIT_PMC));
-
+
// Primary
FAPI_EXEC_HWP(rc, p8_poreslw_init, i_primary_chip_target, PM_INIT_PMC);
if (rc)
@@ -546,17 +575,17 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
break;
}
}
-
+
// Check for xstops and recoverables
rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after PMC and SLW reinit");
- if (!rc.ok()) { break; }
-
+ if (!rc.ok()) { break; }
+
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
- {
+ {
rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after PMC and SLW reinit");
- if (!rc.ok()) { break; }
- }
-
+ if (!rc.ok()) { break; }
+ }
+
// ******************************************************************
// Issue reset to PSS macro
// ******************************************************************
@@ -584,7 +613,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
break;
}
}
-
+
// ******************************************************************
// Issue reset to PORE General Purpose Engine
// ******************************************************************
@@ -637,13 +666,13 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
}
// Check for xstops and recoverables
rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after PBA reset");
- if (!rc.ok()) { break; }
-
+ if (!rc.ok()) { break; }
+
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
- {
+ {
rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after PBA reset");
- if (!rc.ok()) { break; }
- }
+ if (!rc.ok()) { break; }
+ }
// ******************************************************************
// Issue reset to OCC-SRAM
@@ -695,30 +724,30 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
break;
}
}
-
+
// Check for xstops and recoverables
rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after OCB reset");
- if (!rc.ok()) { break; }
-
+ if (!rc.ok()) { break; }
+
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
- {
+ {
rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after OCB reset");
- if (!rc.ok()) { break; }
- }
+ if (!rc.ok()) { break; }
+ }
// ******************************************************************
// Remove the EX chiplet special wakeups
// *****************************************************************
-
+
// Primary
rc = special_wakeup_all (i_primary_chip_target, false);
if (rc)
{
- FAPI_ERR("special_wakeup_all - Disable: Failed for Target %s",
+ FAPI_ERR("special_wakeup_all - Disable: Failed for Target %s",
i_primary_chip_target.toEcmdString());
break;
}
b_special_wakeup_pri = false;
-
+
// Secondary
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
@@ -726,38 +755,38 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
rc = special_wakeup_all (i_secondary_chip_target, false);
if (rc)
{
- FAPI_ERR("special_wakeup_all - Disable: Failed for Target %s",
+ FAPI_ERR("special_wakeup_all - Disable: Failed for Target %s",
i_secondary_chip_target.toEcmdString());
break;
}
-
+
b_special_wakeup_sec = false;
}
-
-
+
+
// ******************************************************************
// FSM trace
// ******************************************************************
- rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
+ rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target,
"after special wake-up clearing");
- if (!rc.ok())
+ if (!rc.ok())
{
break;
}
-
+
// Check for xstops and recoverables
rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after special wake-up clearing");
- if (!rc.ok()) { break; }
-
+ if (!rc.ok()) { break; }
+
if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
- {
+ {
rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after special wake-up clearing");
- if (!rc.ok()) { break; }
- }
-
+ if (!rc.ok()) { break; }
+ }
+
} while(0);
-
-
+
+
// Clear special wakeups that might have been set before a subsequent
// error occured. Only attempts them on targets that have the boolean
// flag set that they were successfully put into special wakeup.
@@ -765,9 +794,9 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
{
// Save the original RC
rc_hold = rc;
-
+
do
- {
+ {
// Primary
if (b_special_wakeup_pri)
{
@@ -775,9 +804,9 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
rc = special_wakeup_all (i_primary_chip_target, false);
if (rc)
{
- FAPI_ERR("special_wakeup_all - Disable: Failed during cleanup from a previous error for Target %s",
+ FAPI_ERR("special_wakeup_all - Disable: Failed during cleanup from a previous error for Target %s",
i_primary_chip_target.toEcmdString());
- FAPI_ERR("special_wakeup_all - Disable: The original error is being returned");
+ FAPI_ERR("special_wakeup_all - Disable: The original error is being returned");
fapiLogError(rc, fapi::FAPI_ERRL_SEV_RECOVERED);
break;
}
@@ -789,7 +818,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
rc = special_wakeup_all (i_secondary_chip_target, false);
if (rc)
{
- FAPI_ERR("special_wakeup_all - Disable: Failed during cleanup from a previous error for Target %s",
+ FAPI_ERR("special_wakeup_all - Disable: Failed during cleanup from a previous error for Target %s",
i_primary_chip_target.toEcmdString());
FAPI_ERR("special_wakeup_all - Disable: The original error is being returned");
fapiLogError(rc, fapi::FAPI_ERRL_SEV_RECOVERED);
@@ -797,7 +826,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
}
}
} while(0);
-
+
// Restore the original RC
rc = rc_hold;
}
@@ -808,7 +837,7 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
} // Procedure
/**
- * special_wakeup_all - Sets or clears special wake-up on all configured EX on a
+ * special_wakeup_all - Sets or clears special wake-up on all configured EX on a
* target
*
* @param[in] i_target Chip target w
@@ -820,13 +849,13 @@ p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target,
fapi::ReturnCode
special_wakeup_all (const fapi::Target &i_target, bool i_action)
{
- fapi::ReturnCode rc;
+ fapi::ReturnCode rc;
std::vector<fapi::Target> l_exChiplets;
- uint8_t l_ex_number = 0;
-
+ uint8_t l_ex_number = 0;
+
do
- {
-
+ {
+
rc = fapiGetChildChiplets ( i_target,
TARGET_TYPE_EX_CHIPLET,
l_exChiplets,
@@ -836,15 +865,15 @@ special_wakeup_all (const fapi::Target &i_target, bool i_action)
FAPI_ERR("Error from fapiGetChildChiplets!");
break;
}
-
+
// Iterate through the returned chiplets
for (uint8_t j=0; j < l_exChiplets.size(); j++)
{
-
- FAPI_INF("\t%s special wake-up on %s",
- i_action ? "Setting" : "Clearing",
+
+ FAPI_INF("\t%s special wake-up on %s",
+ i_action ? "Setting" : "Clearing",
l_exChiplets[j].toEcmdString());
-
+
// Build the SCOM address
rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &l_exChiplets[j], l_ex_number);
FAPI_DBG("Running special wakeup on ex chiplet %d ", l_ex_number);
@@ -853,7 +882,7 @@ special_wakeup_all (const fapi::Target &i_target, bool i_action)
rc = fapiSpecialWakeup(l_exChiplets[j], i_action);
if (rc)
{
- FAPI_ERR("fapiSpecialWakeup: Failed to put CORE %d into special wakeup. With rc = 0x%x",
+ FAPI_ERR("fapiSpecialWakeup: Failed to put CORE %d into special wakeup. With rc = 0x%x",
l_ex_number, (uint32_t)rc);
break;
}
@@ -863,13 +892,68 @@ special_wakeup_all (const fapi::Target &i_target, bool i_action)
// Exit if error
if (!rc.ok())
{
+
+ break;
+ }
+
+ } while(0);
+ return rc;
+}
+
+/**
+ * clear deep exit mask
+ *
+ * @param[in] i_target Chip target w
+ *
+ * @retval ECMD_SUCCESS
+ * @retval ERROR defined in xml
+ */
+fapi::ReturnCode
+clear_deep_exit_mask (const fapi::Target &i_target)
+{
+ fapi::ReturnCode rc;
+ ecmdDataBufferBase data(64);
+
+ do
+ {
+
+ FAPI_INF("Clearing PMC Deep Exit Mask");
+
+ // Read the present values for debug
+ rc = fapiGetScom(i_target, PMC_DEEPEXIT_MASK_0x00062092, data);
+ if(!rc.ok())
+ {
+ FAPI_ERR("Scom error reading PMC_DEEPEXIT_MASK_0x00062092");
+ break;
+ }
+
+ FAPI_INF("PMC Deep Exit Mask value before clearing: 0x%16llX",
+ data.getDoubleWord(0));
+
+ // Clear the PMC Deep Exit Mask
+ data.flushTo0();
+ rc = fapiPutScom(i_target, PMC_DEEPEXIT_MASK_0x00062092, data);
+ if(!rc.ok())
+ {
+ FAPI_ERR("Scom error reading PMC_DEEPEXIT_MASK_0x00062092");
+ break;
+ }
+
+ rc = fapiGetScom(i_target, PMC_DEEPEXIT_MASK_0x00062092, data);
+ if(!rc.ok())
+ {
+ FAPI_ERR("Scom error reading PMC_DEEPEXIT_MASK_0x00062092");
break;
}
+ FAPI_INF("PMC Deep Exit Mask value after clearing: 0x%16llX",
+ data.getDoubleWord(0));
+
} while(0);
return rc;
}
+
//------------------------------------------------------------------------------
/**
* Trace PCBS FSMs across primary and secondary chips
@@ -882,32 +966,32 @@ special_wakeup_all (const fapi::Target &i_target, bool i_action)
*/
fapi::ReturnCode
p4rs_pcbs_fsm_trace(const fapi::Target& i_primary_target,
- const fapi::Target& i_secondary_target,
+ const fapi::Target& i_secondary_target,
const char * i_msg)
{
fapi::ReturnCode rc;
do
{
-
+
rc = p8_pm_pcbs_fsm_trace_chip (i_primary_target, i_msg);
if (rc)
{
- FAPI_ERR("pcbs_fsm_trace_chip failed for Target %s",
+ FAPI_ERR("pcbs_fsm_trace_chip failed for Target %s",
i_primary_target.toEcmdString());
break;
- }
+ }
if ( i_secondary_target.getType() != TARGET_TYPE_NONE )
{
rc = p8_pm_pcbs_fsm_trace_chip (i_secondary_target, i_msg);
if (rc)
{
- FAPI_ERR("pcbs_fsm_trace_chip failed for Target %s",
+ FAPI_ERR("pcbs_fsm_trace_chip failed for Target %s",
i_secondary_target.toEcmdString());
break;
- }
- }
+ }
+ }
} while(0);
return rc;
}
diff --git a/src/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c b/src/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c
index e6d7df2e0..88d136bdf 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c
+++ b/src/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,11 +22,15 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: gpstCheckByte.c,v 1.1 2012/10/16 16:30:15 jimyac Exp $
+// $Id: gpstCheckByte.c,v 1.3 2015/06/01 19:02:17 stillgs Exp $
/// \file gpamCheckByte.c
/// \brief Generate Pstate table check byte - Generated by genGpstCheckByte.tcl
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdint.h>
#define BIT(x, n) (((x) >> (63 - (n))) & 1)
@@ -227,3 +233,6 @@ gpstCheckByte(uint64_t gpstEntry)
(cb[7] << 0);
}
+#ifdef __cplusplus
+} // end extern C
+#endif
diff --git a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c
index f38a3c539..a53ca86e6 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c
+++ b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c
@@ -22,7 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: lab_pstates.c,v 1.10 2015/03/12 18:06:46 stillgs Exp $
+// $Id: lab_pstates.c,v 1.12 2015/06/01 19:02:17 stillgs Exp $
/// \file lab_pstates.c
/// \brief Lab-only (as opposed to product-procedure) support for Pstates.
@@ -30,6 +30,10 @@
/// Lab-only Pstate support is separated from generic Pstate support to reduce
/// the size of OCC product firmware images.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "ssx.h"
// jwy #include "ppc32.h"
#include "lab_pstates.h"
@@ -52,7 +56,7 @@
/// \bug Confirm if the 1.6125V offset is still valid for PgP
// Recall that VRM11 is inverted; rounding a VID code up rounds down the
-// voltage.
+// voltage.
int
vuv2vrm11(uint32_t v_uv, int round, uint8_t *vrm11_vid)
@@ -95,7 +99,7 @@ vrm112vuv(uint8_t vrm11_vid, uint32_t *v_uv)
/// \retval 0 Success
///
/// \retval -IVID_INVALID_VOLTAGE If \a v_uv can not be converted to a legal
-/// IVID encoding.
+/// IVID encoding.
int
vuv2ivid(uint32_t v_uv, int round, uint8_t *ivid)
@@ -109,7 +113,7 @@ vuv2ivid(uint32_t v_uv, int round, uint8_t *ivid)
if (((offset % IVID_STEP_UV) != 0) && (round >= 0)) {
vid++;
}
-
+
*ivid = vid;
if ((vid < 0) || (vid > 0x7f)) {
rc = -IVID_INVALID_VOLTAGE;
@@ -118,7 +122,7 @@ vuv2ivid(uint32_t v_uv, int round, uint8_t *ivid)
}
return rc;
}
-
+
/// Convert an iVID code to a voltage in microvolts
int
@@ -132,6 +136,15 @@ ivid2vuv(uint8_t ivid, uint32_t *v_uv)
}
}
+/// Convert a VPD current (in 0.5A units) to milliamps
+
+int
+vpdcur2ima(uint16_t i_vpdcur, uint32_t *i_ma)
+{
+ *i_ma = (i_vpdcur * 1000 / 2);
+ return 0;
+}
+
/// Format a voltage in microvolts as 10 microvolts into a user-supplied
/// string.. The string \a s must be able to store at least
/// FORMAT_10UV_STRLEN characters.
@@ -142,6 +155,17 @@ sprintf_10uv(char *s, uint32_t v_uv)
return sprintf(s, "%d.%05d", v_uv / 1000000, (v_uv % 1000000) / 10);
}
+/// Format a current in milliamps into a user-supplied
+/// string.. The string \a s must be able to store at least
+/// FORMAT_IMA_STRLEN characters.
+
+int
+sprintf_ima(char *s, uint32_t i_ma)
+{
+ return sprintf(s, "%d.%03d", i_ma / 1000, i_ma % 1000);
+}
+
+
#ifdef FAPIECMD
/// Format a voltage in microvolts as 10 microvolts to a stream.
@@ -225,10 +249,40 @@ fprintf_ivid(FILE *stream, uint8_t ivid)
return rc;
}
+/// Format a VPD current code as .5A into a user-supplied string. The
+/// string \a s must be able to store at least FORMAT_0P5A_STRLEN characters.
+
+int
+sprintf_vpd_current(char *s, uint16_t current)
+{
+ int rc;
+ uint32_t i_ma;
+
+ if ((rc = vpdcur2ima(current, &i_ma)) != 0) {
+ return rc;
+ }
+ return sprintf_ima(s, i_ma);
+}
+
+
+int
+fprintf_vpd_current(FILE *stream, uint16_t current)
+{
+ int rc;
+ char s[FORMAT_IMA_STRLEN];
+
+ rc = sprintf_vpd_current(s, current);
+ if (rc > 0) {
+ rc = fputs(s, stream);
+ }
+ return rc;
+}
+
+
// NB: The gpst_print() routine only needs the revle* functions when compiled
// into little-endian Linux applications, which must provide their
-// implementations.
+// implementations.
#ifdef _BIG_ENDIAN
@@ -261,7 +315,7 @@ gpst_print(FILE *stream, GlobalPstateTable *gpst)
uint8_t entries, pstate_stepsize, vrm_stepdelay_range, vrm_stepdelay_value;
// Pstate pmin, pvsafe, psafe;
Pstate pvsafe, psafe;
-
+
// Endian-corrected vector Pstate fields
@@ -279,7 +333,13 @@ gpst_print(FILE *stream, GlobalPstateTable *gpst)
char evid_vcs_eff_str[FORMAT_10UV_STRLEN];
char maxreg_vdd_str[FORMAT_10UV_STRLEN];
char maxreg_vcs_str[FORMAT_10UV_STRLEN];
+ char* ivrm_max_ps_str;
+ char* ultraturbo_ps_str;
+ char* turbo_ps_str;
+ char* nominal_ps_str;
+ char* powersave_ps_str;
+
// Get endian-corrected scalars
options = revle32(gpst->options.options);
@@ -294,11 +354,11 @@ gpst_print(FILE *stream, GlobalPstateTable *gpst)
psafe = gpst->psafe;
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
fprintf(stream, "Global Pstate Table @ %p\n", gpst);
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
fprintf(stream, "%d Entries from %+d to %+d\n",
entries, gpst_pmin(gpst), gpst_pmax(gpst));
fprintf(stream, "Frequency Step = %u KHz\n", frequency_step_khz);
@@ -320,6 +380,10 @@ gpst_print(FILE *stream, GlobalPstateTable *gpst)
pstate_stepsize, vrm_stepdelay_range, vrm_stepdelay_value);
fprintf(stream, "Pvsafe %d, Psafe %d\n", pvsafe, psafe);
+ fprintf(stream, "iVRM Maximum Pstate %d, Number of GPST entries (from Psafe) where iVRMs are enabled: %d\n",
+ gpst->ivrm_max_ps, gpst->ivrm_entries);
+
+
if (options == 0) {
fprintf(stream, "No Options\n");
} else {
@@ -339,17 +403,20 @@ gpst_print(FILE *stream, GlobalPstateTable *gpst)
if (options & PSTATE_FORCE_INITIAL_PMIN) {
fprintf(stream, " PSTATE_FORCE_INITIAL_PMIN\n");
}
+ if (options & PSTATE_IDDQ_0P80V_VALID) {
+ fprintf(stream, " PSTATE_IDDQ_0P80V_VALID\n");
+ }
}
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
- fprintf(stream,
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream,
" I Pstate F(MHz) evid_vdd(V) evid_vcs(V) evid_vdd_eff(V) evid_vcs_eff(V) maxreg_vdd(V) maxreg_vcs(V)\n"
"---------------------------------------------------------------------------------------------------------\n");
for (i = gpst->entries - 1; i >= 0; i--) {
entry.value = revle64(gpst->pstate[i].value);
-
+
evid_vdd = entry.fields.evid_vdd;
sprintf_vrm11(evid_vdd_str, evid_vdd);
@@ -369,8 +436,28 @@ gpst_print(FILE *stream, GlobalPstateTable *gpst)
sprintf_ivid(maxreg_vcs_str, maxreg_vcs);
pstate = gpst_pmin(gpst) + i;
-
- fprintf(stream,
+
+ ultraturbo_ps_str = "";
+ if (pstate == 0 && gpst->turbo_ps != 0)
+ ultraturbo_ps_str = " <--- UltraTurbo";
+
+ turbo_ps_str = "";
+ if (pstate == gpst->turbo_ps)
+ turbo_ps_str = " <--- Turbo";
+
+ nominal_ps_str = "";
+ if (pstate == gpst->nominal_ps)
+ nominal_ps_str = " <--- Nominal";
+
+ powersave_ps_str = "";
+ if (pstate == gpst->powersave_ps)
+ powersave_ps_str = " <--- PowerSave";
+
+ ivrm_max_ps_str = "";
+ if (pstate == gpst->ivrm_max_ps)
+ ivrm_max_ps_str = " <--- iVRM Maximum";
+
+ fprintf(stream,
"%3d %+4d "
"%4d "
"0x%02x %s "
@@ -378,7 +465,8 @@ gpst_print(FILE *stream, GlobalPstateTable *gpst)
"0x%02x %s "
"0x%02x %s "
"0x%02x %s "
- "0x%02x %s\n",
+ "0x%02x %s "
+ "%s%s%s%s%s\n",
i, pstate,
(pstate0_frequency_khz + (frequency_step_khz * pstate)) / 1000,
evid_vdd, evid_vdd_str,
@@ -386,10 +474,15 @@ gpst_print(FILE *stream, GlobalPstateTable *gpst)
evid_vdd_eff, evid_vdd_eff_str,
evid_vcs_eff, evid_vcs_eff_str,
maxreg_vdd, maxreg_vdd_str,
- maxreg_vcs, maxreg_vcs_str);
+ maxreg_vcs, maxreg_vcs_str,
+ ultraturbo_ps_str,
+ turbo_ps_str,
+ nominal_ps_str,
+ powersave_ps_str,
+ ivrm_max_ps_str);
}
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
}
@@ -408,37 +501,37 @@ lpsa_print(FILE* stream, LocalPstateArray* lpsa)
uint8_t entries;
uint8_t entries_div4;
char ivid_vdd_str[FORMAT_10UV_STRLEN];
- char ivid_vcs_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,
+ "---------------------------------------------------------------------------------------------------------\n");
fprintf(stream, "Local Pstate Array @ %p\n", lpsa);
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
+ 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_lowering);
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------------------\n");
- fprintf(stream,
+ 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;
-
+ entries_div4 = entries/4;
+
if ( entries % 4 != 0)
entries_div4++;
-
- for (i = entries_div4-1 ; i >= 0; i--) {
+
+ 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);
@@ -466,20 +559,20 @@ lpsa_print(FILE* stream, LocalPstateArray* lpsa)
(uint8_t)lpst_entry.fields.dec_step);
}
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------------------\n\n");
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------------------\n\n");
- fprintf(stream,
+ fprintf(stream,
"--------------------------------\n");
- fprintf(stream,
- "VDS\n");
- fprintf(stream,
+ fprintf(stream,
+ "VDS\n");
+ fprintf(stream,
" I beg_offset end_offset \n"
- "--------------------------------\n");
+ "--------------------------------\n");
- for (i = 15 ; i >= 0; i--) {
+ for (i = 15 ; i >= 0; i--) {
vdsvin_entry.value = revle64(lpsa->vdsvin[i].value);
-
+
fprintf(stream,
"%2u "
"%-10u "
@@ -489,38 +582,38 @@ lpsa_print(FILE* stream, LocalPstateArray* lpsa)
(uint8_t)vdsvin_entry.fields.ivid1);
}
- fprintf(stream,
- "--------------------------------\n\n");
-
+ fprintf(stream,
+ "--------------------------------\n\n");
+
- fprintf(stream,
+ fprintf(stream,
"-----------------------------------------------------\n");
- fprintf(stream,
- "VIN\n");
- fprintf(stream,
+ fprintf(stream,
+ "VIN\n");
+ fprintf(stream,
" I ptef0 pfet1 pfet2 pfet3 pfet4 pfet5 pfet6 pfet7\n"
- "-----------------------------------------------------\n");
+ "-----------------------------------------------------\n");
- for (i = 63 ; i >= 0; i--) {
+ 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");
-}
+ (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
///
@@ -532,26 +625,26 @@ void
cpmrange_print(FILE* stream, CpmPstateModeRanges* cpmrange)
{
int i;
-
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
fprintf(stream, "CPM Pstate Range @ %p\n", cpmrange);
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
- fprintf(stream, "Valid Number of CPM Pstate Ranges : %u\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",
+
+ 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");
+
+ fprintf(stream, " CPM Pmax : %d\n",
+ cpmrange->pMax);
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
}
/// Print a Resonant Clocking Setup structure on a given stream
@@ -563,26 +656,242 @@ cpmrange_print(FILE* stream, CpmPstateModeRanges* cpmrange)
void
resclk_print(FILE* stream, ResonantClockingSetup* resclk)
{
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
fprintf(stream, "Resonant Clocking Setup @ %p\n", resclk);
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
- fprintf(stream, "Full Clock Sector Buffer Pstate : %d\n",
+ fprintf(stream, " Full Clock Sector Buffer Pstate : %2d\n",
resclk->full_csb_ps);
- fprintf(stream, "Low Frequency Resonant Lower Pstate : %d\n",
+ fprintf(stream, " Low Frequency Resonant Lower Pstate : %2d\n",
resclk->res_low_lower_ps);
- fprintf(stream, "Low Frequency Resonant Upper Pstate : %d\n",
+ fprintf(stream, " Low Frequency Resonant Upper Pstate : %2d\n",
resclk->res_low_upper_ps);
- fprintf(stream, "High Frequency Resonant Lower Pstate : %d\n",
+ fprintf(stream, " High Frequency Resonant Lower Pstate : %2d\n",
resclk->res_high_lower_ps);
- fprintf(stream, "High Frequency Resonant Upper Pstate : %d\n",
+ fprintf(stream, " High Frequency Resonant Upper Pstate : %2d\n",
resclk->res_high_upper_ps);
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+}
+
+/// Print an IDDQ structure on a given stream
+///
+/// \param stream The output stream
+///
+/// \param iddq The IddqTable to print
+
+void
+iddq_print(FILE* stream, IddqTable* iddq)
+{
+ uint32_t i, j;
+ const uint8_t vdd_measurement_order[LRP_IDDQ_RECORDS] = CORE_IDDQ_MEASUREMENTS_ORDER;
+ const char *core_measurement_str[LRP_IDDQ_RECORDS] = CORE_IDDQ_MEASUREMENT_VOLTAGES;
+ const uint8_t vcs_measurement_order[LRP_IDDQ_RECORDS] = CORE_IDDQ_MEASUREMENTS_ORDER;
+ const char *chip_measurement_str[CRP_IDDQ_RECORDS] = CHIP_IDDQ_MEASUREMENT_VOLTAGES;
+ const uint8_t vio_measurement_order[CRP_IDDQ_RECORDS] = CHIP_IDDQ_MEASUREMENTS_ORDER;
+
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream, "IDDQ Table (version %d) @ %p\n", iddq->iddq_version, iddq);
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+
+
+ for (i = 0; i < CORE_IDDQ_MEASUREMENTS; i++) {
+ for (j = 0; j < CORE_IDDQ_MEASUREMENTS; j++) {
+ if (vdd_measurement_order[j] == i)
+ fprintf(stream, " Core VDD IDDQ @ %sV Raw : 0x%04X, %6d mA; Temperature Corrected: 0x%04X, %6d mA\n",
+ core_measurement_str[j],
+ iddq->iddq_vdd[vdd_measurement_order[j]].fields.iddq_raw_value,
+ iddq->iddq_vdd[vdd_measurement_order[j]].fields.iddq_raw_value*10,
+ iddq->iddq_vdd[vdd_measurement_order[j]].fields.iddq_corrected_value,
+ iddq->iddq_vdd[vdd_measurement_order[j]].fields.iddq_corrected_value*10);
+ }
+ }
+
+ for (i = 0; i < CORE_IDDQ_MEASUREMENTS; i++) {
+ for (j = 0; j < CORE_IDDQ_MEASUREMENTS; j++) {
+ if (vcs_measurement_order[j] == i)
+ fprintf(stream, " Core VCS IDDQ @ %sV Raw : 0x%04X, %6d mA; Temperature Corrected: 0x%04X, %6d mA\n",
+ core_measurement_str[j],
+ iddq->iddq_vcs[vcs_measurement_order[j]].fields.iddq_raw_value,
+ iddq->iddq_vcs[vcs_measurement_order[j]].fields.iddq_raw_value*10,
+ iddq->iddq_vcs[vcs_measurement_order[j]].fields.iddq_corrected_value,
+ iddq->iddq_vcs[vcs_measurement_order[j]].fields.iddq_corrected_value*10);
+ }
+ }
+
+ for (i = 0; i < CHIP_IDDQ_MEASUREMENTS; i++) {
+ for (j = 0; j < CHIP_IDDQ_MEASUREMENTS; j++) {
+ if (vio_measurement_order[j] == i)
+ fprintf(stream, " Chip VIO IDDQ @ %sV Raw : 0x%04X, %6d mA; Temperature Corrected: 0x%04X, %6d mA\n",
+ chip_measurement_str[j],
+ iddq->iddq_vio[vio_measurement_order[j]].fields.iddq_raw_value,
+ iddq->iddq_vio[vio_measurement_order[j]].fields.iddq_raw_value*10,
+ iddq->iddq_vio[vio_measurement_order[j]].fields.iddq_corrected_value,
+ iddq->iddq_vio[vio_measurement_order[j]].fields.iddq_corrected_value*10);
+ }
+ }
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+}
+
+// ENUM defining the printable rails
+enum vidmod_rails
+{
+ VDD,
+ VCS
+};
+
+/// Print the VID Modification structure on a given stream
+///
+/// \param stream The output stream
+/// \param wof The WOF Element structure to print
+/// \param rail The rail to put out
+void
+vidmod_print(FILE* stream, WOFElements* wof, vidmod_rails rail)
+{
+ char line_str[256];
+ char entry_str[128];
- fprintf(stream,
- "---------------------------------------------------------------------------------------------------------\n");
-}
+ uint8_t evid;
+ char evid_str[FORMAT_10UV_STRLEN];
+
+ strcpy(entry_str, "");
+ strcpy(line_str, " Active Cores->");
+ for (int j=0; j < wof->ut_vid_mod.ut_max_cores; ++j)
+ {
+ sprintf(entry_str, " %2d ", j+1);
+ strcat(line_str, entry_str);
+ }
+ fprintf(stream, "%s\n", line_str);
+
+ strcpy(entry_str, "");
+ strcpy(line_str, " Index Pstate ");
+ for (int j=0; j < wof->ut_vid_mod.ut_max_cores; ++j)
+ {
+ if (rail == VDD)
+ sprintf(entry_str, " evid_vdd(V) ");
+ else
+ sprintf(entry_str, " evid_vcs(V) ");
+ strcat(line_str, entry_str);
+ }
+ fprintf(stream, "%s\n", line_str);
+
+ for (int i = wof->ut_vid_mod.ut_segment_pstates; i >= 0; --i)
+ {
+
+ sprintf(line_str, " %2d %+4d ",
+ i,
+ -wof->ut_vid_mod.ut_segment_pstates+i);
+
+ for (int j=0; j < wof->ut_vid_mod.ut_max_cores; ++j)
+ {
+ if (rail == VDD)
+ evid = wof->ut_vid_mod.ut_segment_vdd_vid[i][j];
+ else
+ evid = wof->ut_vid_mod.ut_segment_vcs_vid[i][j];
+
+ sprintf_vrm11(evid_str, evid);
+ strcpy(entry_str, "");
+ sprintf(entry_str, "0x%02x %s ",
+ evid, evid_str);
+ strcat(line_str, entry_str);
+
+ }
+ fprintf(stream, "%s\n", line_str);
+ }
+ return;
+}
+
+/// Print the WOF Element structure on a given stream
+///
+/// \param stream The output stream
+///
+/// \param wof The WOF Element structure to print
+
+void
+wof_print(FILE* stream, WOFElements* wof)
+{
+ const char *vpd_point_str[VPD_PV_POINTS] = VPD_PV_ORDER_STR;
+
+ char vpd_vdd_str[FORMAT_10UV_STRLEN];
+ char vpd_vcs_str[FORMAT_10UV_STRLEN];
+ char vpd_idd_str[FORMAT_IMA_STRLEN];
+ char vpd_ics_str[FORMAT_IMA_STRLEN];
+
+ uint32_t vdd, vcs, idd, ics;
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream, "Workload Optimized Frequency (WOF) elements @ %p\n", wof);
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+
+ fprintf(stream, "WOF Enabled\t: %d\n", wof->wof_enabled);
+
+ if (!wof->wof_enabled)
+ {
+ fprintf(stream, " >>>> With WOF Disabled, relevant content in the Pstate SuperStructure is not populated <<<<\n");
+ }
+
+ fprintf(stream, "VPD Points (biased without System Distribution Elements)\n");
+ for (int i=0; i < VPD_PV_POINTS; ++i)
+ {
+
+ vdd = wof->operating_points[i].vdd_5mv * 5 * 1000;
+ sprintf_10uv(vpd_vdd_str, vdd);
+
+ vcs = wof->operating_points[i].vcs_5mv * 5 * 1000;
+ sprintf_10uv(vpd_vcs_str, vcs);
+
+ idd = wof->operating_points[i].idd_500ma;
+ sprintf_vpd_current(vpd_idd_str, idd);
+
+ ics = wof->operating_points[i].ics_500ma;
+ sprintf_vpd_current(vpd_ics_str, ics);
+
+ fprintf(stream, " %s \t: %4d MHz VDD: %s V %s A VCS: %s V %s A\n",
+ vpd_point_str[i],
+ wof->operating_points[i].frequency_mhz,
+ vpd_vdd_str,
+ vpd_idd_str,
+ vpd_vcs_str,
+ vpd_ics_str
+ );
+ }
+
+ fprintf(stream, "System Distribution Elements\n");
+ fprintf(stream, " VDD loadline : %d uOhm\n", wof->vdd_sysparm.loadline_uohm);
+ fprintf(stream, " VCS loadline : %d uOhm\n", wof->vcs_sysparm.loadline_uohm);
+ fprintf(stream, " VDD distribution loss : %d uOhm\n", wof->vdd_sysparm.distloss_uohm);
+ fprintf(stream, " VCS distribution loss : %d uOhm\n", wof->vcs_sysparm.distloss_uohm);
+ fprintf(stream, " VDD distribution offset : %d uV\n", wof->vdd_sysparm.distoffset_uv);
+ fprintf(stream, " VCS distribution offset : %d uV\n", wof->vcs_sysparm.distoffset_uv);
+
+ fprintf(stream, "WOF Factors\n");
+ fprintf(stream, " TDP to RDP factor 0x%X --> %0.2f%% \n", wof->tdp_rdp_factor, (double)wof->tdp_rdp_factor/100);
+
+ fprintf(stream, "Pstates from Turbo to UltraTurbo (inclusive) : %d (from %-2d to %-2d)\n",
+ wof->ut_vid_mod.ut_segment_pstates+1, // +1 is for inclusivity
+ 0,
+ -(wof->ut_vid_mod.ut_segment_pstates));
+
+
+ fprintf(stream, "Turbo<>UltraTurbo VID Modification - VDD\n");
+ vidmod_print(stream, wof, VDD);
+
+ fprintf(stream, "Turbo<>UltraTurbo VID Modification - VCS\n");
+ vidmod_print(stream, wof, VCS);
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+}
/// Print a PstateSuperStructure on a given stream
@@ -594,19 +903,26 @@ resclk_print(FILE* stream, ResonantClockingSetup* resclk)
void
pss_print(FILE* stream, PstateSuperStructure* pss)
{
- fprintf(stream,
- "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
- fprintf(stream, "PstateSuperStructure @ %p\n", pss);
- fprintf(stream,
- "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
-
+ fprintf(stream,
+ "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+ fprintf(stream, "PstateSuperStructure @ %p; Size: %d bytes\n", pss, sizeof(PstateSuperStructure));
+ fprintf(stream,
+ "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+
gpst_print(stream, &(pss->gpst));
lpsa_print(stream, &(pss->lpsa));
+ cpmrange_print(stream, &(pss->cpmranges));
resclk_print(stream, &(pss->resclk));
-
- fprintf(stream,
- "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+ wof_print(stream, &(pss->wof));
+ iddq_print(stream, &(pss->iddq));
+
+ fprintf(stream,
+ "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
}
-
-#endif // FAPIECMD
+
+#endif // FAPIECMD
+
+#ifdef __cplusplus
+} // end extern C
+#endif
diff --git a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h
index c6da73d60..8d824011e 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h
+++ b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -23,7 +25,7 @@
#ifndef __LAB_PSTATES_H__
#define __LAB_PSTATES_H__
-// $Id: lab_pstates.h,v 1.5 2013/08/13 17:12:56 jimyac Exp $
+// $Id: lab_pstates.h,v 1.7 2015/06/01 19:02:17 stillgs Exp $
/// \file lab_pstates.h
/// \brief Lab-only (as opposed to product-procedure) support for Pstates.
@@ -43,6 +45,7 @@
///
/// \todo Replace with a typedef
#define FORMAT_10UV_STRLEN 8
+#define FORMAT_IMA_STRLEN 8
#define FORMAT_10UV_ERROR "<Error>"
@@ -51,6 +54,10 @@
#ifndef __ASSEMBLER__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
int
vuv2vrm11(uint32_t v_uv, int round, uint8_t *vrm11_vid);
@@ -96,10 +103,20 @@ void
resclk_print(FILE* stream, ResonantClockingSetup* resclk);
void
+iddq_print(FILE* stream, IddqTable* iddq);
+
+void
+wof_print(FILE* stream, WOFElements* wof);
+
+void
pss_print(FILE* stream, PstateSuperStructure* pss);
#endif // FAPIECMD
+#ifdef __cplusplus
+} // end extern C
+#endif
+
#endif // __ASSEMBLER__
#endif // __LAB_PSTATES_H__
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 a9ec97d13..6def3a095 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
@@ -23,7 +23,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: p8_build_pstate_datablock.C,v 1.44 2015/03/16 17:54:25 stillgs Exp $
+// $Id: p8_build_pstate_datablock.C,v 1.46 2015/06/01 18:50:36 stillgs 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
@@ -64,20 +64,63 @@
extern "C" {
-using namespace fapi;
+ using namespace fapi;
// ----------------------------------------------------------------------
// Function prototypes
// ----------------------------------------------------------------------
-ReturnCode proc_get_mvpd_data (const Target& i_target, uint32_t attr_mvpd_data[PV_D][PV_W], ivrm_mvpd_t *ivrm_mvpd, uint8_t *present_chiplets, uint8_t *functional_chiplets, uint8_t *poundm_valid, uint8_t *poundm_ver);
-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);
-ReturnCode proc_upd_psafe_ps (PstateSuperStructure *pss, const AttributeList *attr);
-ReturnCode proc_upd_floor_ps (PstateSuperStructure *pss, const AttributeList *attr);
-ReturnCode proc_chk_valid_poundv (const Target& i_target, const uint32_t chiplet_mvpd_data[PV_D][PV_W], uint8_t chiplet_num, uint8_t bucket_id);
-ReturnCode proc_res_clock (PstateSuperStructure *pss, AttributeList *attr_list);
+ ReturnCode proc_get_mvpd_data ( const Target& i_target,
+ AttributeList *attr,
+ uint32_t attr_mvpd_data[PV_D][PV_W],
+ uint32_t *valid_pdv_points,
+ ivrm_mvpd_t *ivrm_mvpd,
+ uint8_t *present_chiplets,
+ uint8_t *functional_chiplets,
+ uint8_t *poundm_valid,
+ uint8_t *poundm_ver);
+
+ ReturnCode proc_get_mvpd_iddq ( const Target& i_target,
+ PstateSuperStructure *pss);
+
+ ReturnCode proc_get_attributes ( const Target& i_target,
+ AttributeList *attr_list);
+
+ 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);
+
+ ReturnCode proc_upd_psafe_ps ( PstateSuperStructure *pss,
+ const AttributeList *attr);
+
+ ReturnCode proc_upd_floor_ps ( PstateSuperStructure *pss,
+ const AttributeList *attr);
+
+ ReturnCode proc_chk_valid_poundv ( const Target& i_target,
+ AttributeList *attr,
+ const uint32_t chiplet_mvpd_data[PV_D][PV_W],
+ uint32_t *valid_pdv_points,
+ uint8_t chiplet_num,
+ uint8_t bucket_id);
+
+ ReturnCode proc_res_clock ( PstateSuperStructure *pss,
+ AttributeList *attr_list);
+
+ ReturnCode load_wof_attributes ( PstateSuperStructure *pss,
+ const AttributeList *attr);
+
+ ReturnCode load_mvpd_operating_point (const uint32_t src[PV_D][PV_W],
+ VpdOperatingPoint *dest);
+
// ----------------------------------------------------------------------
// Function definitions
// ----------------------------------------------------------------------
@@ -87,423 +130,561 @@ ReturnCode proc_res_clock (PstateSuperStructure *pss, AttributeList *attr
/// \retval FAPI_RC_SUCCESS
/// \retval ERROR defined in xml
-ReturnCode
-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;
- uint8_t present_chiplets = 0;
- uint8_t functional_chiplets = 0;
- uint8_t poundm_ver = 0;
- uint8_t poundm_valid = 1; // assume valid until code determines invalid
- uint8_t lpst_valid = 1; // assume valid until code determines invalid
- uint8_t attr_pm_ivrms_enabled_wr = 0;
- uint8_t attr_pm_ivrms_enabled_rd = 0;
-
- const uint8_t pv_op_order[S132A_POINTS] = PV_OP_ORDER;
-
- 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;
-
- FAPI_INF("Executing p8_build_pstate_datablock ....");
-
- do
- {
- // -----------------------------------------------------------
- // Clear the PstateSuperStructure and install the magic number
- // -----------------------------------------------------------
- memset(io_pss, 0, sizeof(*io_pss));
- (*io_pss).magic = revle64(PSTATE_SUPERSTRUCTURE_MAGIC);
-
- // -------------------------
- // get all attributes needed
- // -------------------------
- FAPI_IMP("Getting Attributes to build Pstate Superstructure");
-
- l_rc = proc_get_attributes(i_target , &attr );
- if (l_rc) break;
-
- // calculate pstate frequency step in Khz
- frequency_step_khz = (attr.attr_freq_proc_refclock * 1000)/attr.attr_proc_dpll_divider;
-
- // --------------------------------
- // check chip ec feature attributes
- // --------------------------------
- if (attr.attr_proc_ec_core_hang_pulse_bug) {
- FAPI_INF("ATTR_PROC_EC_CORE_HANG_PULSE_BUG is set so disable iVRMs - setting PSTATE_NO_INSTALL_LPSA");
- (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) |
- PSTATE_NO_INSTALL_LPSA);
- poundm_valid = 0;
- lpst_valid = 0;
- }
+ ReturnCode
+ 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;
+ uint8_t present_chiplets = 0;
+ uint8_t functional_chiplets = 0;
+ uint8_t poundm_ver = 0;
+ uint8_t poundm_valid =
+ 1; // assume valid until code determines invalid
+ uint8_t lpst_valid =
+ 1; // assume valid until code determines invalid
+
+ uint32_t valid_pdv_points = 0;
+ uint8_t attr_pm_ivrms_enabled_wr = 0;
+ uint8_t attr_pm_ivrms_enabled_rd = 0;
- if (! attr.attr_chip_ec_feature_resonant_clk_valid) {
- FAPI_INF("ATTR_CHIP_EC_FEATURE_RESONANT_CLK_VALID is not set so disable resonant clocking - setting PSTATE_NO_INSTALL_RESCLK");
- (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) |
- PSTATE_NO_INSTALL_RESCLK );
- }
+ double volt_int_vdd_bias = 1.0;
+ double volt_int_vcs_bias = 1.0;
- // ----------------
- // get #V & #M data
- // ----------------
- FAPI_IMP("Getting #V & #M Data");
+ uint32_t frequency_step_khz = 0;
+ uint32_t attr_mvpd_voltage_control[PV_D][PV_W];
- // clear array
- memset(attr_mvpd_voltage_control, 0, sizeof(attr_mvpd_voltage_control));
- memset(&ivrm_mvpd, 0, sizeof(ivrm_mvpd));
+ ivrm_mvpd_t ivrm_mvpd;
- l_rc = proc_get_mvpd_data(i_target, attr_mvpd_voltage_control, &ivrm_mvpd, &present_chiplets, &functional_chiplets, &poundm_valid, &poundm_ver);
- if (l_rc) {
- break;
- }
- else if (!present_chiplets) {
- FAPI_ERR("**** ERROR : There are no cores present");
- const uint8_t &PRESENT_CHIPLETS = present_chiplets;
- const Target &CHIP_TARGET = i_target;
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_NO_CORES_PRESENT_ERROR);
- break;
- }
+ FAPI_INF("Executing p8_build_pstate_datablock ....");
- if (!functional_chiplets || !poundm_valid) {
+ do
+ {
+ // -----------------------------------------------------------
+ // Clear the PstateSuperStructure and install the magic number
+ // -----------------------------------------------------------
+ memset(io_pss, 0, sizeof(*io_pss));
+ (*io_pss).magic = revle64(PSTATE_SUPERSTRUCTURE_MAGIC);
- if (!functional_chiplets)
- {
- FAPI_IMP("No FUNCTIONAL chiplets found - set PSTATE_NO_INSTALL_LPSA");
- }
- else
- {
- FAPI_IMP("Invalid #M found - set PSTATE_NO_INSTALL_LPSA");
- }
+ // -------------------------
+ // get all attributes needed
+ // -------------------------
+ FAPI_IMP("Getting Attributes to build Pstate Superstructure");
- // indicate no LPST installed in PSS
- (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) |
- PSTATE_NO_INSTALL_LPSA);
- }
+ l_rc = proc_get_attributes(i_target , &attr );
- // ---------------------------------------------
- // process external and internal bias attributes
- // ---------------------------------------------
- FAPI_IMP("Apply Biasing to #V");
-
- l_rc = proc_get_extint_bias(attr_mvpd_voltage_control, &attr, &volt_int_vdd_bias, &volt_int_vcs_bias);
- if (l_rc) break;
-
- // -----------------------------------------------
- // populate VpdOperatingPoint with MVPD attributes
- // -----------------------------------------------
- // Assumes a constant 100mV dead zone
- VpdOperatingPoint s132a_vpd[S132A_POINTS];
-
- for (i = 0; i < S132A_POINTS; i++) {
- s132a_vpd[i].frequency_mhz = attr_mvpd_voltage_control[pv_op_order[i]][0];
- s132a_vpd[i].vdd_5mv = attr_mvpd_voltage_control[pv_op_order[i]][1];
- s132a_vpd[i].idd_500ma = attr_mvpd_voltage_control[pv_op_order[i]][2];
- s132a_vpd[i].vdd_maxreg_5mv = attr_mvpd_voltage_control[pv_op_order[i]][1] - DEAD_ZONE_5MV;
- s132a_vpd[i].vcs_5mv = attr_mvpd_voltage_control[pv_op_order[i]][3];
- 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;
- }
+ if (l_rc)
+ {
+ break;
+ }
- // -------------------------------------------------------------------
- // Create s132a_points and filled in by chip_characterization_create()
- // -------------------------------------------------------------------
- OperatingPoint s132a_points[S132A_POINTS];
-
- // -------------------------------------------------
- // populate OperatingPointParameters with attributes
- // -------------------------------------------------
- // Parameters from a P7 system, consistent with s132a. We'll assume the
- // 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) / 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;
- // SW267784
- s132a_parms.vdd_voffset_uv = attr.attr_proc_vrm_voffset_vdd;
- s132a_parms.vcs_voffset_uv = attr.attr_proc_vrm_voffset_vcs;
-
- // --------------------------------------
- // Create Chip characterization structure
- // --------------------------------------
-
- ChipCharacterization s132a_characterization;
- s132a_characterization.vpd = s132a_vpd;
- s132a_characterization.ops = s132a_points;
- s132a_characterization.parameters = &s132a_parms;
- s132a_characterization.points = S132A_POINTS;
-
- // ---------------------------
- // Finish the characterization
- // ---------------------------
- characterization = &s132a_characterization;
-
- rc = chip_characterization_create(characterization,
- characterization->vpd,
- characterization->ops,
- characterization->parameters,
- characterization->points);
-
- // check for error
- int & CHAR_RETURN_CODE = rc;
- if (rc == -GPST_INVALID_OBJECT) {
- FAPI_ERR("**** ERROR : chip_characterization_create was passed null pointer to characterization or characterization->parameters");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_CHARACTERIZATION_OBJECT_ERROR);
- break;
- }
- else if (rc == -GPST_INVALID_ARGUMENT) {
- int & POINTS = characterization->points;
- FAPI_ERR("**** ERROR : chip_characterization_create was passed null pointer to characterization->vpd or no points");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_CHARACTERIZATION_ARGUMENT_ERROR);
- break;
- }
- else if (rc) {
- FAPI_ERR("**** ERROR : chip_characterization_create returned error rc = %d", rc );
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_CHARACTERIZATION_ERROR);
- break;
- }
+ // calculate pstate frequency step in Khz
+ frequency_step_khz = (attr.attr_freq_proc_refclock *
+ 1000)/attr.attr_proc_dpll_divider;
+
+ // --------------------------------
+ // check chip ec feature attributes
+ // --------------------------------
+ if (attr.attr_proc_ec_core_hang_pulse_bug)
+ {
+ FAPI_INF("ATTR_PROC_EC_CORE_HANG_PULSE_BUG is set so disable iVRMs - setting PSTATE_NO_INSTALL_LPSA");
+ (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options)
+ |
+ PSTATE_NO_INSTALL_LPSA);
+ poundm_valid = 0;
+ lpst_valid = 0;
+ }
- // ------------------------------
- // Create the Global Pstate table
- // ------------------------------
- FAPI_IMP("Creating Global Pstate Table");
-
- rc = gpst_create(&((*io_pss).gpst),
- characterization,
- PSTATE_STEPSIZE,
- EVRM_DELAY_NS);
-
- FAPI_INF("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_INF("GPST pmin = %d entries = %u", (*io_pss).gpst.pmin, (*io_pss).gpst.entries);
- FAPI_INF("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);
-
- // check for error
- int & GPST_RETURN_CODE = rc;
- if (rc == -GPST_INVALID_OBJECT) {
- FAPI_ERR("**** ERROR : gpst_create was passed null pointer to gpst, characterization, or characterization->ops or characterization->points = 0");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_OBJECT_ERROR);
- break;
- }
- else if (rc == -GPST_INVALID_ARGUMENT) {
- int32_t & OPS_PMIN = s132a_characterization.ops[0].pstate;
- int32_t & OPS_PMAX = s132a_characterization.ops[s132a_characterization.points - 1].pstate;
- FAPI_ERR("**** ERROR : gpst_create was passed bad argument and resulted in PSTATE limits error or operating point ordering error");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ARGUMENT_ERROR);
- break;
- }
- else if (rc == -GPST_INVALID_ENTRY) {
- FAPI_ERR("**** ERROR : gpst_entry_create was passed a voltage that was out of limits of vrm11 vid code or ivid vide code");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ENTRY_ERROR);
- break;
- }
- else if (rc) {
- FAPI_ERR("**** ERROR : gpst_create returned error rc = %d", rc );
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ERROR);
- break;
- }
+ if (! attr.attr_chip_ec_feature_resonant_clk_valid)
+ {
+ FAPI_INF("ATTR_CHIP_EC_FEATURE_RESONANT_CLK_VALID is not set so disable resonant clocking - setting PSTATE_NO_INSTALL_RESCLK");
+ (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options)
+ |
+ PSTATE_NO_INSTALL_RESCLK );
+ }
- // -----------------------------
- // Boost the Global Pstate table
- // -----------------------------
- FAPI_IMP("Boost Global Pstate Table per CPM Boost Attribute");
-
- l_rc = proc_boost_gpst (io_pss, attr.attr_cpm_turbo_boost_percent);
- if (l_rc) break;
-
- // --------------------------------------------------------------------
- // Setup psafe_pstate via attr_pm_safe_frequency (added per SW260812)
- // --------------------------------------------------------------------
- FAPI_INF("Setup psafe_pstate via attr_pm_safe_frequency");
-
- l_rc = proc_upd_psafe_ps (io_pss, &attr);
- if (l_rc) break;
-
- // --------------------------------------------------------------------
- // Setup pmin_clip via attr_freq_core_floor (added per SW260911)
- // --------------------------------------------------------------------
- FAPI_INF("Setup pmin_clip via attr_freq_core_floor");
-
- l_rc = proc_upd_floor_ps (io_pss, &attr);
- if (l_rc) break;
-
- // -----------------------------
- // Create the Local Pstate table
- // -----------------------------
- uint8_t vid_incr_gt7_nonreg = 0;
-
- if (! attr.attr_proc_ec_core_hang_pulse_bug) {
- FAPI_IMP("Creating Local Pstate Table");
-
- rc = lpst_create( &((*io_pss).gpst), &((*io_pss).lpsa), DEAD_ZONE_5MV, volt_int_vdd_bias, volt_int_vcs_bias, &vid_incr_gt7_nonreg);
-
- int & LPST_RETURN_CODE = rc;
- if (rc == -LPST_INVALID_OBJECT) {
- FAPI_ERR("**** ERROR : lpst_create was passed null pointer to gpst or lpsa");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_OBJECT_ERROR);
- break;
- }
- else if (rc == -IVID_INVALID_VOLTAGE) {
- FAPI_ERR("**** ERROR : lpst_create attempted to convert an invalid voltage value to ivid format (GT 1.39375V or LT 0.6V");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_IVID_ERROR);
- break;
- }
- else if (rc == -LPST_INCR_CLIP_ERROR) {
- FAPI_ERR("**** ERROR : lpst_create encountered a vid increment > 7 in regulation");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_VID_INCR_CLIP_INREG_ERROR);
- break;
- }
- else if (rc == -LPST_GPST_WARNING) {
- FAPI_IMP("No Local Pstate Generated - Global Pstate Table is completely within Deadzone - set PSTATE_NO_INSTALL_LPSA" );
-
- // indicate no LPST installed in PSS
- (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) |
- PSTATE_NO_INSTALL_LPSA);
- lpst_valid = 0;
- }
- else if (rc) {
- FAPI_ERR("**** ERROR : lpst_create returned error rc = %d", rc );
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_ERROR);
- break;
- }
-
- // display warning message if this condition occurs
- if (vid_incr_gt7_nonreg) {
- FAPI_IMP("Warning : vid increment field was > 7 in non-regulation - clipped to 7 in lpst");
- }
+ // ----------------
+ // get #V & #M data
+ // ----------------
+ FAPI_IMP("Getting #V & #M Data");
+
+ // clear array
+ memset(attr_mvpd_voltage_control, 0, sizeof(attr_mvpd_voltage_control));
+ memset(&ivrm_mvpd, 0, sizeof(ivrm_mvpd));
+
+ l_rc = proc_get_mvpd_data( i_target,
+ &attr,
+ attr_mvpd_voltage_control,
+ &valid_pdv_points,
+ &ivrm_mvpd,
+ &present_chiplets,
+ &functional_chiplets,
+ &poundm_valid,
+ &poundm_ver);
+ if (l_rc)
+ {
+ break;
+ }
+ else if (!present_chiplets)
+ {
+ FAPI_ERR("**** ERROR : There are no cores present");
+ const uint8_t &PRESENT_CHIPLETS = present_chiplets;
+ const Target &CHIP_TARGET = i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_NO_CORES_PRESENT_ERROR);
+ break;
+ }
- }
+ if (!functional_chiplets || !poundm_valid)
+ {
+
+ if (!functional_chiplets)
+ {
+ FAPI_IMP("No FUNCTIONAL chiplets found - set PSTATE_NO_INSTALL_LPSA");
+ }
+ else
+ {
+ FAPI_IMP("Invalid #M found - set PSTATE_NO_INSTALL_LPSA");
+ }
+
+ // indicate no LPST installed in PSS
+ (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options)
+ |
+ PSTATE_NO_INSTALL_LPSA);
+ }
- // -----------------------
- // Create VDS & VIN tables
- // -----------------------
- FAPI_IMP("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[i].Coef,
- &(ivrm_mvpd.data.ex[i]) );
-
- write_HWtab_bin(&ivrm_parms,
- ivrm_mvpd.data.ex[i].Coef,
- io_pss);
- break;
- }
- }
+ // ---------------------------------------------
+ // process external and internal bias attributes
+ // ---------------------------------------------
+ FAPI_IMP("Apply Biasing to #V");
- // ---------------------------------------
- // Update CPM Range info in Superstructure
- // ---------------------------------------
- FAPI_IMP("Creating CPM Range Table");
+ l_rc = proc_get_extint_bias(attr_mvpd_voltage_control,
+ &attr,
+ &volt_int_vdd_bias,
+ &volt_int_vcs_bias);
- l_rc = proc_upd_cpmrange (io_pss, &attr);
- if (l_rc) break;
+ if (l_rc)
+ {
+ break;
+ }
- // -----------------------------------------------
- // Update Resonant Clocking info in Superstructure
- // -----------------------------------------------
- if (attr.attr_chip_ec_feature_resonant_clk_valid) {
- FAPI_IMP("Creating Resonant Clocking Band Table");
- l_rc = proc_res_clock (io_pss, &attr);
- if (l_rc) break;
- }
+ // -----------------------------------------------
+ // populate VpdOperatingPoint with biased MVPD attributes
+ // -----------------------------------------------
+ VpdOperatingPoint s132a_vpd[S132A_POINTS];
+
+ rc = load_mvpd_operating_point (attr_mvpd_voltage_control,
+ s132a_vpd);
+
+ // -------------------------------------------------------------------
+ // Create s132a_points and filled in by chip_characterization_create()
+ // -------------------------------------------------------------------
+ OperatingPoint s132a_points[S132A_POINTS];
+
+ // -------------------------------------------------
+ // populate OperatingPointParameters with attributes
+ // -------------------------------------------------
+
+ OperatingPointParameters s132a_parms;
+ s132a_parms.pstate0_frequency_khz = ((s132a_vpd[valid_pdv_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;
+ // SW267784
+ s132a_parms.vdd_voffset_uv = attr.attr_proc_vrm_voffset_vdd;
+ s132a_parms.vcs_voffset_uv = attr.attr_proc_vrm_voffset_vcs;
+
+
+ // --------------------------------------
+ // Create Chip characterization structure
+ // --------------------------------------
+
+ ChipCharacterization s132a_characterization;
+ s132a_characterization.vpd = s132a_vpd;
+ s132a_characterization.ops = s132a_points;
+ s132a_characterization.parameters = &s132a_parms;
+ s132a_characterization.points = valid_pdv_points;
+ s132a_characterization.max_cores = present_chiplets;
+
+ // ---------------------------
+ // Finish the characterization
+ // ---------------------------
+ characterization = &s132a_characterization;
+
+ rc = chip_characterization_create(characterization,
+ characterization->vpd,
+ characterization->ops,
+ characterization->parameters,
+ characterization->points);
+
+ // check for error
+ int & CHAR_RETURN_CODE = rc;
+
+ if (rc == -GPST_INVALID_OBJECT)
+ {
+ FAPI_ERR("**** ERROR : chip_characterization_create was passed null pointer to characterization or characterization->parameters");
+ FAPI_SET_HWP_ERROR(l_rc,
+ RC_PROCPM_PSTATE_DATABLOCK_CHARACTERIZATION_OBJECT_ERROR);
+ break;
+ }
+ else if (rc == -GPST_INVALID_ARGUMENT)
+ {
+ uint32_t & POINTS = characterization->points;
+ FAPI_ERR("**** ERROR : chip_characterization_create was passed null pointer to characterization->vpd or no points");
+ FAPI_SET_HWP_ERROR(l_rc,
+ RC_PROCPM_PSTATE_DATABLOCK_CHARACTERIZATION_ARGUMENT_ERROR);
+ break;
+ }
+ else if (rc)
+ {
+ FAPI_ERR("**** ERROR : chip_characterization_create returned error rc = %d",
+ rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_CHARACTERIZATION_ERROR);
+ break;
+ }
- // ------------------------
- // Force optional overrides
- // ------------------------
- FAPI_INF(" Set PSTATE_FORCE_INITIAL_PMIN in GPST control options");
- (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) | PSTATE_FORCE_INITIAL_PMIN);
- FAPI_INF(" GPST control options mask is now: [%x].", (*io_pss).gpst.options.options);
-
- // -------------------
- // Attributes to write
- // -------------------
- // uint32_t ATTR_PM_PSTATE0_FREQUENCY // Binary in Khz
- FAPI_IMP("Writing Attribute Values");
-
- // check if IVRMs should be enabled
- if (poundm_valid && lpst_valid && // IVRMs should be enabled based on VPD findings
- attr.attr_pm_system_ivrms_enabled && // Allowed by system
- (attr.attr_pm_system_ivrm_vpd_min_level != 0) && // Attribute has a valid value
- (attr.attr_pm_system_ivrm_vpd_min_level >= poundm_ver) && // Hardware characterized
- attr.attr_chip_ec_feature_ivrm_winkle_bug) // Hardware has logic fixes
- {
- attr_pm_ivrms_enabled_wr = 1;
- }
- else
- {
- attr_pm_ivrms_enabled_wr = 0;
- FAPI_INF(" ATTR_PM_IVRMS_ENABLED will be set to 0 - set PSTATE_NO_INSTALL_LPSA");
- // indicate no LPST installed in PSS
- (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) |
- PSTATE_NO_INSTALL_LPSA);
- }
+ // Load the WOF information as this influences the generation
+ // of the Pstate tables
+ if (attr.attr_wof_enabled)
+ {
+ // -----------------------------------------------
+ // populate WOF structure with the biased VPD information
+ // -----------------------------------------------
+ l_rc = load_mvpd_operating_point (attr_mvpd_voltage_control,
+ io_pss->wof.operating_points);
+ if (l_rc)
+ {
+ // No errors to handle at this time
+ }
+
+ // ----------------
+ // get IQ (IDDQ) data and place into the Pstate SuperStructure
+ // ----------------
+ FAPI_IMP("Getting IQ (IDDQ) Data");
+
+ l_rc = proc_get_mvpd_iddq(i_target, io_pss);
+ if (l_rc)
+ {
+ // @todo add FFDC
+
+ // Disable WOF and keep going
+ FAPI_INF("**** WARNING: While WOF was enabled via attributes, IDDQ information "
+ "for the present part could not be obtained (either due to access error "
+ "or is not present in the VPD. WOF is being DISABLED but Pstate table "
+ "generation is continuing");
+ attr.attr_wof_enabled = 0;
+
+ }
+ else
+ {
+ // -----------------------------------------------
+ // populate WOF structure with the biased VPD information
+ // -----------------------------------------------
+ rc = load_wof_attributes (io_pss, &attr);
+ if (l_rc)
+ {
+ // No errors to handle at this time
+ }
+ }
+ }
- // write ATTR_PM_IVRMS_ENABLED
- SETATTR(l_rc, ATTR_PM_IVRMS_ENABLED, "ATTR_PM_IVRMS_ENABLED", &i_target, attr_pm_ivrms_enabled_wr);
- // Read back attribute to see if overridden
- GETATTR (l_rc, ATTR_PM_IVRMS_ENABLED, "ATTR_PM_IVRMS_ENABLED", &i_target, attr_pm_ivrms_enabled_rd);
+ // ------------------------------
+ // Create the Global Pstate table
+ // ------------------------------
+ FAPI_IMP("Creating Global Pstate Table");
+
+ rc = gpst_create(&((*io_pss).gpst),
+ characterization,
+ &((*io_pss).wof),
+ PSTATE_STEPSIZE,
+ EVRM_DELAY_NS);
+
+ FAPI_INF("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_INF("GPST pmin = %d entries = %u", (*io_pss).gpst.pmin,
+ (*io_pss).gpst.entries);
+ FAPI_INF("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);
+
+ // check for error
+ int & GPST_RETURN_CODE = rc;
+
+ if (rc == -GPST_INVALID_OBJECT)
+ {
+ FAPI_ERR("**** ERROR : gpst_create was passed null pointer to gpst, characterization, or characterization->ops or characterization->points = 0");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_OBJECT_ERROR);
+ break;
+ }
+ else if (rc == -GPST_INVALID_ARGUMENT)
+ {
+ int32_t & OPS_PMIN = s132a_characterization.ops[0].pstate;
+ int32_t & OPS_PMAX =
+ s132a_characterization.ops[s132a_characterization.points - 1].pstate;
+ FAPI_ERR("**** ERROR : gpst_create was passed bad argument and resulted in PSTATE limits error or operating point ordering error");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ARGUMENT_ERROR);
+ break;
+ }
+ else if (rc == -GPST_INVALID_ENTRY)
+ {
+ FAPI_ERR("**** ERROR : gpst_entry_create was passed a voltage that was out of limits of vrm11 vid code or ivid vide code");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ENTRY_ERROR);
+ break;
+ }
+ else if (rc)
+ {
+ FAPI_ERR("**** ERROR : gpst_create returned error rc = %d", rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ERROR);
+ break;
+ }
- if (attr_pm_ivrms_enabled_rd && !attr_pm_ivrms_enabled_wr) {
- FAPI_INF("WARNING : Attribute ATTR_PM_IVRMS_ENABLED was overridden to 1, but #V or #M data is not valid for IVRMs");
- }
- else if (!attr_pm_ivrms_enabled_rd && attr_pm_ivrms_enabled_wr) {
- FAPI_INF("WARNING : ATTR_PM_IVRMS_ENABLED was overriden to 0, but #V or #M data are valid - set PSTATE_NO_INSTALL_LPSA");
- // indicate no LPST installed in PSS
- (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) |
- PSTATE_NO_INSTALL_LPSA);
- }
+ // -----------------------------
+ // Boost the Global Pstate table
+ // -----------------------------
+ FAPI_IMP("Boost Global Pstate Table per CPM Boost Attribute");
- } while(0);
+ l_rc = proc_boost_gpst (io_pss, attr.attr_cpm_turbo_boost_percent);
+
+ if (l_rc)
+ {
+ break;
+ }
+
+ // --------------------------------------------------------------------
+ // Setup psafe_pstate via attr_pm_safe_frequency (added per SW260812)
+ // --------------------------------------------------------------------
+ FAPI_INF("Setup psafe_pstate via attr_pm_safe_frequency");
+
+ l_rc = proc_upd_psafe_ps (io_pss, &attr);
+
+ if (l_rc)
+ {
+ break;
+ }
+
+ // --------------------------------------------------------------------
+ // Setup pmin_clip via attr_freq_core_floor (added per SW260911)
+ // --------------------------------------------------------------------
+ FAPI_INF("Setup pmin_clip via attr_freq_core_floor");
+
+ l_rc = proc_upd_floor_ps (io_pss, &attr);
+
+ if (l_rc)
+ {
+ break;
+ }
+
+ // -----------------------------
+ // Create the Local Pstate table
+ // -----------------------------
+ uint8_t vid_incr_gt7_nonreg = 0;
+
+ if (! attr.attr_proc_ec_core_hang_pulse_bug)
+ {
+ FAPI_IMP("Creating Local Pstate Table");
+
+ rc = lpst_create( &((*io_pss).gpst), &((*io_pss).lpsa), DEAD_ZONE_5MV,
+ volt_int_vdd_bias, volt_int_vcs_bias, &vid_incr_gt7_nonreg);
+
+ int & LPST_RETURN_CODE = rc;
+
+ if (rc == -LPST_INVALID_OBJECT)
+ {
+ FAPI_ERR("**** ERROR : lpst_create was passed null pointer to gpst or lpsa");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_OBJECT_ERROR);
+ break;
+ }
+ else if (rc == -IVID_INVALID_VOLTAGE)
+ {
+ FAPI_ERR("**** ERROR : lpst_create attempted to convert an invalid voltage value to ivid format (GT 1.39375V or LT 0.6V");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_IVID_ERROR);
+ break;
+ }
+ else if (rc == -LPST_INCR_CLIP_ERROR)
+ {
+ FAPI_ERR("**** ERROR : lpst_create encountered a vid increment > 7 in regulation");
+ FAPI_SET_HWP_ERROR(l_rc,
+ RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_VID_INCR_CLIP_INREG_ERROR);
+ break;
+ }
+ else if (rc == -LPST_GPST_WARNING)
+ {
+ FAPI_IMP("No Local Pstate Generated - Global Pstate Table is completely within Deadzone - set PSTATE_NO_INSTALL_LPSA" );
+
+ // indicate no LPST installed in PSS
+ (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options)
+ |
+ PSTATE_NO_INSTALL_LPSA);
+ lpst_valid = 0;
+ }
+ else if (rc)
+ {
+ FAPI_ERR("**** ERROR : lpst_create returned error rc = %d", rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_LPST_CREATE_ERROR);
+ break;
+ }
+
+ // display warning message if this condition occurs
+ if (vid_incr_gt7_nonreg)
+ {
+ FAPI_IMP("Warning : vid increment field was > 7 in non-regulation - clipped to 7 in lpst");
+ }
+
+ }
+
+ // -----------------------
+ // Create VDS & VIN tables
+ // -----------------------
+ FAPI_IMP("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[i].Coef,
+ &(ivrm_mvpd.data.ex[i]) );
+
+ write_HWtab_bin(&ivrm_parms,
+ ivrm_mvpd.data.ex[i].Coef,
+ io_pss);
+ break;
+ }
+ }
+
+ // ---------------------------------------
+ // Update CPM Range info in Superstructure
+ // ---------------------------------------
+ FAPI_IMP("Creating CPM Range Table");
+
+ l_rc = proc_upd_cpmrange (io_pss, &attr);
+
+ if (l_rc)
+ {
+ break;
+ }
- return l_rc;
-} // end p8_build_pstate_datablock
+ // -----------------------------------------------
+ // Update Resonant Clocking info in Superstructure
+ // -----------------------------------------------
+ if (attr.attr_chip_ec_feature_resonant_clk_valid)
+ {
+ FAPI_IMP("Creating Resonant Clocking Band Table");
+ l_rc = proc_res_clock (io_pss, &attr);
+
+ if (l_rc)
+ {
+ break;
+ }
+ }
+
+ // ------------------------
+ // Force optional overrides
+ // ------------------------
+ FAPI_INF(" Set PSTATE_FORCE_INITIAL_PMIN in GPST control options");
+ (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options)
+ | PSTATE_FORCE_INITIAL_PMIN);
+ FAPI_INF(" GPST control options mask is now: [%x].",
+ (*io_pss).gpst.options.options);
+
+ // -------------------
+ // Attributes to write
+ // -------------------
+ // uint32_t ATTR_PM_PSTATE0_FREQUENCY // Binary in Khz
+ FAPI_IMP("Writing Attribute Values");
+
+ // check if IVRMs should be enabled
+ if (poundm_valid && lpst_valid
+ && // IVRMs should be enabled based on VPD findings
+ attr.attr_pm_system_ivrms_enabled && // Allowed by system
+ (attr.attr_pm_system_ivrm_vpd_min_level != 0)
+ && // Attribute has a valid value
+ (attr.attr_pm_system_ivrm_vpd_min_level >= poundm_ver)
+ && // Hardware characterized
+ attr.attr_chip_ec_feature_ivrm_winkle_bug) // Hardware has logic fixes
+ {
+ attr_pm_ivrms_enabled_wr = 1;
+ }
+ else
+ {
+ attr_pm_ivrms_enabled_wr = 0;
+ FAPI_INF(" ATTR_PM_IVRMS_ENABLED will be set to 0 - set PSTATE_NO_INSTALL_LPSA");
+ // indicate no LPST installed in PSS
+ (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options)
+ |
+ PSTATE_NO_INSTALL_LPSA);
+ }
+
+ // write ATTR_PM_IVRMS_ENABLED
+ SETATTR(l_rc, ATTR_PM_IVRMS_ENABLED, "ATTR_PM_IVRMS_ENABLED", &i_target,
+ attr_pm_ivrms_enabled_wr);
+
+ // Read back attribute to see if overridden
+ GETATTR (l_rc, ATTR_PM_IVRMS_ENABLED, "ATTR_PM_IVRMS_ENABLED", &i_target,
+ attr_pm_ivrms_enabled_rd);
+
+ if (attr_pm_ivrms_enabled_rd && !attr_pm_ivrms_enabled_wr)
+ {
+ FAPI_INF("WARNING : Attribute ATTR_PM_IVRMS_ENABLED was overridden to 1, but #V or #M data is not valid for IVRMs");
+ }
+ else if (!attr_pm_ivrms_enabled_rd && attr_pm_ivrms_enabled_wr)
+ {
+ FAPI_INF("WARNING : ATTR_PM_IVRMS_ENABLED was overriden to 0, but #V or #M data are valid - set PSTATE_NO_INSTALL_LPSA");
+ // indicate no LPST installed in PSS
+ (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options)
+ |
+ PSTATE_NO_INSTALL_LPSA);
+ }
+
+ }
+ while(0);
+
+ return l_rc;
+ } // end p8_build_pstate_datablock
/// -----------------------------------------------------------------------
/// \brief Get needed attributes
@@ -511,46 +692,49 @@ p8_build_pstate_datablock(const Target& i_target,
/// \param[inout] attr => pointer to attribute list structure
/// -----------------------------------------------------------------------
-ReturnCode proc_get_attributes(const Target& i_target,
- AttributeList *attr)
-{
- ReturnCode l_rc;
- uint8_t i = 0;
-
- do
- {
- // --------------------------
- // attributes not yet defined
- // --------------------------
- attr->attr_dpll_bias = 0;
- attr->attr_undervolting = 0;
-
- // ---------------------------------------------------------------
- // set ATTR_PROC_DPLL_DIVIDER
- // ---------------------------------------------------------------
- attr->attr_proc_dpll_divider = 4;
- FAPI_INF("ATTR_PROC_DPLL_DIVIDER - set to %x", attr->attr_proc_dpll_divider);
-
- l_rc = FAPI_ATTR_SET(ATTR_PROC_DPLL_DIVIDER, &i_target, attr->attr_proc_dpll_divider );
- if (l_rc ) {
- FAPI_ERR("fapiSetAttribute of ATTR_PROC_DPLL_DIVIDER failed");
- break;
- }
+ ReturnCode proc_get_attributes(const Target& i_target,
+ AttributeList *attr)
+ {
+ ReturnCode l_rc;
+ uint8_t i = 0;
+
+ do
+ {
+ // --------------------------
+ // attributes not yet defined
+ // --------------------------
+ attr->attr_dpll_bias = 0;
+ attr->attr_undervolting = 0;
+
+ // ---------------------------------------------------------------
+ // set ATTR_PROC_DPLL_DIVIDER
+ // ---------------------------------------------------------------
+ attr->attr_proc_dpll_divider = 4;
+ FAPI_INF("ATTR_PROC_DPLL_DIVIDER - set to %x", attr->attr_proc_dpll_divider);
+
+ l_rc = FAPI_ATTR_SET(ATTR_PROC_DPLL_DIVIDER, &i_target,
+ attr->attr_proc_dpll_divider );
+
+ if (l_rc )
+ {
+ FAPI_ERR("fapiSetAttribute of ATTR_PROC_DPLL_DIVIDER failed");
+ break;
+ }
- // ----------------------------
- // attributes currently defined
- // ----------------------------
- #define DATABLOCK_GET_ATTR(attr_name, target, attr_assign) \
+ // ----------------------------
+ // 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("%-60s = 0x%08x %u", #attr_name, attr->attr_assign, attr->attr_assign);
-
- // This macro is in place to to deal with the movement of attribute placement
- // from SYSTEM to PROC_CHIP per SW298278 hhile allowing for this procedure
- // to still operate in system that continue store attributes at the SYSTEM level.
- // This is done by trying the passed target first; if it doesn't succeed, the
- // SYSTEM level is attempted. Failure of both will cause a break.
- #define DATABLOCK_GET_ATTR_CHECK_PROC(attr_name, target, attr_assign) \
+
+ // This macro is in place to to deal with the movement of attribute placement
+ // from SYSTEM to PROC_CHIP per SW298278 while allowing for this procedure
+ // to still operate in system that continue store attributes at the SYSTEM level.
+ // This is done by trying the passed target first; if it doesn't succeed, the
+ // SYSTEM level is attempted. Failure of both will cause a break.
+#define DATABLOCK_GET_ATTR_CHECK_PROC(attr_name, target, attr_assign) \
l_rc = FAPI_ATTR_GET(attr_name, target, attr->attr_assign); \
if (!l_rc) { \
FAPI_INF("%-60s = 0x%08x %u from PROC_CHIP target", #attr_name, attr->attr_assign, attr->attr_assign); \
@@ -566,420 +750,859 @@ ReturnCode proc_get_attributes(const Target& i_target,
break; \
} \
}
+
+ 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);
+ 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_FREQ_CORE_FLOOR,
+ NULL, attr_freq_core_floor);
+ 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_CHECK_PROC(ATTR_PROC_R_LOADLINE_VDD,
+ &i_target, attr_proc_r_loadline_vdd);
+ DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_R_LOADLINE_VCS,
+ &i_target, attr_proc_r_loadline_vcs);
+ DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_R_DISTLOSS_VDD,
+ &i_target, attr_proc_r_distloss_vdd);
+ DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_R_DISTLOSS_VCS,
+ &i_target, attr_proc_r_distloss_vcs);
+ DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_VRM_VOFFSET_VDD,
+ &i_target, attr_proc_vrm_voffset_vdd);
+ DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_VRM_VOFFSET_VCS,
+ &i_target, 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;
+ }
- 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);
- 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_FREQ_CORE_FLOOR, NULL, attr_freq_core_floor);
- 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_CHECK_PROC(ATTR_PROC_R_LOADLINE_VDD, &i_target, attr_proc_r_loadline_vdd);
- DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_R_LOADLINE_VCS, &i_target, attr_proc_r_loadline_vcs);
- DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_R_DISTLOSS_VDD, &i_target, attr_proc_r_distloss_vdd);
- DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_R_DISTLOSS_VCS, &i_target, attr_proc_r_distloss_vcs);
- DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_VRM_VOFFSET_VDD, &i_target, attr_proc_vrm_voffset_vdd);
- DATABLOCK_GET_ATTR_CHECK_PROC(ATTR_PROC_VRM_VOFFSET_VCS, &i_target, 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]);
- }
-
- // Read chip ec feature
- DATABLOCK_GET_ATTR(ATTR_CHIP_EC_FEATURE_RESONANT_CLK_VALID, &i_target, attr_chip_ec_feature_resonant_clk_valid);
- DATABLOCK_GET_ATTR(ATTR_PROC_EC_CORE_HANG_PULSE_BUG , &i_target, attr_proc_ec_core_hang_pulse_bug);
- DATABLOCK_GET_ATTR(ATTR_CHIP_EC_FEATURE_IVRM_WINKLE_BUG , &i_target, attr_chip_ec_feature_ivrm_winkle_bug);
+ 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]);
+ }
- // Read IVRM attributes
- DATABLOCK_GET_ATTR(ATTR_PM_SYSTEM_IVRMS_ENABLED , NULL, attr_pm_system_ivrms_enabled);
- DATABLOCK_GET_ATTR(ATTR_PM_SYSTEM_IVRM_VPD_MIN_LEVEL , NULL, attr_pm_system_ivrm_vpd_min_level);
+ // Read chip ec feature
+ DATABLOCK_GET_ATTR(ATTR_CHIP_EC_FEATURE_RESONANT_CLK_VALID, &i_target,
+ attr_chip_ec_feature_resonant_clk_valid);
+ DATABLOCK_GET_ATTR(ATTR_PROC_EC_CORE_HANG_PULSE_BUG , &i_target,
+ attr_proc_ec_core_hang_pulse_bug);
+ DATABLOCK_GET_ATTR(ATTR_CHIP_EC_FEATURE_IVRM_WINKLE_BUG , &i_target,
+ attr_chip_ec_feature_ivrm_winkle_bug);
+
+ // Read IVRM attributes
+ DATABLOCK_GET_ATTR(ATTR_PM_SYSTEM_IVRMS_ENABLED , NULL,
+ attr_pm_system_ivrms_enabled);
+ DATABLOCK_GET_ATTR(ATTR_PM_SYSTEM_IVRM_VPD_MIN_LEVEL , NULL,
+ attr_pm_system_ivrm_vpd_min_level);
+
+ // Read WOF attributes
+ DATABLOCK_GET_ATTR(ATTR_WOF_ENABLED , NULL,
+ attr_wof_enabled);
+ DATABLOCK_GET_ATTR(ATTR_TDP_RDP_CURRENT_FACTOR , &i_target,
+ attr_tdp_rdp_current_factor);
+
+ // --------------------------------------------------------------
+ // do basic attribute value checking and generate error if needed
+ // --------------------------------------------------------------
+
+ //check that dpll_divider is not 0
+ if (attr->attr_proc_dpll_divider == 0)
+ {
+ FAPI_ERR("**** ERROR : Attribute ATTR_PROC_DPLL_DIVIDER = 0");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_ATTR_DPLL_DIV_ERROR);
+ break;
+ }
- // --------------------------------------------------------------
- // do basic attribute value checking and generate error if needed
- // --------------------------------------------------------------
+ // ----------------------------------------------------
+ // 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;
+ }
- //check that dpll_divider is not 0
- if (attr->attr_proc_dpll_divider == 0) {
- FAPI_ERR("**** ERROR : Attribute ATTR_PROC_DPLL_DIVIDER = 0");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_ATTR_DPLL_DIV_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_VDD_VOLTAGE_BIAS_ERROR);
+ break;
+ }
- // ----------------------------------------------------
- // 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_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_VCS_VOLTAGE_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_VDD_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_VDD_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_VCS_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_VCS_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_VDD_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_INF("Double Biasing enabled on external and internal VDD");
+ }
- 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_VCS_VOLTAGE_BIAS_ERROR);
- break;
- }
+ 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_INF("Double Biasing enabled on external and internal VCS");
+ }
- // 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_INF("Double Biasing enabled on external and internal VDD");
- }
+ // check resonant clocking attribute values relative to each other
+ if (attr->attr_chip_ec_feature_resonant_clk_valid)
+ {
+
+ if ( (attr->attr_pm_resonant_clock_low_band_lower_frequency >
+ attr->attr_pm_resonant_clock_low_band_upper_frequency) ||
+ (attr->attr_pm_resonant_clock_low_band_upper_frequency >
+ attr->attr_pm_resonant_clock_high_band_lower_frequency) ||
+ (attr->attr_pm_resonant_clock_high_band_lower_frequency >
+ attr->attr_pm_resonant_clock_high_band_upper_frequency) )
+ {
+ const uint32_t &PM_RES_CLOCK_LOW_BAND_LOWER_FREQ =
+ attr->attr_pm_resonant_clock_low_band_lower_frequency;
+ const uint32_t &PM_RES_CLOCK_LOW_BAND_UPPER_FREQ =
+ attr->attr_pm_resonant_clock_low_band_upper_frequency;
+ const uint32_t &PM_RES_CLOCK_HIGH_BAND_LOWER_FREQ =
+ attr->attr_pm_resonant_clock_high_band_lower_frequency;
+ const uint32_t &PM_RES_CLOCK_HIGH_BAND_UPPER_FREQ =
+ attr->attr_pm_resonant_clock_high_band_upper_frequency;
+ FAPI_ERR("**** ERROR : Resonant clocking band attribute values are not in ascending order from low to high");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_RESCLK_BAND_ERROR);
+ break;
+ }
+ }
- 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_INF("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_INF("Attribute value was 0 - setting to default value ATTR_FREQ_PROC_REFCLOCK = 133");
+ }
- // check resonant clocking attribute values relative to each other
- if (attr->attr_chip_ec_feature_resonant_clk_valid) {
-
- if ( (attr->attr_pm_resonant_clock_low_band_lower_frequency > attr->attr_pm_resonant_clock_low_band_upper_frequency) ||
- (attr->attr_pm_resonant_clock_low_band_upper_frequency > attr->attr_pm_resonant_clock_high_band_lower_frequency) ||
- (attr->attr_pm_resonant_clock_high_band_lower_frequency > attr->attr_pm_resonant_clock_high_band_upper_frequency) ) {
- const uint32_t &PM_RES_CLOCK_LOW_BAND_LOWER_FREQ = attr->attr_pm_resonant_clock_low_band_lower_frequency;
- const uint32_t &PM_RES_CLOCK_LOW_BAND_UPPER_FREQ = attr->attr_pm_resonant_clock_low_band_upper_frequency;
- const uint32_t &PM_RES_CLOCK_HIGH_BAND_LOWER_FREQ = attr->attr_pm_resonant_clock_high_band_lower_frequency;
- const uint32_t &PM_RES_CLOCK_HIGH_BAND_UPPER_FREQ = attr->attr_pm_resonant_clock_high_band_upper_frequency;
- FAPI_ERR("**** ERROR : Resonant clocking band attribute values are not in ascending order from low to high");
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_RESCLK_BAND_ERROR);
- break;
- }
- }
+ if (attr->attr_proc_dpll_divider == 0)
+ {
+ attr->attr_proc_dpll_divider = 4;
+ FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_DPLL_DIVIDER = 4");
+ }
- // ------------------------------------------------------
- // 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_INF("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_INF("Attribute value was 0 - setting to default value ATTR_PM_SAFE_FREQUENCY = ATTR_BOOT_FREQ_MHZ");
+ }
- if (attr->attr_proc_dpll_divider == 0) {
- attr->attr_proc_dpll_divider = 4;
- FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_DPLL_DIVIDER = 4");
- }
+ if (attr->attr_proc_r_loadline_vdd == 0)
+ {
+ attr->attr_proc_r_loadline_vdd = 570;
+ FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_R_LOADLINE_VDD = 570");
+ }
- if (attr->attr_pm_safe_frequency == 0) {
- attr->attr_pm_safe_frequency = attr->attr_boot_freq_mhz;
- FAPI_INF("Attribute value was 0 - setting to default value ATTR_PM_SAFE_FREQUENCY = ATTR_BOOT_FREQ_MHZ");
- }
+ if (attr->attr_proc_r_loadline_vcs == 0)
+ {
+ attr->attr_proc_r_loadline_vcs = 570;
+ FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_R_LOADLINE_VCS = 570");
+ }
- if (attr->attr_proc_r_loadline_vdd == 0) {
- attr->attr_proc_r_loadline_vdd = 570;
- FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_R_LOADLINE_VDD = 570");
- }
+ if (attr->attr_proc_r_distloss_vdd == 0)
+ {
+ attr->attr_proc_r_distloss_vdd = 390;
+ FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_R_DISTLOSS_VDD = 390");
+ }
- if (attr->attr_proc_r_loadline_vcs == 0) {
- attr->attr_proc_r_loadline_vcs = 570;
- FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_R_LOADLINE_VCS = 570");
- }
+ if (attr->attr_proc_r_distloss_vcs == 0)
+ {
+ attr->attr_proc_r_distloss_vcs = 3500;
+ FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_R_DISTLOSS_VCS = 3500");
+ }
- if (attr->attr_proc_r_distloss_vdd == 0) {
- attr->attr_proc_r_distloss_vdd = 390;
- FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_R_DISTLOSS_VDD = 390");
- }
+ }
+ while(0);
- if (attr->attr_proc_r_distloss_vcs == 0) {
- attr->attr_proc_r_distloss_vcs = 3500;
- FAPI_INF("Attribute value was 0 - setting to default value ATTR_PROC_R_DISTLOSS_VCS = 3500");
+ return l_rc;
}
- } while(0);
-
- 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],
- ivrm_mvpd_t *ivrm_mvpd,
- uint8_t *present_chiplets,
- uint8_t *functional_chiplets,
- uint8_t *poundm_valid,
- uint8_t *poundm_ver)
-{
- ReturnCode l_rc;
- std::vector<fapi::Target> l_exChiplets;
- 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 bucket_id = 0;
- uint16_t cal_data[4];
-
- do
- {
- // initialize
- *present_chiplets = 0;
- *functional_chiplets = 0;
-
- // -----------------------------------------------------------------
- // get list of chiplets and loop over each and get #V data from each
- // -----------------------------------------------------------------
- // check that frequency is the same per chiplet
- // for voltage, get the max for use for the chip
-
- l_rc = fapiGetChildChiplets (i_target, TARGET_TYPE_EX_CHIPLET, l_exChiplets, TARGET_STATE_PRESENT);
- if (l_rc) {
- FAPI_ERR("Error from fapiGetChildChiplets!");
- break;
- }
-
- FAPI_INF("Number of EX chiplets present => %u", l_exChiplets.size());
-
- for (j=0; j < l_exChiplets.size(); j++) {
- *present_chiplets = 1;
- 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) {
- FAPI_ERR("fapiGetAttribute of ATTR_CHIP_UNIT_POS error");
- break;
- }
-
- // set l_record to appropriate lprx record (add core number to lrp0)
- l_record = (uint32_t)fapi::MVPD_RECORD_LRP0 + l_chipNum;
-
- // clear out buffer to known value before calling fapiGetMvpdField
- memset(l_buffer, 0, 512);
-
- // Get Chiplet MVPD data and put in chiplet_mvpd_data using accessor function
- l_rc = fapiGetMvpdField((fapi::MvpdRecord)l_record,
- fapi::MVPD_KEYWORD_PDV,
- i_target,
- l_buffer,
- l_bufferSize);
- if (!l_rc.ok()) {
- FAPI_ERR("**** ERROR : Unexpected error encountered in fapiGetMvpdField");
- break;
- }
-
- // check buffer size
- if (l_bufferSize < PDV_BUFFER_SIZE) {
- FAPI_ERR("**** ERROR : Wrong size buffer returned from fapiGetMvpdField for #V => %d", l_bufferSize );
- const uint32_t &BUFFER_SIZE = l_bufferSize;
- const Target &CHIP_TARGET= i_target;
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDV_BUFFER_SIZE_ERROR);
- break;
- }
-
- // clear array
- memset(chiplet_mvpd_data, 0, sizeof(chiplet_mvpd_data));
-
- // 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) ) ))
-
- // use copy of allocated buffer pointer to increment through buffer
- l_buffer_inc = l_buffer;
-
- bucket_id = *l_buffer_inc;
- l_buffer_inc++;
-
- FAPI_INF("#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_inc);
- FAPI_INF("#V data = 0x%04X %-6d", chiplet_mvpd_data[i][ii], chiplet_mvpd_data[i][ii]);
- // increment to next MVPD value in buffer
- l_buffer_inc+= 2;
- }
- }
-
- // perform data validity checks on this #V data before proceeding to use it
- l_rc = proc_chk_valid_poundv(i_target ,chiplet_mvpd_data, l_chipNum, bucket_id);
- if (l_rc) break;
+ ReturnCode proc_get_mvpd_data(const Target& i_target,
+ AttributeList *i_attr,
+ uint32_t attr_mvpd_data[PV_D][PV_W],
+ uint32_t *valid_pdv_points,
+ ivrm_mvpd_t *ivrm_mvpd,
+ uint8_t *present_chiplets,
+ uint8_t *functional_chiplets,
+ uint8_t *poundm_valid,
+ uint8_t *poundm_ver)
+ {
+ ReturnCode l_rc;
+ std::vector<fapi::Target> l_exChiplets;
+ uint8_t l_functional = 0;
+ uint8_t * l_buffer = reinterpret_cast<uint8_t *>(malloc(PDV_BUFFER_ALLOC) );
+ uint8_t * l_buffer_pdm = reinterpret_cast<uint8_t *>(malloc(PDM_BUFFER_ALLOC) );
+ 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 bucket_id = 0;
+ uint16_t cal_data[POUNDM_MEASUREMENTS_PER_POINT];
+
+
+ do
+ {
+ // initialize
+ *present_chiplets = 0;
+ *functional_chiplets = 0;
+
+ // -----------------------------------------------------------------
+ // get list of chiplets and loop over each and get #V data from each
+ // -----------------------------------------------------------------
+ // check that frequency is the same per chiplet
+ // for voltage, get the max for use for the chip
+
+ l_rc = fapiGetChildChiplets (i_target, TARGET_TYPE_EX_CHIPLET, l_exChiplets,
+ TARGET_STATE_PRESENT);
+
+ if (l_rc)
+ {
+ FAPI_ERR("Error from fapiGetChildChiplets!");
+ break;
+ }
- // on first chiplet put each bucket's data into attr_mvpd_voltage_control
- if (first_chplt) {
+ *present_chiplets = l_exChiplets.size();
+ FAPI_INF("Number of EX chiplets present => %u", *present_chiplets);
+
+ for (j=0; j < l_exChiplets.size(); j++)
+ {
+
+ 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)
+ {
+ FAPI_ERR("fapiGetAttribute of ATTR_CHIP_UNIT_POS error");
+ break;
+ }
+
+ // set l_record to appropriate lprx record (add core number to lrp0)
+ l_record = (uint32_t)fapi::MVPD_RECORD_LRP0 + l_chipNum;
+
+ // clear out buffer to known value before calling fapiGetMvpdField
+ memset(l_buffer, 0, 512);
+
+ // Get Chiplet MVPD data and put in chiplet_mvpd_data using accessor function
+ l_rc = fapiGetMvpdField((fapi::MvpdRecord)l_record,
+ fapi::MVPD_KEYWORD_PDV,
+ i_target,
+ l_buffer,
+ l_bufferSize);
+
+ if (!l_rc.ok())
+ {
+ FAPI_ERR("**** ERROR : Unexpected error encountered in fapiGetMvpdField");
+ break;
+ }
+
+ // check buffer size
+ if (l_bufferSize < PDV_BUFFER_SIZE)
+ {
+ FAPI_ERR("**** ERROR : Wrong size buffer returned from fapiGetMvpdField for #V => %d",
+ l_bufferSize );
+ const uint32_t &BUFFER_SIZE = l_bufferSize;
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDV_BUFFER_SIZE_ERROR);
+ break;
+ }
+
+ // clear array
+ memset(chiplet_mvpd_data, 0, sizeof(chiplet_mvpd_data));
+
+ // 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) ) ))
+
+ // use copy of allocated buffer pointer to increment through buffer
+ l_buffer_inc = l_buffer;
+
+ bucket_id = *l_buffer_inc;
+ l_buffer_inc++;
+
+ FAPI_INF("#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_inc);
+ FAPI_INF("#V data = 0x%04X %-6d", chiplet_mvpd_data[i][ii],
+ chiplet_mvpd_data[i][ii]);
+ // increment to next MVPD value in buffer
+ l_buffer_inc+= 2;
+ }
+ }
+
+ // perform data validity checks on this #V data before proceeding to use it
+ l_rc = proc_chk_valid_poundv( i_target,
+ i_attr,
+ chiplet_mvpd_data,
+ valid_pdv_points,
+ l_chipNum,
+ bucket_id);
+
+ if (l_rc == RC_PROCPM_PSTATE_DATABLOCK_PDV_ZERO_DATA_UT_ERROR)
+ {
+ // Disable WOF
+ i_attr->attr_wof_enabled = 0;
+ }
+ else if (l_rc)
+ {
+ break;
+ }
+
+ // on first chiplet put each bucket's data into attr_mvpd_voltage_control
+ if (first_chplt)
+ {
+
+ for (i=0; i<=4; i++)
+ {
+
+ for (ii=0; ii<=4; ii++)
+ {
+ attr_mvpd_data[i][ii] = chiplet_mvpd_data[i][ii];
+ }
+ }
+
+ first_chplt = 0;
+ }
+ else
+ {
+ // on subsequent chiplets, check that frequencies are same for each operating point for each chiplet
+ if ( (attr_mvpd_data[0][0] != chiplet_mvpd_data[0][0]) ||
+ (attr_mvpd_data[1][0] != chiplet_mvpd_data[1][0]) ||
+ (attr_mvpd_data[2][0] != chiplet_mvpd_data[2][0]) ||
+ (attr_mvpd_data[3][0] != chiplet_mvpd_data[3][0]) ||
+ (attr_mvpd_data[4][0] != chiplet_mvpd_data[4][0]) )
+ {
+ const uint32_t &ATTR_MVPD_DATA_0 = attr_mvpd_data[0][0];
+ const uint32_t &ATTR_MVPD_DATA_1 = attr_mvpd_data[1][0];
+ const uint32_t &ATTR_MVPD_DATA_2 = attr_mvpd_data[2][0];
+ const uint32_t &ATTR_MVPD_DATA_3 = attr_mvpd_data[3][0];
+ const uint32_t &ATTR_MVPD_DATA_4 = attr_mvpd_data[4][0];
+ FAPI_ERR("**** ERROR : frequencies are not the same for each operating point for each chiplet");
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_MVPD_CHIPLET_VOLTAGE_NOT_EQUAL);
+ break;
+ }
+ }
+
+ // check each bucket for max voltage and if max, put bucket's data into attr_mvpd_voltage_control
+ for (i=0; i <= 4; i++)
+ {
+
+ if (attr_mvpd_data[i][1] < chiplet_mvpd_data[i][1])
+ {
+ attr_mvpd_data[i][0] = chiplet_mvpd_data[i][0];
+ attr_mvpd_data[i][1] = chiplet_mvpd_data[i][1];
+ attr_mvpd_data[i][2] = chiplet_mvpd_data[i][2];
+ attr_mvpd_data[i][3] = chiplet_mvpd_data[i][3];
+ attr_mvpd_data[i][4] = chiplet_mvpd_data[i][4];
+ }
+ }
+
+ // --------------------------------------------
+ // Process #M Data
+ // --------------------------------------------
+
+ // Determine if present chiplet is functional
+ l_rc = FAPI_ATTR_GET(ATTR_FUNCTIONAL, &l_exChiplets[j], l_functional);
+
+ if (l_rc)
+ {
+ FAPI_ERR("fapiGetAttribute of ATTR_FUNCTIONAL error");
+ break;
+ }
+
+ if ( l_functional )
+ {
+ *functional_chiplets = 1;
+
+ // clear out buffer to known value before calling fapiGetMvpdField
+ memset(l_buffer_pdm, 0, PDM_BUFFER_ALLOC);
+
+ // 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_INF("**** Warning : Unexpected error encountered in fapiGetMvpdField - IVRMs will not be enabled");
+ *poundm_valid = 0;
+ }
+
+ // check buffer size
+ if (l_bufferSize_pdm < PDM_BUFFER_SIZE)
+ {
+ FAPI_ERR("**** ERROR : Wrong size buffer returned from fapiGetMvpdField for #M from LRP%u => %d vs expected %d",
+ l_chipNum, l_bufferSize_pdm, PDM_BUFFER_SIZE);
+ const uint32_t &BUFFER_SIZE = l_bufferSize;
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDM_BUFFER_SIZE_ERROR);
+ break;
+ }
+
+ // 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
+ *poundm_ver = *l_buffer_pdm_inc;
+ ivrm_mvpd->header.version = *poundm_ver ;
+ l_buffer_pdm_inc++;
+
+ // loop over 13 entries of #M data with 4 measurements per entry
+ FAPI_INF("#M chiplet = %u version = %u", l_chipNum, *poundm_ver);
+
+ for (i=0; i < POUNDM_POINTS; i++)
+ {
+
+ for (ii=0; ii<POUNDM_MEASUREMENTS_PER_POINT; ii++)
+ {
+ cal_data[ii] = UINT16_GET(l_buffer_pdm_inc);
+
+ if (*poundm_ver == 2)
+ {
+ l_buffer_pdm_inc+= 4;
+ }
+ else
+ {
+ 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_INF("#M data (hex & dec) = 0x%04x 0x%04x 0x%04x 0x%04x %5u %5u %5u %5u",
+ cal_data[0], cal_data[1], cal_data[2], cal_data[3], cal_data[0], cal_data[1],
+ cal_data[2], cal_data[3]);
+
+ // #M validity check - not valid if measurements are 0 (exception : cal_data[0](Vg) can be 0)
+ if (cal_data[1] == 0 || cal_data[2] == 0 || cal_data[3] == 0 )
+ {
+ FAPI_INF("**** Warning : #M has zero valued measurements - IVRMs will not be enabled");
+ *poundm_valid = 0;
+ }
+
+ }
+
+ // set number of samples
+ ivrm_mvpd->data.ex[j].point_valid = POUNDM_POINTS;
+ } // end functional
+
+ } // end for loop
- for (i=0; i<=4; i++) {
- for (ii=0; ii<=4; ii++) {
- attr_mvpd_data[i][ii] = chiplet_mvpd_data[i][ii];
- }
- }
- first_chplt = 0;
- }
- else {
- // on subsequent chiplets, check that frequencies are same for each operating point for each chiplet
- if ( (attr_mvpd_data[0][0] != chiplet_mvpd_data[0][0]) ||
- (attr_mvpd_data[1][0] != chiplet_mvpd_data[1][0]) ||
- (attr_mvpd_data[2][0] != chiplet_mvpd_data[2][0]) ||
- (attr_mvpd_data[3][0] != chiplet_mvpd_data[3][0]) ||
- (attr_mvpd_data[4][0] != chiplet_mvpd_data[4][0]) ) {
- const uint32_t &ATTR_MVPD_DATA_0 = attr_mvpd_data[0][0];
- const uint32_t &ATTR_MVPD_DATA_1 = attr_mvpd_data[1][0];
- const uint32_t &ATTR_MVPD_DATA_2 = attr_mvpd_data[2][0];
- const uint32_t &ATTR_MVPD_DATA_3 = attr_mvpd_data[3][0];
- const uint32_t &ATTR_MVPD_DATA_4 = attr_mvpd_data[4][0];
- FAPI_ERR("**** ERROR : frequencies are not the same for each operating point for each chiplet");
- const Target &CHIP_TARGET= i_target;
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_MVPD_CHIPLET_VOLTAGE_NOT_EQUAL);
- break;
}
- }
+ while(0);
- // check each bucket for max voltage and if max, put bucket's data into attr_mvpd_voltage_control
- for (i=0; i <= 4; i++) {
+ free (l_buffer);
+ free (l_buffer_pdm);
- if (attr_mvpd_data[i][1] < chiplet_mvpd_data[i][1]) {
- attr_mvpd_data[i][0] = chiplet_mvpd_data[i][0];
- attr_mvpd_data[i][1] = chiplet_mvpd_data[i][1];
- attr_mvpd_data[i][2] = chiplet_mvpd_data[i][2];
- attr_mvpd_data[i][3] = chiplet_mvpd_data[i][3];
- attr_mvpd_data[i][4] = chiplet_mvpd_data[i][4];
- }
- }
-
- // --------------------------------------------
- // Process #M Data
- // --------------------------------------------
-
- // Determine if present chiplet is functional
- l_rc = FAPI_ATTR_GET(ATTR_FUNCTIONAL, &l_exChiplets[j], l_functional);
- if (l_rc) {
- FAPI_ERR("fapiGetAttribute of ATTR_FUNCTIONAL error");
- break;
- }
-
- if ( l_functional ) {
- *functional_chiplets = 1;
-
- // clear out buffer to known value before calling fapiGetMvpdField
- memset(l_buffer_pdm, 0, 512);
-
- // 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_INF("**** Warning : Unexpected error encountered in fapiGetMvpdField - IVRMs will not be enabled");
- *poundm_valid = 0;
- }
-
- // 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 );
- const uint32_t &BUFFER_SIZE = l_bufferSize;
- const Target &CHIP_TARGET= i_target;
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDM_BUFFER_SIZE_ERROR);
- break;
- }
+ return l_rc;
- // use copy of allocated buffer pointer to increment through buffer
- l_buffer_pdm_inc = l_buffer_pdm;
+ } // end proc_get_mvpd_data
- // get #M version and advance pointer 1-byte to beginning of #M data
- *poundm_ver = *l_buffer_pdm_inc;
- ivrm_mvpd->header.version = *poundm_ver ;
- l_buffer_pdm_inc++;
-
- // loop over 13 entries of #M data with 4 measurements per entry
- FAPI_INF("#M chiplet = %u version = %u", l_chipNum, *poundm_ver);
-
- for (i=0; i < POUNDM_POINTS; i++) {
-
- for (ii=0; ii<4; ii++) {
- cal_data[ii] = UINT16_GET(l_buffer_pdm_inc);
-
- if (*poundm_ver == 2)
- l_buffer_pdm_inc+= 4;
- else
- 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_INF("#M data (hex & dec) = 0x%04x 0x%04x 0x%04x 0x%04x %5u %5u %5u %5u", cal_data[0], cal_data[1], cal_data[2], cal_data[3], cal_data[0], cal_data[1], cal_data[2], cal_data[3]);
-
- // #M validity check - not valid if measurements are 0 (exception : cal_data[0](Vg) can be 0)
- if (cal_data[1] == 0 || cal_data[2] == 0 || cal_data[3] == 0 )
- {
- FAPI_INF("**** Warning : #M has zero valued measurements - IVRMs will not be enabled");
- *poundm_valid = 0;
- }
+/// ----------------------------------------------------------------
+/// \brief Get IQ (IDDQ) data and put into array
+/// \param[in] i_target => Chip Target
+/// \param[inout] attr_mvpd_iddq => 24 x 16 array to hold the IQ data
+/// ----------------------------------------------------------------
+ ReturnCode proc_get_mvpd_iddq(const Target& i_target,
+ PstateSuperStructure *pss)
+ {
+ ReturnCode l_rc;
+ uint8_t * l_buffer_iq = reinterpret_cast<uint8_t *>(malloc(IQ_BUFFER_ALLOC));
+ uint8_t * l_buffer_iq_c = reinterpret_cast<uint8_t *>(malloc(IQ_BUFFER_ALLOC));
+
+ uint8_t * l_buffer_iq_inc;
+ uint32_t l_bufferSize_iq = IQ_BUFFER_ALLOC;
+ uint32_t l_record = 0;
+ uint32_t l_lrp_record = 0;
+ IddqReading * l_iddq_reading;
+ uint32_t c = 0;
+
+
+ const uint8_t vdd_measurement_order[LRP_IDDQ_RECORDS] =
+ CORE_IDDQ_MEASUREMENTS_ORDER;
+ const char * core_measurement_str[LRP_IDDQ_RECORDS] =
+ CORE_IDDQ_MEASUREMENT_VOLTAGES;
+ const uint8_t vcs_measurement_order[LRP_IDDQ_RECORDS] =
+ CORE_IDDQ_MEASUREMENTS_ORDER;
+ const uint8_t core_validity_check[LRP_IDDQ_RECORDS] =
+ CORE_IDDQ_VALIDITY_CHECK;
+ const uint8_t core_second_reading_valid[LRP_IDDQ_RECORDS] =
+ CORE_IDDQ_VALID_SECOND;
+
+ const char * chip_measurement_str[CRP_IDDQ_RECORDS] =
+ CHIP_IDDQ_MEASUREMENT_VOLTAGES;
+ const uint8_t vio_measurement_order[CRP_IDDQ_RECORDS] =
+ CHIP_IDDQ_MEASUREMENTS_ORDER;
+
+
+ // --------------------------------------------
+ // Process IQ (IDD) Data
+ // --------------------------------------------
+
+ // This extraction is not done based on functional or present EX chiplets
+ // as the chip level IDDQ values are stored in LRPx records as matter of
+ // available data storage locations; they are NOT associated with the
+ // EX chiplets themselves.
+
+ // The chip level readings are stored as follows:
+ // LRP 1 1 Vdd 0.90 Raw
+ // LRP 1 2 Vdd 0.90 Temp corrected
+ // LRP 1 3 Vcs 0.90 Raw
+ // LRP 1 4 Vcs 0.90 Temp corrected
+ // LRP 2 1 Vdd 1.00 Raw
+ // LRP 2 2 Vdd 1.00 Temp corrected
+ // LRP 2 3 Vcs 1.00 Raw
+ // LRP 2 4 Vcs 1.00 Temp corrected
+ // LRP 3 1 Vdd 1.10 Raw
+ // LRP 3 2 Vdd 1.10 Temp corrected
+ // LRP 3 3 Vcs 1.10 Raw
+ // LRP 3 4 Vcs 1.10 Temp corrected
+ // LRP 4 1 Vdd 1.20 Raw
+ // LRP 4 2 Vdd 1.20 Temp corrected
+ // LRP 4 3 Vcs 1.20 Raw
+ // LRP 4 4 Vcs 1.20 Temp corrected
+ // LRP 5 1 Vdd 1.25 Raw
+ // LRP 5 2 Vdd 1.25 Temp corrected
+ // LRP 5 3 Vcs 1.25 Raw
+ // LRP 5 4 Vcs 1.25 Temp corrected
+ // LRP 6 1 Vdd 0.80 Raw
+ // LRP 6 2 Vdd 0.80 Temp corrected
+ // CRP 0 1 Vio 1.10 Raw
+ // CRP 0 2 Vio 1.10 Temp corrected
+ //
+ // Note: Vcs never gets to 0.80V. Therefore LRP 6 does not have Vcss.
+ //
+ // Each entry is 2 bytes. The values are in 10mA units; this allow for a
+ // maximum value of 655.36A represented.
+ //
+ // Temp corrected value = Raw value * (1.25^((60C - OCTS_avg_temp)/10)
+ //
+ // Buffer size needed is, at minimum 2B x 24 = 48B.
+
+ do
+ {
+ FAPI_INF("Processing LRPx records for IDDQ keywords");
+ for (c = 0; c < LRP_IDDQ_RECORDS; ++c)
+ {
+ // clear out buffer to known value before calling fapiGetMvpdField
+ memset(l_buffer_iq, 0, IQ_BUFFER_ALLOC);
+
+ l_lrp_record = c+1;
+
+ // set l_record to appropriate lprx record (add core number to lrp0)
+ // Note: Index in the loop are zero origin while the LRP records start at 1
+ l_record = (uint32_t)fapi::MVPD_RECORD_LRP0 + l_lrp_record;
+
+ // Get Chiplet IQ MVPD data from the LRP recoreds
+ l_rc = fapiGetMvpdField((fapi::MvpdRecord)l_record,
+ fapi::MVPD_KEYWORD_IQ,
+ i_target,
+ l_buffer_iq,
+ l_bufferSize_iq);
+
+ if (!l_rc.ok())
+ {
+ FAPI_ERR("**** Error: fapiGetMvpdField from LRP%u", l_lrp_record);
+ const uint32_t &CHIPLET_NUMBER = vdd_measurement_order[c];
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_IQ_MVPD_ERROR);
+ break;
+ }
+
+ // check buffer size
+ if (l_bufferSize_iq < IQ_BUFFER_SIZE)
+ {
+ FAPI_ERR("**** ERROR : Wrong size buffer returned from fapiGetMvpdField for IQ => %d",
+ l_bufferSize_iq );
+ const uint32_t &BUFFER_SIZE = l_bufferSize_iq;
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_IQ_BUFFER_SIZE_ERROR);
+ break;
+ }
+
+ // Initialize the incrementing pointer
+ l_buffer_iq_inc = l_buffer_iq;
+
+ // get IQ version and advance pointer 1-byte to beginning of IQ data
+ uint8_t iq_ver = *l_buffer_iq_inc;
+ pss->iddq.iddq_version = iq_ver ;
+ FAPI_INF(" LRP%d: IDDQ Version Number = %u", l_lrp_record,
+ iq_ver);
+
+ // Increment pointer beyond the 1B version number to the first of the
+ // reading data
+ l_buffer_iq_inc++;
+
+ l_iddq_reading = reinterpret_cast<IddqReading*>(l_buffer_iq_inc);
+ pss->iddq.iddq_vdd[vdd_measurement_order[c]].value =
+ revle32((*l_iddq_reading).value);
+
+ FAPI_INF(" IQ VDD measurement in LRP%d (hex & dec) = 0x%04X %5d (raw), 0x%04X %5d (temp corrected)",
+ l_lrp_record,
+ pss->iddq.iddq_vdd[vdd_measurement_order[c]].fields.iddq_raw_value,
+ pss->iddq.iddq_vdd[vdd_measurement_order[c]].fields.iddq_raw_value,
+ pss->iddq.iddq_vdd[vdd_measurement_order[c]].fields.iddq_corrected_value,
+ pss->iddq.iddq_vdd[vdd_measurement_order[c]].fields.iddq_corrected_value);
+
+ // Check for reading validity
+ // Applies to LRP1-5 content for all versions
+ // Checking LRP6 (VDD = 0.8V) will only produce a warning but will not fail
+
+ // Assume that the 0.80V readings are valid. If they turn out to be zeros,
+ // clear the flag in the Pstate Options vector.
+
+ pss->gpst.options.options = revle32(revle32(pss->gpst.options.options)
+ |
+ PSTATE_IDDQ_0P80V_VALID);
+
+ if (revle16(l_iddq_reading->fields.iddq_raw_value) == 0)
+ {
+ FAPI_INF("**** Warning : IQ VDD measurement @ %s has zero valued measurement",
+ core_measurement_str[c]);
+
+ if (core_validity_check[c])
+ {
+ FAPI_ERR("**** Error : IQ measurement was 0 when expected to be non-zero");
+ const uint16_t &RAW_VALUE = revle16(l_iddq_reading->fields.iddq_raw_value);
+ const uint32_t &LRP_NUMBER = l_lrp_record;
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_IQ_INVALID_VDD_ERROR);
+ break;
+ }
+ // The only reading that might not be valid is 0.8V. If the readings
+ // are zero and the valitity check is off, then clear the 0.80 valid
+ // flag.
+ else
+ {
+ pss->gpst.options.options = revle32(revle32(pss->gpst.options.options)
+ &
+ PSTATE_IDDQ_0P80V_INVALID);
+
+ }
+ }
+
+ if (core_second_reading_valid[c])
+ {
+ FAPI_DBG(" Second reading valid for LRP%d", l_lrp_record);
+
+ l_buffer_iq_inc += sizeof(IddqReading);
+
+ l_iddq_reading = reinterpret_cast<IddqReading*>(l_buffer_iq_inc);
+ pss->iddq.iddq_vcs[vcs_measurement_order[c]].value =
+ revle32((*l_iddq_reading).value);
+
+ FAPI_INF(" IQ VCS measurement in LRP%d (hex & dec) = 0x%04X %5d (raw), 0x%04X %5d (temp corrected)",
+ l_lrp_record,
+ pss->iddq.iddq_vcs[vcs_measurement_order[c]].fields.iddq_raw_value,
+ pss->iddq.iddq_vcs[vcs_measurement_order[c]].fields.iddq_raw_value,
+ pss->iddq.iddq_vcs[vcs_measurement_order[c]].fields.iddq_corrected_value,
+ pss->iddq.iddq_vcs[vcs_measurement_order[c]].fields.iddq_corrected_value);
+
+ if (l_iddq_reading->fields.iddq_raw_value == 0)
+ {
+ FAPI_INF("**** Warning : IQ VDD measurement @ %s has zero valued measurement",
+ core_measurement_str[c]);
+ const uint16_t &RAW_VALUE = revle16(l_iddq_reading->fields.iddq_raw_value);
+ const uint32_t &LRP_NUMBER = c;
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_IQ_INVALID_VCS_ERROR);
+ break;
+ }
+ }
+
+ } // for LRP records
+
+ // Error out chck
+ if(!l_rc.ok())
+ {
+ break;
+ }
+
+
+ FAPI_INF("Processing CRP records for IDDQ keywords");
+ for (c = 0; c < CRP_IDDQ_RECORDS; ++c)
+ {
+ // clear out buffer to known value before calling fapiGetMvpdField
+ memset(l_buffer_iq_c, 0, IQ_BUFFER_ALLOC);
+
+ // set l_record to appropriate cprx record
+ l_record = (uint32_t)fapi::MVPD_RECORD_CRP0;
+ l_bufferSize_iq = IQ_BUFFER_ALLOC; // @todo?
+
+ FAPI_DBG("fapiGetMvpdField(record %X, keyword %X, iq %p, size %d)", l_record,
+ (uint32_t)fapi::MVPD_KEYWORD_IQ,
+ l_buffer_iq_c,
+ l_bufferSize_iq);
+
+ // Get Chip IQ MVPD data from the CRPx records
+ l_rc = fapiGetMvpdField((fapi::MvpdRecord)l_record,
+ fapi::MVPD_KEYWORD_IQ,
+ i_target,
+ l_buffer_iq_c,
+ l_bufferSize_iq);
+ if (!l_rc.ok())
+ {
+ FAPI_ERR("**** Error: fapiGetMvpdField from CRP%u with size %d into buffer sized at %d and rc = %X",
+ c, l_bufferSize_iq, IQ_BUFFER_ALLOC, (uint32_t)l_rc);
+ const uint32_t &CHIPLET_NUMBER = c;
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_IQ_MVPD_ERROR);
+ break;
+ }
+
+ // check buffer size
+ if (l_bufferSize_iq < IQ_BUFFER_SIZE)
+ {
+ FAPI_ERR("**** ERROR : Wrong size buffer returned from fapiGetMvpdField for IQ => %d", l_bufferSize_iq );
+ const uint32_t &BUFFER_SIZE = l_bufferSize_iq;
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_IQ_BUFFER_SIZE_ERROR);
+ break;
+ }
+
+ // use copy of allocated buffer pointer to increment through buffer
+ l_buffer_iq_inc = l_buffer_iq_c;
+
+ // get IQ version and advance pointer 1-byte to beginning of IQ data
+ uint8_t iq_ver = *l_buffer_iq_inc;
+ pss->iddq.iddq_version = iq_ver ;
+ FAPI_INF(" CRP0: IDDQ Version Number = %u", iq_ver);
+ l_buffer_iq_inc++;
+
+ l_iddq_reading = reinterpret_cast<IddqReading*>(l_buffer_iq_inc);
+ pss->iddq.iddq_vio[vio_measurement_order[c]].value =
+ revle32((*l_iddq_reading).value);
+
+ FAPI_INF(" IQ VIO measurement (hex & dec) = 0x%04x %5x (raw), 0x%04x %5x (temp corrected)",
+ pss->iddq.iddq_vio[c].fields.iddq_raw_value,
+ pss->iddq.iddq_vio[c].fields.iddq_raw_value,
+ pss->iddq.iddq_vio[c].fields.iddq_corrected_value,
+ pss->iddq.iddq_vio[c].fields.iddq_corrected_value);
+
+ if (revle16(l_iddq_reading->fields.iddq_raw_value) == 0)
+ {
+ FAPI_ERR("IQ VIO measurement @ %s has zero valued measurement",
+ chip_measurement_str[c]);
+ const uint16_t &RAW_VALUE = l_iddq_reading->fields.iddq_raw_value ;
+ const Target &CHIP_TARGET= i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_IQ_INVALID_VIO_ERROR);
+ break;
+ }
+
+ } // for CRP records
}
+ while(0);
- // set number of samples to 13
- ivrm_mvpd->data.ex[j].point_valid = POUNDM_POINTS;
- } // end functional
-
- } // end for loop
+ // Free up memory buffer
+ free(l_buffer_iq);
+// free(l_buffer_iq_c);
- } while(0);
+ return l_rc;
- free (l_buffer);
- free (l_buffer_pdm);
+ } // proc_get_mvdp_iddq
- return l_rc;
-} // end proc_get_mvpd_data
/// ---------------------------------------------------------------------------
@@ -989,44 +1612,59 @@ ReturnCode proc_get_mvpd_data(const Target& i_target,
/// \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_INF("BIAS freq = %f", freq_bias);
- FAPI_INF("BIAS vdd ext = %f vcs ext = %f", volt_ext_vdd_bias, volt_ext_vcs_bias);
- FAPI_INF("BIAS vdd int = %f vcs int = %f", *volt_int_vdd_bias, *volt_int_vcs_bias);
-
- return l_rc;
-} // end proc_get_extint_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_INF("BIAS freq = %f", freq_bias);
+ FAPI_INF("BIAS vdd ext = %f vcs ext = %f", volt_ext_vdd_bias,
+ volt_ext_vcs_bias);
+ FAPI_INF("BIAS vdd int = %f vcs int = %f", *volt_int_vdd_bias,
+ *volt_int_vcs_bias);
+
+ return l_rc;
+ } // end proc_get_extint_bias
/// ------------------------------------------------------------
@@ -1035,78 +1673,117 @@ ReturnCode proc_get_extint_bias(uint32_t attr_mvpd_data[PV_D][PV_W],
/// \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_INF("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);
- FAPI_INF("Converting CPM inflection point %u (%u khz) to Pstate", i, freq_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_INF("CPM point freq_khz = %u pstate = %d",freq_khz, pstate);
- }
+ 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_INF("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);
+ FAPI_INF("Converting CPM inflection point %u (%u khz) to Pstate", i, freq_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_INF("CPM point freq_khz = %u pstate = %d",freq_khz, pstate);
+ }
- if (rc) break;
+ if (rc)
+ {
+ break;
+ }
- // convert pMax attribute to Khz and then convert to pstate value
+ // convert pMax attribute to Khz and then convert to pstate value
- if (attr->attr_cpm_inflection_points[9] == 0) {
- FAPI_INF(" CPM pMax = 0. Skipping conversion to pstate");
- }
- else {
- freq_khz = attr->attr_cpm_inflection_points[9] * revle32(pss->gpst.frequency_step_khz);
- FAPI_INF("Converting CPM pMax (%u khz) to Pstate", freq_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_INF("CPM pMax freq_khz = %u pstate = %d",freq_khz, pstate);
- }
+ if (attr->attr_cpm_inflection_points[9] == 0)
+ {
+ FAPI_INF(" CPM pMax = 0. Skipping conversion to pstate");
+ }
+ else
+ {
+ freq_khz = attr->attr_cpm_inflection_points[9] * revle32(
+ pss->gpst.frequency_step_khz);
+ FAPI_INF("Converting CPM pMax (%u khz) to Pstate", freq_khz);
+ rc = freq2pState(&(pss->gpst), freq_khz, &pstate);
- } while (0);
+ if (rc)
+ {
+ break;
+ }
- // ------------------------------------------------------
- // check error code from freq2pState or pstate_minmax_chk
- // ------------------------------------------------------
- if (rc) {
- int & RETURN_CODE = rc;
- int8_t & PSTATE = pstate;
- uint32_t & FREQ_KHZ = freq_khz;
+ rc = pstate_minmax_chk(&(pss->gpst), &pstate);
- if (rc == -PSTATE_LT_PSTATE_MIN || rc == -PSTATE_GT_PSTATE_MAX) {
- 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 (computed pstate = %d max 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);
- }
- }
+ if (rc)
+ {
+ break;
+ }
+
+ pss->cpmranges.pMax = pstate;
+
+ FAPI_INF("CPM pMax freq_khz = %u pstate = %d",freq_khz, pstate);
+ }
- return l_rc;
-} // end proc_upd_cpmrange
+ }
+ while (0);
+
+ // ------------------------------------------------------
+ // check error code from freq2pState or pstate_minmax_chk
+ // ------------------------------------------------------
+ if (rc)
+ {
+ int & RETURN_CODE = rc;
+ int8_t & PSTATE = pstate;
+ uint32_t & FREQ_KHZ = freq_khz;
+
+ if (rc == -PSTATE_LT_PSTATE_MIN || rc == -PSTATE_GT_PSTATE_MAX)
+ {
+ 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 (computed pstate = %d max 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
/// -------------------------------------------------------------------
@@ -1115,97 +1792,111 @@ ReturnCode proc_upd_cpmrange (PstateSuperStructure *pss,
/// \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;
-
- const uint32_t MAXIMUM_BOOST_PERCENT_SUPPORTED = 20;
- const uint32_t MAXIMUM_PSTATE_RANGE = 255; // maximum represented by uint8_t
-
- do
- {
-
- if (attr_boost_percent == 0) {
- FAPI_INF("CPM Turbo Boost Attribute = 0 -- no boosting will be done");
- break;
- }
+ 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;
+
+ const uint32_t MAXIMUM_BOOST_PERCENT_SUPPORTED = 20;
+ const uint32_t MAXIMUM_PSTATE_RANGE = 255; // maximum represented by uint8_t
+
+ do
+ {
+
+ if (attr_boost_percent == 0)
+ {
+ FAPI_INF("CPM Turbo Boost Attribute = 0 -- no boosting will be done");
+ break;
+ }
- // check that percentage is rational. Note: attribute information is .1 percent units
- if (attr_boost_percent > MAXIMUM_BOOST_PERCENT_SUPPORTED * 10) {
- FAPI_ERR("Boost percentage is greater than maximum supported. Max: %u; Value: %u",
- MAXIMUM_BOOST_PERCENT_SUPPORTED, attr_boost_percent);
- const uint32_t& MAXBOOSTPERCENT = MAXIMUM_BOOST_PERCENT_SUPPORTED;
- const uint32_t& ATTRBOOSTPERCENT = attr_boost_percent;
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_INVALID_BOOST_PERCENTAGE_ERROR);
- break;
- }
+ // check that percentage is rational. Note: attribute information is .1 percent units
+ if (attr_boost_percent > MAXIMUM_BOOST_PERCENT_SUPPORTED * 10)
+ {
+ FAPI_ERR("Boost percentage is greater than maximum supported. Max: %u; Value: %u",
+ MAXIMUM_BOOST_PERCENT_SUPPORTED, attr_boost_percent);
+ const uint32_t& MAXBOOSTPERCENT = MAXIMUM_BOOST_PERCENT_SUPPORTED;
+ const uint32_t& ATTRBOOSTPERCENT = attr_boost_percent;
+ FAPI_SET_HWP_ERROR(l_rc,
+ RC_PROCPM_PSTATE_DATABLOCK_INVALID_BOOST_PERCENTAGE_ERROR);
+ break;
+ }
- // calculate percent to boost
- boosted_pct = 1.0 + (BOOST_PCT_UNIT * (double)attr_boost_percent);
+ // 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 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);
+ // 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);
+ // 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) {
- FAPI_INF("CPM Turbo Boost Attribute resulted in no increase in pstates - boost_pct = %f turbo_freq_khz = %u boosted_freq_khz = %u",
- boosted_pct, pstate0_frequency_khz, boosted_freq_khz);
- break;
- }
- // 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) {
- FAPI_INF("CPM Turbo Boost Attribute resulted in no increase in pstates - boost_pct = %f turbo_freq_khz = %u boosted_freq_khz = %u",
- boosted_pct, pstate0_frequency_khz, boosted_freq_khz);
- break;
- }
- else if (pstate_diff > MAXIMUM_PSTATE_RANGE) {
- FAPI_ERR("Percentage boost calculation overrun produced invalid Pstate Difference: %u", pstate_diff);
- const uint32_t& PSTATEDIFF = pstate_diff;
- const uint32_t& BOOSTEDFREQKHZ = boosted_freq_khz;
- const uint32_t& PSTATE0FREQKHZ = pstate0_frequency_khz;
- const uint32_t& FREQSTEPKHZ = frequency_step_khz;
- const uint32_t& ATTRBOOSTPERCENT = attr_boost_percent;
- const double& BOOSTEDPCT = boosted_pct;
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PSTATE_DIFF_ERROR);
- break;
- }
- else {
- gpsi_max = pss->gpst.entries - 1;
- entry.value = revle64(pss->gpst.pstate[gpsi_max].value);
+ // if boosted frequency is <= turbo frequency, then no boost is to be done
+ if (boosted_freq_khz <= pstate0_frequency_khz)
+ {
+ FAPI_INF("CPM Turbo Boost Attribute resulted in no increase in pstates - boost_pct = %f turbo_freq_khz = %u boosted_freq_khz = %u",
+ boosted_pct, pstate0_frequency_khz, boosted_freq_khz);
+ break;
+ }
- FAPI_INF("Boosting Pstate Table : percent = %f num pstates added = %d", boosted_pct, pstate_diff);
+ // calculate # pstates that boosted frequency is above turbo
+ pstate_diff = (boosted_freq_khz/frequency_step_khz) -
+ (pstate0_frequency_khz/frequency_step_khz);
- for (i = 1; i <= pstate_diff; i++) {
- idx = gpsi_max + i;
- pss->gpst.pstate[idx].value = revle64(entry.value);
- }
+ // pstate difference is 0 then no boost is to be done, else update global pstate table
+ if (pstate_diff == 0)
+ {
+ FAPI_INF("CPM Turbo Boost Attribute resulted in no increase in pstates - boost_pct = %f turbo_freq_khz = %u boosted_freq_khz = %u",
+ boosted_pct, pstate0_frequency_khz, boosted_freq_khz);
+ break;
+ }
+ else if (pstate_diff > MAXIMUM_PSTATE_RANGE)
+ {
+ FAPI_ERR("Percentage boost calculation overrun produced invalid Pstate Difference: %u",
+ pstate_diff);
+ const uint32_t& PSTATEDIFF = pstate_diff;
+ const uint32_t& BOOSTEDFREQKHZ = boosted_freq_khz;
+ const uint32_t& PSTATE0FREQKHZ = pstate0_frequency_khz;
+ const uint32_t& FREQSTEPKHZ = frequency_step_khz;
+ const uint32_t& ATTRBOOSTPERCENT = attr_boost_percent;
+ const double& BOOSTEDPCT = boosted_pct;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PSTATE_DIFF_ERROR);
+ break;
+ }
+ else
+ {
+ gpsi_max = pss->gpst.entries - 1;
+ entry.value = revle64(pss->gpst.pstate[gpsi_max].value);
- pss->gpst.entries += pstate_diff;
+ FAPI_INF("Boosting Pstate Table : percent = %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);
+ }
- } while(0);
- return l_rc;
-} // end proc_boost_gpst
+ pss->gpst.entries += pstate_diff;
+
+ }
+
+ }
+ while(0);
+
+ return l_rc;
+ } // end proc_boost_gpst
/// -------------------------------------------------------------------
@@ -1213,76 +1904,141 @@ ReturnCode proc_boost_gpst (PstateSuperStructure *pss,
/// \param[in] poundv_data => pointer to array of #V data
/// -------------------------------------------------------------------
-ReturnCode proc_chk_valid_poundv(const Target& i_target,
- const uint32_t poundv_data[PV_D][PV_W],
- uint8_t chiplet_num,
- uint8_t bucket_id)
-{
- ReturnCode l_rc;
- const uint8_t pv_op_order[S132A_POINTS] = PV_OP_ORDER;
- const char *pv_op_str[S132A_POINTS] = PV_OP_ORDER_STR;
- uint8_t i = 0;
-
- do
- {
- // check for non-zero freq, voltage, or current in valid operating points
- for (i = 0; i <= S132A_POINTS-1; i++) {
-
- FAPI_INF("Checking for Zero valued data in each #V operating point (%s) f=%u v=%u i=%u v=%u i=%u",
- pv_op_str[pv_op_order[i]],
- poundv_data[pv_op_order[i]][0],
- poundv_data[pv_op_order[i]][1],
- poundv_data[pv_op_order[i]][2],
- poundv_data[pv_op_order[i]][3],
- poundv_data[pv_op_order[i]][4]);
-
- if (poundv_data[pv_op_order[i]][0] == 0 ||
- poundv_data[pv_op_order[i]][1] == 0 ||
- poundv_data[pv_op_order[i]][2] == 0 ||
- poundv_data[pv_op_order[i]][3] == 0 ||
- poundv_data[pv_op_order[i]][4] == 0 ) {
-
- FAPI_ERR("**** ERROR : Zero valued data found in #V (chiplet = %u bucket id = %u op point = %s)", chiplet_num, bucket_id, pv_op_str[pv_op_order[i]]);
- const uint8_t& OP_POINT = pv_op_order[i];
- const uint8_t& CHIPLET_NUM = chiplet_num;
- const uint8_t& BUCKET_ID = bucket_id;
- const Target &CHIP_TARGET = i_target;
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDV_ZERO_DATA_ERROR);
- break;
- }
- }
+ ReturnCode proc_chk_valid_poundv(const Target& i_target,
+ AttributeList* i_attr,
+ const uint32_t poundv_data[PV_D][PV_W],
+ uint32_t* valid_pdv_points,
+ uint8_t chiplet_num,
+ uint8_t bucket_id)
+
+ {
+ ReturnCode l_rc;
+ const uint8_t pv_op_order[S132A_POINTS] = PV_OP_ORDER;
+ const char *pv_op_str[S132A_POINTS] = PV_OP_ORDER_STR;
+ uint8_t i = 0;
+ bool suspend_ut_check = false;
+
+ do
+ {
+ // check for non-zero freq, voltage, or current in valid operating points
+ for (i = 0; i <= S132A_POINTS-1; i++)
+ {
+ FAPI_INF("Checking for Zero valued data in each #V operating point (%s) f=%u v=%u i=%u v=%u i=%u",
+ pv_op_str[pv_op_order[i]],
+ poundv_data[pv_op_order[i]][0],
+ poundv_data[pv_op_order[i]][1],
+ poundv_data[pv_op_order[i]][2],
+ poundv_data[pv_op_order[i]][3],
+ poundv_data[pv_op_order[i]][4]);
+
+ if (i_attr->attr_wof_enabled && (strcmp(pv_op_str[pv_op_order[i]], "UltraTurbo") == 0))
+ {
+
+ if (poundv_data[pv_op_order[i]][0] == 0 ||
+ poundv_data[pv_op_order[i]][1] == 0 ||
+ poundv_data[pv_op_order[i]][2] == 0 ||
+ poundv_data[pv_op_order[i]][3] == 0 ||
+ poundv_data[pv_op_order[i]][4] == 0 )
+ {
+
+ FAPI_INF("**** WARNING: WOF is enabled but zero valued data found in #V (chiplet = %u bucket id = %u op point = %s)",
+ chiplet_num, bucket_id, pv_op_str[pv_op_order[i]]);
+ FAPI_INF("**** WARNING: Disabling WOF and continuing");
+ const uint8_t& OP_POINT = pv_op_order[i];
+ const uint8_t& CHIPLET_NUM = chiplet_num;
+ const uint8_t& BUCKET_ID = bucket_id;
+ const Target &CHIP_TARGET = i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDV_ZERO_DATA_UT_ERROR);
+ suspend_ut_check = true;
+ }
+ }
+ else if ((!i_attr->attr_wof_enabled) && (strcmp(pv_op_str[pv_op_order[i]], "UltraTurbo") == 0))
+ {
+ FAPI_INF("**** NOTE: WOF is disabled so the UltraTurbo VPD is not being checked");
+ suspend_ut_check = true;
+ }
+ else
+ {
+
+ if (poundv_data[pv_op_order[i]][0] == 0 ||
+ poundv_data[pv_op_order[i]][1] == 0 ||
+ poundv_data[pv_op_order[i]][2] == 0 ||
+ poundv_data[pv_op_order[i]][3] == 0 ||
+ poundv_data[pv_op_order[i]][4] == 0 )
+ {
+
+ FAPI_ERR("**** ERROR : Zero valued data found in #V (chiplet = %u bucket id = %u op point = %s)",
+ chiplet_num, bucket_id, pv_op_str[pv_op_order[i]]);
+ const uint8_t& OP_POINT = pv_op_order[i];
+ const uint8_t& CHIPLET_NUM = chiplet_num;
+ const uint8_t& BUCKET_ID = bucket_id;
+ const Target &CHIP_TARGET = i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDV_ZERO_DATA_ERROR);
+ break;
+ }
+ }
+ }
- if (l_rc) break;
-
- // check valid operating points' values have this relationship (power save <= nominal <= turbo)
- for (i = 1; i <= S132A_POINTS-1; i++) {
-
- FAPI_INF("Checking for relationship between #V operating point (%s <= %s)", pv_op_str[pv_op_order[i-1]], pv_op_str[pv_op_order[i]]);
- FAPI_INF(" f=%u <= f=%u", poundv_data[pv_op_order[i-1]][0], poundv_data[pv_op_order[i]][0]);
- FAPI_INF(" v=%u <= v=%u i=%u <= i=%u", poundv_data[pv_op_order[i-1]][1], poundv_data[pv_op_order[i]][1], poundv_data[pv_op_order[i-1]][2], poundv_data[pv_op_order[i]][2]);
- FAPI_INF(" v=%u <= v=%u i=%u <= i=%u", poundv_data[pv_op_order[i-1]][3], poundv_data[pv_op_order[i]][3], poundv_data[pv_op_order[i-1]][4], poundv_data[pv_op_order[i]][4]);
-
- if (poundv_data[pv_op_order[i-1]][0] > poundv_data[pv_op_order[i]][0] ||
- poundv_data[pv_op_order[i-1]][1] > poundv_data[pv_op_order[i]][1] ||
- poundv_data[pv_op_order[i-1]][2] > poundv_data[pv_op_order[i]][2] ||
- poundv_data[pv_op_order[i-1]][3] > poundv_data[pv_op_order[i]][3] ||
- poundv_data[pv_op_order[i-1]][4] > poundv_data[pv_op_order[i]][4] ) {
-
- FAPI_ERR("**** ERROR : Relationship error between #V operating point (%s <= %s)(power save <= nominal <= turbo) (chiplet = %u bucket id = %u op point = %u)",
- pv_op_str[pv_op_order[i-1]], pv_op_str[pv_op_order[i]], chiplet_num, bucket_id, pv_op_order[i]);
- const uint8_t& OP_POINT = pv_op_order[i];
- const uint8_t& CHIPLET_NUM = chiplet_num;
- const uint8_t& BUCKET_ID = bucket_id;
- const Target &CHIP_TARGET = i_target;
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDV_OPPOINT_ORDER_ERROR);
- break;
- }
- }
+ if (l_rc)
+ {
+ // If an error was found where suspension was flagged, keep going.
+ // If not, break to exit point.
+ if (!suspend_ut_check)
+ break;
+ }
+
+
+ // Adjust the valid operating point based on UltraTurbo presence
+ // and WOF enablement
+ *valid_pdv_points = S132A_POINTS;
+
+ if (suspend_ut_check)
+ (*valid_pdv_points)--;
+
+ FAPI_DBG("valid_pdv_points = %d", *valid_pdv_points);
+
+ // check valid operating points' values have this relationship (power save <= nominal <= turbo <= ultraturbo)
+ for (i = 1; i <= (*valid_pdv_points)-1; i++)
+ {
+
+ FAPI_INF("Checking for relationship between #V operating point (%s <= %s)",
+ pv_op_str[pv_op_order[i-1]], pv_op_str[pv_op_order[i]]);
+ FAPI_INF(" f=%u <= f=%u", poundv_data[pv_op_order[i-1]][0],
+ poundv_data[pv_op_order[i]][0]);
+ FAPI_INF(" v=%u <= v=%u i=%u <= i=%u", poundv_data[pv_op_order[i-1]][1],
+ poundv_data[pv_op_order[i]][1], poundv_data[pv_op_order[i-1]][2],
+ poundv_data[pv_op_order[i]][2]);
+ FAPI_INF(" v=%u <= v=%u i=%u <= i=%u", poundv_data[pv_op_order[i-1]][3],
+ poundv_data[pv_op_order[i]][3], poundv_data[pv_op_order[i-1]][4],
+ poundv_data[pv_op_order[i]][4]);
+
+ if (i_attr->attr_wof_enabled && strcmp(pv_op_str[pv_op_order[i]], "UltraTurbo") && !suspend_ut_check )
+ {
+ if (poundv_data[pv_op_order[i-1]][0] > poundv_data[pv_op_order[i]][0] ||
+ poundv_data[pv_op_order[i-1]][1] > poundv_data[pv_op_order[i]][1] ||
+ poundv_data[pv_op_order[i-1]][2] > poundv_data[pv_op_order[i]][2] ||
+ poundv_data[pv_op_order[i-1]][3] > poundv_data[pv_op_order[i]][3] ||
+ poundv_data[pv_op_order[i-1]][4] > poundv_data[pv_op_order[i]][4] )
+ {
+
+ FAPI_ERR("**** ERROR : Relationship error between #V operating point (%s <= %s)(power save <= nominal <= turbo <= ultraturbo) (chiplet = %u bucket id = %u op point = %u)",
+ pv_op_str[pv_op_order[i-1]], pv_op_str[pv_op_order[i]], chiplet_num, bucket_id,
+ pv_op_order[i]);
+ const uint8_t& OP_POINT = pv_op_order[i];
+ const uint8_t& CHIPLET_NUM = chiplet_num;
+ const uint8_t& BUCKET_ID = bucket_id;
+ const Target &CHIP_TARGET = i_target;
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PDV_OPPOINT_ORDER_ERROR);
+ break;
+ }
+ }
+ }
- } while(0);
+ }
+ while(0);
- return l_rc;
-}
+ return l_rc;
+ }
/// -------------------------------------------------------------------
@@ -1290,20 +2046,20 @@ ReturnCode proc_chk_valid_poundv(const Target& i_target,
/// \param[inout] *pss => pointer to pstate superstructure
/// \param[in] *attr => pointer to attribute list structure
/// -------------------------------------------------------------------
-ReturnCode proc_res_clock (PstateSuperStructure *pss,
- AttributeList *attr_list)
-{
- ReturnCode l_rc;
- int rc = 0;
- uint32_t freq_khz = 0;
- Pstate pstate = 0;
-
- do
- {
- // ----------------------------------------------------------------------------
- // convert resonant clock frequencies to pstate value and set in superstructure
- // ----------------------------------------------------------------------------
- #define DATABLOCK_RESCLK(attr_name, ps_name) \
+ ReturnCode proc_res_clock (PstateSuperStructure *pss,
+ AttributeList *attr_list)
+ {
+ ReturnCode l_rc;
+ int rc = 0;
+ uint32_t freq_khz = 0;
+ Pstate pstate = 0;
+
+ do
+ {
+ // ----------------------------------------------------------------------------
+ // convert resonant clock frequencies to pstate value and set in superstructure
+ // ----------------------------------------------------------------------------
+#define DATABLOCK_RESCLK(attr_name, ps_name) \
freq_khz = attr_list->attr_name; \
FAPI_INF("Converting %s (%u khz) to Pstate", #attr_name, freq_khz); \
rc = freq2pState(&(pss->gpst), freq_khz, &pstate); \
@@ -1315,34 +2071,45 @@ ReturnCode proc_res_clock (PstateSuperStructure *pss,
} \
pss->resclk.ps_name = pstate;
- DATABLOCK_RESCLK(attr_pm_resonant_clock_full_clock_sector_buffer_frequency, full_csb_ps);
- DATABLOCK_RESCLK(attr_pm_resonant_clock_low_band_lower_frequency, res_low_lower_ps);
- DATABLOCK_RESCLK(attr_pm_resonant_clock_low_band_upper_frequency, res_low_upper_ps);
- DATABLOCK_RESCLK(attr_pm_resonant_clock_high_band_lower_frequency, res_high_lower_ps);
- DATABLOCK_RESCLK(attr_pm_resonant_clock_high_band_upper_frequency, res_high_upper_ps);
-
- } while(0);
-
- // ---------------------------------
- // check error code from freq2pState
- // ---------------------------------
- if (rc && rc != -GPST_PSTATE_GT_GPST_PMAX) {
- int & RETURN_CODE = rc;
- int8_t & PSTATE = pstate;
- uint32_t & FREQ_KHZ = freq_khz;
-
- if (rc == -PSTATE_LT_PSTATE_MIN || rc == -PSTATE_GT_PSTATE_MAX) {
- 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_FREQ2PSTATE_PSTATE_MINMAX_BOUNDS_ERROR);
- }
- else {
- FAPI_ERR("**** ERROR : Bad Return code rc = %d", rc );
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_FREQ2PSTATE_ERROR);
- }
- }
+ DATABLOCK_RESCLK(attr_pm_resonant_clock_full_clock_sector_buffer_frequency,
+ full_csb_ps);
+ DATABLOCK_RESCLK(attr_pm_resonant_clock_low_band_lower_frequency,
+ res_low_lower_ps);
+ DATABLOCK_RESCLK(attr_pm_resonant_clock_low_band_upper_frequency,
+ res_low_upper_ps);
+ DATABLOCK_RESCLK(attr_pm_resonant_clock_high_band_lower_frequency,
+ res_high_lower_ps);
+ DATABLOCK_RESCLK(attr_pm_resonant_clock_high_band_upper_frequency,
+ res_high_upper_ps);
- return l_rc;
-}
+ }
+ while(0);
+
+ // ---------------------------------
+ // check error code from freq2pState
+ // ---------------------------------
+ if (rc && rc != -GPST_PSTATE_GT_GPST_PMAX)
+ {
+ int & RETURN_CODE = rc;
+ int8_t & PSTATE = pstate;
+ uint32_t & FREQ_KHZ = freq_khz;
+
+ if (rc == -PSTATE_LT_PSTATE_MIN || rc == -PSTATE_GT_PSTATE_MAX)
+ {
+ 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_FREQ2PSTATE_PSTATE_MINMAX_BOUNDS_ERROR);
+ }
+ else
+ {
+ FAPI_ERR("**** ERROR : Bad Return code rc = %d", rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_FREQ2PSTATE_ERROR);
+ }
+ }
+
+ return l_rc;
+ }
/// ------------------------------------------------------------
@@ -1351,53 +2118,71 @@ ReturnCode proc_res_clock (PstateSuperStructure *pss,
/// \param[in] *attr => pointer to attribute list structure
/// ------------------------------------------------------------
-ReturnCode proc_upd_psafe_ps (PstateSuperStructure *pss,
- const AttributeList *attr)
-{
- ReturnCode l_rc;
- int rc = 0;
- Pstate pstate;
- uint32_t freq_khz;
-
- do
- {
-
- freq_khz = attr->attr_pm_safe_frequency*1000;
- FAPI_INF("Converting attr_pm_safe_frequency in %u khz to Pstate", freq_khz);
- rc = freq2pState(&(pss->gpst), freq_khz, &pstate);
- if(rc) break;
- FAPI_INF("Producing pstate = %d for attr_pm_safe_frequency = %u khz", pstate, freq_khz);
- rc = pstate_minmax_chk(&(pss->gpst), &pstate);
- if(rc) break;
- FAPI_IMP("Now set psafe in Global Pstate Table to be pstate of attr_pm_safe_frequency");
- pss->gpst.psafe = pstate;
-
- } while (0);
-
- // ------------------------------------------------------
- // check error code from freq2pState or pstate_minmax_chk
- // ------------------------------------------------------
- if (rc) {
- int & RETURN_CODE = rc;
- int8_t & PSTATE = pstate;
- uint32_t & FREQ_KHZ = freq_khz;
-
- if (rc == -PSTATE_LT_PSTATE_MIN || rc == -PSTATE_GT_PSTATE_MAX) {
- 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_PSAFE_MINMAX_BOUNDS_ERROR);
- }
- else if (rc == -GPST_PSTATE_GT_GPST_PMAX){
- FAPI_ERR("**** ERROR : Computed pstate is greater than max pstate in gpst (computed pstate = %d max pstate = %d rc = %d", pstate, gpst_pmax(&(pss->gpst)), rc );
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PSAFE_GT_GPSTPMAX_ERROR);
- }
- else {
- FAPI_ERR("**** ERROR : Bad Return code rc = %d", rc );
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PSAFE_ERROR);
- }
- }
+ ReturnCode proc_upd_psafe_ps (PstateSuperStructure *pss,
+ const AttributeList *attr)
+ {
+ ReturnCode l_rc;
+ int rc = 0;
+ Pstate pstate;
+ uint32_t freq_khz;
+
+ do
+ {
- return l_rc;
-} // end proc_upd_psafe_ps
+ freq_khz = attr->attr_pm_safe_frequency*1000;
+ FAPI_INF("Converting attr_pm_safe_frequency in %u khz to Pstate", freq_khz);
+ rc = freq2pState(&(pss->gpst), freq_khz, &pstate);
+
+ if(rc)
+ {
+ break;
+ }
+
+ FAPI_INF("Producing Pstate = %d for attr_pm_safe_frequency = %u khz", pstate,
+ freq_khz);
+ rc = pstate_minmax_chk(&(pss->gpst), &pstate);
+
+ if(rc)
+ {
+ break;
+ }
+
+ FAPI_IMP("Setting Psafe in Global Pstate Table to be Pstate of attr_pm_safe_frequency");
+ pss->gpst.psafe = pstate;
+
+ }
+ while (0);
+
+ // ------------------------------------------------------
+ // check error code from freq2pState or pstate_minmax_chk
+ // ------------------------------------------------------
+ if (rc)
+ {
+ int & RETURN_CODE = rc;
+ int8_t & PSTATE = pstate;
+ uint32_t & FREQ_KHZ = freq_khz;
+
+ if (rc == -PSTATE_LT_PSTATE_MIN || rc == -PSTATE_GT_PSTATE_MAX)
+ {
+ 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_PSAFE_MINMAX_BOUNDS_ERROR);
+ }
+ else if (rc == -GPST_PSTATE_GT_GPST_PMAX)
+ {
+ FAPI_ERR("**** ERROR : Computed pstate is greater than max pstate in gpst (computed pstate = %d max pstate = %d rc = %d",
+ pstate, gpst_pmax(&(pss->gpst)), rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PSAFE_GT_GPSTPMAX_ERROR);
+ }
+ else
+ {
+ FAPI_ERR("**** ERROR : Bad Return code rc = %d", rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PSAFE_ERROR);
+ }
+ }
+
+ return l_rc;
+ } // end proc_upd_psafe_ps
/// ------------------------------------------------------------
@@ -1406,53 +2191,134 @@ ReturnCode proc_upd_psafe_ps (PstateSuperStructure *pss,
/// \param[in] *attr => pointer to attribute list structure
/// ------------------------------------------------------------
-ReturnCode proc_upd_floor_ps (PstateSuperStructure *pss,
- const AttributeList *attr)
-{
- ReturnCode l_rc;
- int rc = 0;
- Pstate pstate;
- uint32_t freq_khz;
-
- do
- {
-
- freq_khz = attr->attr_freq_core_floor*1000;
- FAPI_INF("Converting attr_freq_core_floor in %u khz to Pstate", freq_khz);
- rc = freq2pState(&(pss->gpst), freq_khz, &pstate);
- if(rc) break;
- FAPI_INF("Producing pstate = %d for attr_freq_core_floor = %u khz", pstate, freq_khz);
- rc = pstate_minmax_chk(&(pss->gpst), &pstate);
- if(rc) break;
- FAPI_IMP("Now set pfloor in Global Pstate Table to be pstate of attr_freq_core_floor");
- pss->gpst.pfloor = pstate;
-
- } while (0);
-
- // ------------------------------------------------------
- // check error code from freq2pState or pstate_minmax_chk
- // ------------------------------------------------------
- if (rc) {
- int & RETURN_CODE = rc;
- int8_t & PSTATE = pstate;
- uint32_t & FREQ_KHZ = freq_khz;
-
- if (rc == -PSTATE_LT_PSTATE_MIN || rc == -PSTATE_GT_PSTATE_MAX) {
- 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_PFLOOR_MINMAX_BOUNDS_ERROR);
- }
- else if (rc == -GPST_PSTATE_GT_GPST_PMAX){
- FAPI_ERR("**** ERROR : Computed pstate is greater than max pstate in gpst (computed pstate = %d max pstate = %d rc = %d", pstate, gpst_pmax(&(pss->gpst)), rc );
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PFLOOR_GT_GPSTPMAX_ERROR);
- }
- else {
- FAPI_ERR("**** ERROR : Bad Return code rc = %d", rc );
- FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PFLOOR_ERROR);
- }
- }
+ ReturnCode proc_upd_floor_ps (PstateSuperStructure *pss,
+ const AttributeList *attr)
+ {
+ ReturnCode l_rc;
+ int rc = 0;
+ Pstate pstate;
+ uint32_t freq_khz;
+
+ do
+ {
+
+ freq_khz = attr->attr_freq_core_floor*1000;
+ FAPI_INF("Converting attr_freq_core_floor in %u khz to Pstate", freq_khz);
+ rc = freq2pState(&(pss->gpst), freq_khz, &pstate);
+
+ if(rc)
+ {
+ break;
+ }
+
+ FAPI_INF("Producing Pstate = %d for attr_freq_core_floor = %u khz", pstate,
+ freq_khz);
+ rc = pstate_minmax_chk(&(pss->gpst), &pstate);
+
+ if(rc)
+ {
+ break;
+ }
+
+ FAPI_IMP("Setting Pfloor in Global Pstate Table to be Pstate of attr_freq_core_floor");
+ pss->gpst.pfloor = pstate;
+
+ }
+ while (0);
+
+ // ------------------------------------------------------
+ // check error code from freq2pState or pstate_minmax_chk
+ // ------------------------------------------------------
+ if (rc)
+ {
+ int & RETURN_CODE = rc;
+ int8_t & PSTATE = pstate;
+ uint32_t & FREQ_KHZ = freq_khz;
+
+ if (rc == -PSTATE_LT_PSTATE_MIN || rc == -PSTATE_GT_PSTATE_MAX)
+ {
+ 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_PFLOOR_MINMAX_BOUNDS_ERROR);
+ }
+ else if (rc == -GPST_PSTATE_GT_GPST_PMAX)
+ {
+ FAPI_ERR("**** ERROR : Computed pstate is greater than max pstate in gpst (computed pstate = %d max pstate = %d rc = %d",
+ pstate, gpst_pmax(&(pss->gpst)), rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PFLOOR_GT_GPSTPMAX_ERROR);
+ }
+ else
+ {
+ FAPI_ERR("**** ERROR : Bad Return code rc = %d", rc );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_PFLOOR_ERROR);
+ }
+ }
+
+ return l_rc;
+ } // end proc_upd_floor_ps
+
+/// ------------------------------------------------------------
+/// \brief Populate a subset of the WOFElements structure from Attributes
+/// \param[inout] *pss => pointer to pstate superstructure
+/// \param[in] *attr => pointer to attribute list structure
+/// ------------------------------------------------------------
+
+ ReturnCode load_wof_attributes (PstateSuperStructure *pss,
+ const AttributeList *attr)
+ {
+
+
+ // -----------------------------------------------
+ // ATTR_WOF_ENABLED setting
+ // -----------------------------------------------
+ pss->wof.wof_enabled = attr->attr_wof_enabled;
+
+ // -----------------------------------------------
+ // ATTR_TDP_RDP_CURRENT_FACTOR value
+ // -----------------------------------------------
+ pss->wof.tdp_rdp_factor = attr->attr_tdp_rdp_current_factor;
+
+ // -----------------------------------------------
+ // System Power Distribution value
+ // -----------------------------------------------
+
+ pss->wof.vdd_sysparm.loadline_uohm = attr->attr_proc_r_loadline_vdd;
+ pss->wof.vcs_sysparm.loadline_uohm = attr->attr_proc_r_loadline_vcs;
+ pss->wof.vdd_sysparm.distloss_uohm = attr->attr_proc_r_distloss_vdd;
+ pss->wof.vcs_sysparm.distloss_uohm = attr->attr_proc_r_distloss_vcs;
+ pss->wof.vdd_sysparm.distoffset_uv = attr->attr_proc_vrm_voffset_vdd;
+ pss->wof.vcs_sysparm.distoffset_uv = attr->attr_proc_vrm_voffset_vcs;
+
+ return FAPI_RC_SUCCESS;
+
+ } // end load_wof_attributes
+
+
+/// ------------------------------------------------------------
+/// \brief Copy VPD operating point into destination in assending order
+/// \param[in] &src[VPD_PV_POINTS] => reference to source VPD structure (array)
+/// \param[out] *dest[VPD_PV_POINTS] => pointer to destination VpdOperatingPoint structure
+/// ------------------------------------------------------------
+
+ ReturnCode load_mvpd_operating_point (const uint32_t src[PV_D][PV_W],
+ VpdOperatingPoint *dest)
+ {
+
+ const uint8_t pv_op_order[S132A_POINTS] = PV_OP_ORDER;
+
+ for (uint32_t i = 0; i < S132A_POINTS; i++)
+ {
+ dest[i].frequency_mhz = src[pv_op_order[i]][0];
+ dest[i].vdd_5mv = src[pv_op_order[i]][1];
+ dest[i].idd_500ma = src[pv_op_order[i]][2];
+ dest[i].vdd_maxreg_5mv = src[pv_op_order[i]][1] - DEAD_ZONE_5MV;
+ dest[i].vcs_5mv = src[pv_op_order[i]][3];
+ dest[i].ics_500ma = src[pv_op_order[i]][4];
+ dest[i].vcs_maxreg_5mv = src[pv_op_order[i]][3] - DEAD_ZONE_5MV;
+ }
- return l_rc;
-} // end proc_upd_floor_ps
+ return FAPI_RC_SUCCESS;
+ } // end attr2wof
} //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 d5447810e..512943d7c 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
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,7 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: p8_build_pstate_datablock.H,v 1.14 2014/05/27 15:33:49 daviddu Exp $
+// $Id: p8_build_pstate_datablock.H,v 1.15 2015/05/13 03:12:36 stillgs Exp $
#ifndef _P8_BUILD_PSTATE_DATABLOCK_H_
#define _P8_BUILD_PSTATE_DATABLOCK_H_
@@ -38,29 +40,40 @@ extern "C" {
/// \param[in] i_target Chip Target
/// \param[in/out] *io_pss Reference to PstateSuperStructure
-fapi::ReturnCode p8_build_pstate_datablock(const fapi::Target& i_target, PstateSuperStructure *io_pss);
+fapi::ReturnCode
+p8_build_pstate_datablock(const fapi::Target& i_target, PstateSuperStructure *io_pss);
} // extern "C"
-#define S132A_POINTS 3
+#define S132A_POINTS 4
#define PSTATE_STEPSIZE 1
#define EVRM_DELAY_NS 100
-#define DEAD_ZONE_5MV 20
+#define DEAD_ZONE_5MV 20 // 100mV
#define PDV_BUFFER_SIZE 51
-#define PDM_BUFFER_SIZE 105
+#define PDV_BUFFER_ALLOC 512
+
+//#define PDM_BUFFER_SIZE 105
+#define PDM_BUFFER_SIZE 257 // Value is for version 3 @ 256 + 1 for version number
+#define PDM_BUFFER_ALLOC 513 // Value is for version 2 @ 512 + 1 for version number
#define BIAS_PCT_UNIT 0.005
#define BOOST_PCT_UNIT 0.001
#define POUNDM_POINTS 13
+#define POUNDM_MEASUREMENTS_PER_POINT 4
// #V 2 dimensional array values (5x5) - 5 operating point and 5 values per operating point
#define PV_D 5
#define PV_W 5
// order of operating points from slow to fast in #V
-// 1=pwrsave 0=nominal 2=turbo
-#define PV_OP_ORDER {1, 0, 2}
-#define PV_OP_ORDER_STR {"nominal", "powersave", "turbo"}
-
+// 1=pwrsave 0=nominal 2=turbo. 3=ultraturbo
+#define PV_OP_ORDER {1, 0, 2, 3}
+#define PV_OP_ORDER_STR {"Nominal", "PowerSave", "Turbo", "UltraTurbo"}
+#define PV_OP_ORDER_MIN_VALID {1, 1, 1, 0}
+
+// IQ Keyword Sizes
+#define IQ_BUFFER_SIZE 9
+#define IQ_BUFFER_ALLOC 64
+
typedef struct {
uint32_t attr_freq_core_max;
uint32_t attr_proc_r_loadline_vdd;
@@ -106,6 +119,9 @@ typedef struct {
uint8_t attr_chip_ec_feature_ivrm_winkle_bug;
uint8_t attr_pm_system_ivrms_enabled;
uint8_t attr_pm_system_ivrm_vpd_min_level;
+
+ uint8_t attr_wof_enabled;
+ uint32_t attr_tdp_rdp_current_factor;
} AttributeList;
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 92800bfb5..867196d34 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
@@ -5,7 +5,7 @@
<!-- -->
<!-- OpenPOWER HostBoot Project -->
<!-- -->
-<!-- Contributors Listed Below - COPYRIGHT 2013,2014 -->
+<!-- Contributors Listed Below - COPYRIGHT 2013,2015 -->
<!-- [+] International Business Machines Corp. -->
<!-- -->
<!-- -->
@@ -22,7 +22,7 @@
<!-- permissions and limitations under the License. -->
<!-- -->
<!-- IBM_PROLOG_END_TAG -->
-<!-- $Id: p8_build_pstate_datablock_errors.xml,v 1.13 2014/07/22 21:46:56 daviddu Exp $ -->
+<!-- $Id: p8_build_pstate_datablock_errors.xml,v 1.14 2015/05/13 02:56:56 stillgs Exp $ -->
<!-- Error definitions for p8_build_pstate_datablock procedure -->
<hwpErrors>
<!-- *********************************************************************** -->
@@ -449,5 +449,109 @@
<priority>HIGH</priority>
</callout>
</hwpError>
- <!-- *********************************************************************** -->
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_IQ_BUFFER_SIZE_ERROR</rc>
+ <description>IQ Buffer returned is wrong size</description>
+ <ffdc>BUFFER_SIZE</ffdc>
+ <callout>
+ <target>CHIP_TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>LOW</priority>
+ </callout>
+ <deconfigure>
+ <target>CHIP_TARGET</target>
+ </deconfigure>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_IQ_MVPD_ERROR</rc>
+ <description>LRPx access for IQ keyword failed</description>
+ <ffdc>CHIPLET_NUMBER</ffdc>
+ <callout>
+ <target>CHIP_TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>LOW</priority>
+ </callout>
+ <deconfigure>
+ <target>CHIP_TARGET</target>
+ </deconfigure>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_IQ_INVALID_VDD_ERROR</rc>
+ <description>IDDQ measurement for VDD was invalid (eg zero)</description>
+ <ffdc>RAW_VALUE</ffdc>
+ <ffdc>LRP_NUMBER</ffdc>
+ <callout>
+ <target>CHIP_TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>LOW</priority>
+ </callout>
+ <deconfigure>
+ <target>CHIP_TARGET</target>
+ </deconfigure>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_IQ_INVALID_VCS_ERROR</rc>
+ <description>IDDQ measurement for VCS was invalid (eg zero)</description>
+ <ffdc>RAW_VALUE</ffdc>
+ <ffdc>LRP_NUMBER</ffdc>
+ <callout>
+ <target>CHIP_TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>LOW</priority>
+ </callout>
+ <deconfigure>
+ <target>CHIP_TARGET</target>
+ </deconfigure>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_IQ_INVALID_VIO_ERROR</rc>
+ <description>IDDQ measurement for VIO was invalid (eg zero)</description>
+ <ffdc>RAW_VALUE</ffdc>
+ <callout>
+ <target>CHIP_TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>LOW</priority>
+ </callout>
+ <deconfigure>
+ <target>CHIP_TARGET</target>
+ </deconfigure>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_PDV_ZERO_DATA_UT_ERROR</rc>
+ <description>Zero valued data found in #V for UltraTubro point. Continuing
+ Pstate generation</description>
+ <ffdc>OP_POINT</ffdc>
+ <ffdc>CHIPLET_NUM</ffdc>
+ <ffdc>BUCKET_ID</ffdc>
+ <callout>
+ <target>CHIP_TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>LOW</priority>
+ </callout>
+ </hwpError>
+ <!-- *********************************************************************** -->
</hwpErrors>
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c
index 2a57af50a..5518b3954 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -22,7 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: pstate_tables.c,v 1.22 2014/07/03 02:57:52 daviddu Exp $
+// $Id: pstate_tables.c,v 1.26 2015/08/20 17:04:06 stillgs Exp $
/// \file pstate_tables.c
/// \brief This file contains code used to generate Pstate tables from real or
@@ -32,14 +32,53 @@
/// 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) \
+
+// Debugging support, normally disabled. All of the formatted I/O you see in
+// the code is effectively under this switch.
+
+#ifdef __FAPI
+
+#include "fapi.H"
+#define fprintf(stream, ...) FAPI_ERR(__VA_ARGS__)
+#define printf(...) FAPI_INF(__VA_ARGS__)
+#define TRACE_NEWLINE ""
+
+#else // __FAPI
+
+#include <stdio.h>
+#define fprintf(stream, ...) printf("***ERROR*** " __VA_ARGS__)
+#define TRACE_NEWLINE "\n"
+
+#endif // __FAPI
+
+#define TRACE_ERROR(x) \
+ ({ \
+ fprintf(stderr, "%s:%d : Returning error code %d " TRACE_NEWLINE, \
+ __FILE__, __LINE__, (x)); \
+ (x); \
+ })
+
+#define TRACE_ERRORX(x, ...) \
({ \
+ TRACE_ERROR(x); \
+ fprintf(stderr, ##__VA_ARGS__); \
+ (x); \
+ })
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX(X, Y) \
+ ({ \
typeof (X) __x = (X); \
typeof (Y) __y = (Y); \
(__x > __y) ? __x : __y; \
@@ -122,6 +161,7 @@ revle64(const uint64_t i_x)
return rx;
}
+
/// Create a ChipCharacterization from an array of VPD operating points and
/// characterization parameters.
///
@@ -149,16 +189,17 @@ chip_characterization_create(ChipCharacterization *characterization,
VpdOperatingPoint *vpd,
OperatingPoint *ops,
OperatingPointParameters *parameters,
- int points)
+ uint32_t points)
{
int rc;
- uint8_t i;
+ uint32_t i, c;
uint32_t pstate0_code;
- uint8_t gpst_points = 0; // jwy
- uint32_t curr_pstate_code = 0; // jwy
- uint32_t next_pstate_code = 0; // jwy
+ uint8_t gpst_points = 0;
+ uint32_t curr_pstate_code = 0;
+ uint32_t next_pstate_code = 0;
+ uint32_t max_cores = 0;
+
-
do {
rc = 0;
@@ -167,7 +208,8 @@ chip_characterization_create(ChipCharacterization *characterization,
break;
}
if ((vpd == 0) || (points <= 0)) {
- rc = -GPST_INVALID_ARGUMENT;
+ rc = TRACE_ERRORX(-GPST_INVALID_ARGUMENT,
+ "vpd & points");
break;
}
@@ -176,6 +218,8 @@ chip_characterization_create(ChipCharacterization *characterization,
characterization->parameters = parameters;
characterization->points = points;
+ max_cores = characterization->max_cores;
+
// Now convert the array of VPD operating point to the array of
// internal operating points
//
@@ -194,19 +238,19 @@ chip_characterization_create(ChipCharacterization *characterization,
for (i = 0; i < points; i++) {
- // jwy skip vpd point if next point is at same pstate
+ // Skip vpd point if next point is at same pstate
curr_pstate_code = vpd[i].frequency_mhz * 1000 / parameters->frequency_step_khz;
- if (i < points - 1) {
+ if (i < points-1) {
next_pstate_code = vpd[i+1].frequency_mhz * 1000 / parameters->frequency_step_khz;
}
-
- if (i < points - 1 && (curr_pstate_code == next_pstate_code)) {
+
+ if (i < points-1 && (curr_pstate_code == next_pstate_code)) {
continue;
}
-
+
ops[gpst_points].vdd_uv = vpd[i].vdd_5mv * 5000;
ops[gpst_points].vcs_uv = vpd[i].vcs_5mv * 5000;
-
+
ops[gpst_points].vdd_maxreg_uv = vpd[i].vdd_maxreg_5mv * 5000;
ops[gpst_points].vcs_maxreg_uv = vpd[i].vcs_maxreg_5mv * 5000;
@@ -214,17 +258,17 @@ chip_characterization_create(ChipCharacterization *characterization,
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
ops[gpst_points].vdd_corrected_uv =
ops[gpst_points].vdd_uv +
- ((ops[gpst_points].idd_ma * (parameters->vdd_load_line_uohm + parameters->vdd_distribution_uohm)) / 1000) + // jwy add in distribution_uohm
+ ((ops[gpst_points].idd_ma * (parameters->vdd_load_line_uohm + parameters->vdd_distribution_uohm)) / 1000) +
parameters->vdd_voffset_uv; // SW267784 add in offset in uohm
ops[gpst_points].vcs_corrected_uv =
ops[gpst_points].vcs_uv +
- ((ops[gpst_points].ics_ma * (parameters->vcs_load_line_uohm + parameters->vcs_distribution_uohm)) / 1000) + // jwy add in distribution_uohm
+ ((ops[gpst_points].ics_ma * (parameters->vcs_load_line_uohm + parameters->vcs_distribution_uohm)) / 1000) +
parameters->vcs_voffset_uv; // SW267784 add in offset in uohm
// iVRM 'Effective' voltages are set to the measured voltages
@@ -236,11 +280,107 @@ chip_characterization_create(ChipCharacterization *characterization,
(ops[gpst_points].frequency_khz / parameters->frequency_step_khz) -
pstate0_code;
+ // For WOF, compute the "per active core" point set based on ratioing
+ // the current at the operating point in a linear fashion. The ratio
+ // is only computed for up to the number of cores present on this chip
+ // as the current contained in the VPD is measured with only that number
+ // of cores active.
+ if (i == TURBO || i == ULTRA)
+ {
+ for (c = 0; c < max_cores; ++c)
+ {
+ double ratio = (double)(c+1)/max_cores;
+ double idd_currentf_ma = (double)ops[gpst_points].idd_ma;
+ uint32_t idd_current_ratioed_ma = (uint32_t)(idd_currentf_ma * ratio + 0.5); // round up
+ uint32_t vdd_impedance_uohm = parameters->vdd_load_line_uohm + parameters->vdd_distribution_uohm;
+
+ uint32_t vdd_dist_uplift_uv =
+ (uint32_t)( idd_current_ratioed_ma *
+ ((double)vdd_impedance_uohm/1000));
+
+ ops[gpst_points].vdd_corrected_wof_uv[c] =
+ ops[gpst_points].vdd_uv + // Base Point with bias but no system effects
+ vdd_dist_uplift_uv + // Distribution loss based on apportioned current
+ parameters->vdd_voffset_uv; // Offset present
+
+ printf( "ops[%d].vdd_uv = %u "
+ "ratio = %f "
+ "id_ma = %6.0f "
+ "current ratioed_ma = %d "
+ "load line = %d "
+ "dist loss = %d "
+ "dist impedance uohm %d "
+ "dist uplift %d uV "
+ "dist offset %d uV "
+ "ops[%d].vdd_corrected_wof_uv[%u] = %u" TRACE_NEWLINE,
+ gpst_points, ops[gpst_points].vdd_uv,
+ ratio,
+ idd_currentf_ma,
+ idd_current_ratioed_ma,
+ parameters->vdd_load_line_uohm,
+ parameters->vdd_distribution_uohm,
+ vdd_impedance_uohm,
+ vdd_dist_uplift_uv,
+ parameters->vdd_voffset_uv,
+ gpst_points, c, ops[gpst_points].vdd_corrected_wof_uv[c]);
+
+ double ics_currentf_ma = (double)ops[gpst_points].ics_ma;
+ uint32_t ics_current_ratioed_ma = (uint32_t)(ics_currentf_ma * ratio + 0.5); // round up
+
+ uint32_t vcs_impedance_uohm = parameters->vcs_load_line_uohm + parameters->vcs_distribution_uohm;
+
+ uint32_t vcs_dist_uplift_uv =
+ (uint32_t)( ics_current_ratioed_ma *
+ ((double)vcs_impedance_uohm/1000));
+
+ ops[gpst_points].vcs_corrected_wof_uv[c] =
+ ops[gpst_points].vcs_uv + // Base Point with bias but no system effects
+ vcs_dist_uplift_uv + // Distribution loss based on apportioned current
+ parameters->vcs_voffset_uv; // Offset present
+
+ printf( "ops[%d].vcs_uv = %u "
+ "ratio = %f "
+ "id_ma = %6.0f "
+ "current ratioed_ma = %d "
+ "load line = %d "
+ "dist loss = %d "
+ "dist impedance %d "
+ "dist uplift %d uV "
+ "dist offset %d UV "
+ "ops[%d].vcs_corrected_wof_uv[%u] = %u" TRACE_NEWLINE,
+ gpst_points, ops[gpst_points].vcs_uv,
+ ratio,
+ ics_currentf_ma,
+ ics_current_ratioed_ma,
+ parameters->vcs_load_line_uohm,
+ parameters->vcs_distribution_uohm,
+ ((parameters->vcs_load_line_uohm +
+ parameters->vcs_distribution_uohm)),
+ vcs_dist_uplift_uv,
+ parameters->vcs_voffset_uv,
+ gpst_points, c, ops[gpst_points].vcs_corrected_wof_uv[c]);
+ }
+ }
+
+ printf("gpst_points %u "
+ "ops[gpst_points].vdd_uv = %u "
+ "ops[gpst_points].vcs_uv = %u "
+ "ops[gpst_points].vdd_maxreg_uv = %u "
+ "ops[gpst_points].vcs_maxreg_uv = %u "
+ "ops[gpst_points].idd_ma = %u "
+ "ops[gpst_points].ics_ma = %u" TRACE_NEWLINE,
+ gpst_points,
+ ops[gpst_points].vdd_uv,
+ ops[gpst_points].vcs_uv,
+ ops[gpst_points].vdd_maxreg_uv,
+ ops[gpst_points].vcs_maxreg_uv,
+ ops[gpst_points].idd_ma,
+ ops[gpst_points].ics_ma);
gpst_points++;
}
-
- // jwy set points to adjusted number of points (ie. if vpd point was skipped due to being same pstate
- // jwy as next vpd point
+
+ // Set points to adjusted number of points (ie. if vpd point was skipped due to being same pstate
+ // as next vpd point
characterization->points = gpst_points;
} while (0);
@@ -292,7 +432,8 @@ gpst_stepping_setup(GlobalPstateTable* gpst,
(pstate_stepsize > PSTATE_STEPSIZE_MAX) ||
(vrm_delay_ns < 0) ||
(vrm_delay_ns > VRM_STEPDELAY_MAX)) {
- rc = -GPST_INVALID_ARGUMENT;
+ rc = TRACE_ERRORX(-GPST_INVALID_ARGUMENT,
+ "pstate_stepsize");
break;
}
@@ -306,7 +447,7 @@ gpst_stepping_setup(GlobalPstateTable* gpst,
// Normalize the exponential encoding
sigbits = 32 - cntlz32(cycles);
-
+
stepdelay_range = (sigbits - VRM_STEPDELAY_RANGE_BITS);
if (stepdelay_range < 0)
@@ -317,7 +458,8 @@ gpst_stepping_setup(GlobalPstateTable* gpst,
stepdelay_value = cycles >> (stepdelay_range + LOG2_VRM_STEPDELAY_DIVIDER);
if (stepdelay_range > ((1u << VRM_STEPDELAY_RANGE_BITS) - 1)) {
- rc = -GPST_INVALID_ARGUMENT;
+ rc = TRACE_ERRORX(-GPST_INVALID_ARGUMENT,
+ "stepdelay_range");
break;
}
@@ -370,15 +512,15 @@ gpst_entry_create(gpst_entry_t *entry, OperatingPoint *op)
if (rc) break; \
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_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);
+
+ ;
- ;
-
// Add the check byte
uint8_t gpstCheckByte(uint64_t gpstEntry);
@@ -393,6 +535,45 @@ gpst_entry_create(gpst_entry_t *entry, OperatingPoint *op)
}
+int
+vid_mod_entry_create(WOFElements *wof, uint32_t index, uint32_t core, OperatingPoint *op)
+{
+ int rc = 0;
+ uint8_t vid;
+
+ do {
+
+
+#define __SETVM(type, round, wof_field, op_field) \
+ rc = vuv2##type(op->op_field, round, &vid); \
+ if (rc) \
+ { \
+ fprintf(stderr, " SETVM error: op_field = %u; vid = %u" TRACE_NEWLINE, op->op_field, vid); \
+ break; \
+ } \
+ wof->ut_vid_mod.wof_field = vid; \
+
+ __SETVM(vrm11, ROUND_VOLTAGE_UP, ut_segment_vdd_vid[index][core], vdd_corrected_wof_uv[core]);
+
+ printf(" op->vdd_corrected_wof_uv[%d] = %u; wof->ut_vid_mod.ut_segment_vdd_vid[%d][%d] = 0x%02X" TRACE_NEWLINE,
+ core, op->vdd_corrected_wof_uv[core],
+ index, core, wof->ut_vid_mod.ut_segment_vdd_vid[index][core]);
+
+ __SETVM(vrm11, ROUND_VOLTAGE_UP, ut_segment_vcs_vid[index][core], vcs_corrected_wof_uv[core]);
+
+
+
+ printf(" op->vcs_corrected_wof_uv[%d] = %u; wof->ut_vid_mod.ut_segment_vcs_vid[%d][%d] = 0x%02X" TRACE_NEWLINE,
+ core, op->vcs_corrected_wof_uv[core],
+ index, core, wof->ut_vid_mod.ut_segment_vcs_vid[index][core]);
+
+ } while (0);
+
+ return rc;
+}
+
+
+
// Linear interpolation of voltages
static uint32_t
@@ -441,15 +622,19 @@ interpolate(uint32_t base, uint32_t next, int step, int steps)
int
gpst_create(GlobalPstateTable *gpst,
- ChipCharacterization *characterization,
+ ChipCharacterization *characterization,
+ WOFElements *wof,
int pstate_stepsize,
int evrm_delay_ns)
{
OperatingPoint *ops, interp;
- int rc, points;
- int32_t entry;
+ int rc;
+ uint32_t points, pstates_ut = 0;
+ int32_t entry, entry_turbo;
int32_t pmin, pmax, pstate;
- uint8_t fNom, i;
+ uint8_t fNom;
+ uint32_t i, c, max_cores;
+ gpst_entry_t gpst_entry_temp;
do {
rc = 0;
@@ -463,8 +648,9 @@ gpst_create(GlobalPstateTable *gpst,
// Check for null or illegal operating point tables
- ops = characterization->ops;
- points = characterization->points;
+ ops = characterization->ops;
+ points = characterization->points;
+ max_cores = characterization->max_cores;
if ((ops == 0) || (points <= 0)) {
rc = -GPST_INVALID_OBJECT;
@@ -473,6 +659,8 @@ gpst_create(GlobalPstateTable *gpst,
pmin = ops[0].pstate;
pmax = ops[points - 1].pstate;
+ printf("**** Check : pmin %x, pmax %x" TRACE_NEWLINE,
+ pmin, pmax);
// Check that the range of Pstates are legal and will actually fit in
// the table. 'Fitting' will never be a problem for PgP as long as the
@@ -482,18 +670,36 @@ gpst_create(GlobalPstateTable *gpst,
if ((pmin < PSTATE_MIN) ||
(pmax > PSTATE_MAX) ||
((pmax - pmin + 1) > GLOBAL_PSTATE_TABLE_ENTRIES)) {
- rc = -GPST_INVALID_ARGUMENT;
+ rc = TRACE_ERRORX(-GPST_INVALID_ARGUMENT,
+ "pmin %x, PSTATE_MIN %x; pmax %x, PSTATE_MAX %x; pmax - pmin + 1 %x, GLOBAL_PSTATE_TABLE_ENTRIES %x" TRACE_NEWLINE,
+ pmin,
+ PSTATE_MIN,
+ pmax,
+ PSTATE_MAX,
+ pmax - pmin + 1,
+ GLOBAL_PSTATE_TABLE_ENTRIES
+ );
break;
}
// Check the ordering constraints
for (i = 1; i < points; i++) {
-
+
if ((ops[i].pstate < ops[i - 1].pstate) ||
- (ops[i].vdd_uv < ops[i - 1].vdd_uv) || // jwy allow them to be equal
- (ops[i].vcs_uv < ops[i - 1].vcs_uv)) { // jwy allow them to be equal
- rc = -GPST_INVALID_ARGUMENT;
+ (ops[i].vdd_uv < ops[i - 1].vdd_uv) | // allow them to be equal
+ (ops[i].vcs_uv < ops[i - 1].vcs_uv)) { // allow them to be equal
+ rc = TRACE_ERRORX(-GPST_INVALID_ARGUMENT,
+ "i = %u pstate %x, ops[i - 1].pstate %x; ops[i].vdd_uv %x, ops[i - 1].vdd_uv %x; ops[i].vcs_uv %x, ops[i - 1].vcs_uv %x" TRACE_NEWLINE,
+ i,
+ ops[i].pstate,
+ ops[i - 1].pstate,
+ ops[i].vdd_uv ,
+ ops[i - 1].vdd_uv,
+ ops[i].vcs_uv,
+ ops[i - 1].vcs_uv
+ );
+
break;
}
}
@@ -503,11 +709,11 @@ gpst_create(GlobalPstateTable *gpst,
// pstate0_frequency_code (fNom) to the 'nominal' code and set the
// DPLL bias to 0.
- gpst->pstate0_frequency_khz =
+ gpst->pstate0_frequency_khz =
revle32(characterization->parameters->pstate0_frequency_khz);
- gpst->frequency_step_khz =
+ gpst->frequency_step_khz =
revle32(characterization->parameters->frequency_step_khz);
-
+
// Now we can interpolate the operating points to build the
// table. Interpolation is done by creating (or using) an
// OperatingPoint for each intermediate (or characterized) Pstate.
@@ -515,25 +721,23 @@ gpst_create(GlobalPstateTable *gpst,
// the operating point. Only the voltages are interpolated, and they
// are all interpolated in units of micro-Volts.
+ // The WOF algorithm augments the interpolation between the Turbo
+ // and the UltraTurbo points to calculate a differnt segment based
+ // on the number of cores that might be active.
+
gpst->pmin = pmin;
gpst->entries = pmax - pmin + 1;
-
+
// Set the Pmin Pstate
entry = 0;
if (gpst_entry_create(&(gpst->pstate[entry]), &(ops[0]))) {
- rc = -GPST_INVALID_ENTRY;
+ rc = TRACE_ERRORX(-GPST_INVALID_ENTRY,
+ "gpst_entry_create error setting Pmin");
break;
}
entry++;
pstate = pmin;
-
- // Iterate over characterized operating points...
- for (i = 1; i < points; i++) {
-
- // Interpolate intermediate Pstates...
- while (++pstate != ops[i].pstate) {
-
- interp.pstate = pstate;
+ printf("**** Check : pstate %x" TRACE_NEWLINE, pstate);
#define __INTERPOLATE(field) \
do { \
@@ -543,27 +747,308 @@ gpst_create(GlobalPstateTable *gpst,
(ops[i].pstate - ops[i - 1].pstate)); \
} while (0)
- __INTERPOLATE(vdd_corrected_uv);
- __INTERPOLATE(vcs_corrected_uv);
- __INTERPOLATE(vdd_ivrm_effective_uv);
- __INTERPOLATE(vcs_ivrm_effective_uv);
- __INTERPOLATE(vdd_maxreg_uv);
- __INTERPOLATE(vcs_maxreg_uv);
- if (gpst_entry_create(&(gpst->pstate[entry]), &interp)) {
- rc = - GPST_INVALID_ENTRY;
- break;
+ // Iterate over characterized operating points...
+ for (i = 1; i < points; i++) {
+
+ // For WOF, handle the Turbo<>UltraTurbo segment differently
+ if (i == ULTRA) {
+
+ // Save the Turbo Pstate in the GPST structure for future reference
+ gpst->turbo_ps = ops[i-1].pstate;
+
+ printf( " Turbo -> %d", gpst->turbo_ps);
+
+ for (c = 0; c < max_cores; ++c) {
+ pstate = gpst->turbo_ps; // Start again
+ entry = entry_turbo;
+ pstates_ut = 0; // Turbo is the first pstate
+
+ // --------------------------------------------------
+ // Fill in the Turbo information in the WOF structure
+ interp.pstate = pstate;
+
+ // Compute the VID overlay values for this core count
+ __INTERPOLATE(vdd_corrected_wof_uv[c]);
+ __INTERPOLATE(vcs_corrected_wof_uv[c]);
+
+ printf( ">> Turbo UT WOF entry %u pstate %x %-2d index %d "
+ "ops[%d].vdd_corrected_wof_uv[%d] = %06d "
+ "ops[%d].vdd_corrected_wof_uv[%d] = %06d "
+ "interp.vdd_corrected_wof_uv[%d] = %06d ",
+ entry,
+ pstate, pstate,
+ pstates_ut,
+ i-1, c, ops[i-1].vdd_corrected_wof_uv[c],
+ i, c, ops[i].vdd_corrected_wof_uv[c],
+ c, interp.vdd_corrected_wof_uv[c]
+ );
+
+ // >>> Note: iVRMs are not supported as active in the Turbo
+ // to UltraTurbo segment
+ if (wof->wof_enabled)
+ {
+ printf(">>>> WOF Enabled <<<< " TRACE_NEWLINE);
+ if (vid_mod_entry_create(wof, pstates_ut, c, &interp)) {
+ rc = TRACE_ERRORX(-GPST_INVALID_ENTRY,
+ "gpst_entry_create error - vid mod interpolation");
+ break;
+ }
+ }
+
+ pstates_ut++;
+ entry++;
+
+ // --------------------------------------------------
+ // Interpolate intermediate Pstates...
+ while (++pstate != ops[i].pstate) {
+ printf("pstate = %d", pstate);
+
+ interp.pstate = pstate;
+
+ if (wof->wof_enabled)
+ {
+ // Compute the VID overlay values for this core count
+ __INTERPOLATE(vdd_corrected_wof_uv[c]);
+ __INTERPOLATE(vcs_corrected_wof_uv[c]);
+
+ printf( "UT WOF entry %u pstate %x %-2d index %d "
+ "ops[%d].vdd_corrected_wof_uv[%d] = %06d "
+ "ops[%d].vdd_corrected_wof_uv[%d] = %06d "
+ "interp.vdd_corrected_wof_uv[%d] = %06d ",
+ entry,
+ pstate, pstate,
+ pstates_ut,
+ i-1, c, ops[i-1].vdd_corrected_wof_uv[c],
+ i, c, ops[i].vdd_corrected_wof_uv[c],
+ c, interp.vdd_corrected_wof_uv[c]
+ );
+
+ // >>> Note: iVRMs are not supported as active in the Turbo
+ // to UltraTurbo segment
+
+ if (vid_mod_entry_create(wof, pstates_ut, c, &interp)) {
+ rc = TRACE_ERRORX(-GPST_INVALID_ENTRY,
+ "gpst_entry_create error - vid mod interpolation");
+ break;
+ }
+
+ // Increment VID modification table index
+ pstates_ut++;
+ }
+
+ // Compute the VIDs for this Pstate
+ __INTERPOLATE(vdd_corrected_uv);
+ __INTERPOLATE(vcs_corrected_uv);
+ __INTERPOLATE(vdd_ivrm_effective_uv);
+ __INTERPOLATE(vcs_ivrm_effective_uv);
+ __INTERPOLATE(vdd_maxreg_uv);
+ __INTERPOLATE(vcs_maxreg_uv);
+
+ // Write the Global Ptate Table if processing the
+ // maximum core count
+ if (c == max_cores-1)
+ {
+ printf(">>>> Writing GPST entry %d <<<<" TRACE_NEWLINE, entry);
+ if (gpst_entry_create(&(gpst->pstate[entry]), &interp))
+ {
+ rc = TRACE_ERRORX(-GPST_INVALID_ENTRY,
+ "gpst_entry_create error - UT interpolation");
+ break;
+ }
+
+ gpst_entry_temp.value = revle64(gpst->pstate[entry].value);
+ printf("UT entry %u pstate %x %-2d"
+ "evid_vdd = 0x%02llX (VRM-11) "
+ "evid_vcs = 0x%02llX (VRM-11) "
+ "evid_vdd_eff = 0x%02llX (iVID) "
+ "evid_vcs_eff = 0x%02llX (iVID) "
+ "maxreg_vdd = 0x%02llX (iVID) "
+ "maxreg_vcs = 0x%02llX (iVID) ",
+ entry,
+ pstate, pstate,
+ gpst_entry_temp.fields.evid_vdd,
+ gpst_entry_temp.fields.evid_vcs,
+ gpst_entry_temp.fields.evid_vdd_eff,
+ gpst_entry_temp.fields.evid_vcs_eff,
+ gpst_entry_temp.fields.maxreg_vdd,
+ gpst_entry_temp.fields.maxreg_vcs);
+
+ }
+ entry++;
+ }
+ if (rc) break;
+
+ // Set the characterized Pstate
+ if (gpst_entry_create(&(gpst->pstate[entry]), &(ops[i]))) {
+ rc = TRACE_ERRORX(-GPST_INVALID_ENTRY,
+ "gpst_entry_create error - normal UT interpolation");
+ break;
+ }
+
+ gpst_entry_temp.value = revle64(gpst->pstate[entry].value);
+ printf("UT entry %u pstate %x %-2d "
+ "evid_vdd = 0x%02llX (VRM-11) "
+ "evid_vcs = 0x%02llX (VRM-11) "
+ "evid_vdd_eff = 0x%02llX (iVID) "
+ "evid_vcs_eff = 0x%02llX (iVID) "
+ "maxreg_vdd = 0x%02llX (iVID) "
+ "maxreg_vcs = 0x%02llX (iVID) ",
+ entry,
+ pstate, pstate,
+ gpst_entry_temp.fields.evid_vdd,
+ gpst_entry_temp.fields.evid_vcs,
+ gpst_entry_temp.fields.evid_vdd_eff,
+ gpst_entry_temp.fields.evid_vcs_eff,
+ gpst_entry_temp.fields.maxreg_vdd,
+ gpst_entry_temp.fields.maxreg_vcs);
+
+ if (wof->wof_enabled)
+ {
+ // Fill in the UltraTurbo information in the WOF structure
+ interp.pstate = pstate;
+
+ // Compute the VID overlay values for this core count
+ __INTERPOLATE(vdd_corrected_wof_uv[c]);
+ __INTERPOLATE(vcs_corrected_wof_uv[c]);
+
+ printf( ">> UltraTurbo UT WOF entry %u pstate %x %-2d index %d "
+ "ops[%d].vdd_corrected_wof_uv[%d] = %06d "
+ "ops[%d].vdd_corrected_wof_uv[%d] = %06d "
+ "interp.vdd_corrected_wof_uv[%d] = %06d " TRACE_NEWLINE,
+ entry,
+ pstate, pstate,
+ pstates_ut,
+ i-1, c, ops[i-1].vdd_corrected_wof_uv[c],
+ i, c, ops[i].vdd_corrected_wof_uv[c],
+ c, interp.vdd_corrected_wof_uv[c]
+ );
+
+ // >>> Note: iVRMs are not supported as active in the Turbo
+ // to UltraTurbo segment
+
+ if (vid_mod_entry_create(wof, pstates_ut, c, &interp)) {
+ rc = TRACE_ERRORX(-GPST_INVALID_ENTRY,
+ "gpst_entry_create error - vid mod interpolation");
+ break;
+ }
+
+ // Save the UltraTurbo segment Pstate count
+ wof->ut_vid_mod.ut_segment_pstates = pstates_ut;
+
+ // Save the maximum core count
+ wof->ut_vid_mod.ut_max_cores = max_cores;
+
+ printf( "UT WOF entry %u pstate %x index %d "
+ "wof->ut_vid_mod.ut_segment_vcs_vid[%d][%d] = 0x%02X "
+ "ops[%d].vdd_corrected_uv %d UltraTurbo",
+ entry,
+ pstate,
+ pstates_ut,
+ pstates_ut, c, wof->ut_vid_mod.ut_segment_vdd_vid[pstates_ut][c],
+ i, ops[i].vdd_corrected_uv
+ );
+ }
+ entry++;
}
- entry++;
+
}
- if (rc) break;
+ else
+ {
- // Set the characterized Pstate
- if (gpst_entry_create(&(gpst->pstate[entry]), &(ops[i]))) {
- rc = -GPST_INVALID_ENTRY;
- break;
+ // Save the PowerSave and Nominal Pstate in the GPST structure for future reference
+ // Get update for each point;
+
+ if (i == NOMINAL)
+ {
+ gpst->nominal_ps = ops[i].pstate;
+ printf( " Nominal Pstate -> %d", gpst->nominal_ps);
+
+ gpst->powersave_ps = ops[i-1].pstate;
+ printf( " PowerSave Pstate -> %d", gpst->powersave_ps);
+ }
+
+ // Interpolate intermediate Pstates...
+ while (++pstate != ops[i].pstate) {
+
+ interp.pstate = pstate;
+
+ __INTERPOLATE(vdd_corrected_uv);
+ __INTERPOLATE(vcs_corrected_uv);
+ __INTERPOLATE(vdd_ivrm_effective_uv);
+ __INTERPOLATE(vcs_ivrm_effective_uv);
+ __INTERPOLATE(vdd_maxreg_uv);
+ __INTERPOLATE(vcs_maxreg_uv);
+
+ if (gpst_entry_create(&(gpst->pstate[entry]), &interp)) {
+ rc = TRACE_ERRORX(-GPST_INVALID_ENTRY,
+ "gpst_entry_create error - normal interpolation");
+ break;
+ }
+
+ gpst_entry_temp.value = revle64(gpst->pstate[entry].value);
+ printf( "Non UT entry %u pstate %x %-2d "
+ "evid_vdd = 0x%02llX (VRM-11) "
+ "evid_vcs = 0x%02llX (VRM-11) "
+ "evid_vdd_eff = 0x%02llX (iVID) "
+ "evid_vcs_eff = 0x%02llX (iVID) "
+ "maxreg_vdd = 0x%02llX (iVID) "
+ "maxreg_vcs = 0x%02llX (iVID) ",
+ entry,
+ pstate, pstate,
+ gpst_entry_temp.fields.evid_vdd,
+ gpst_entry_temp.fields.evid_vcs,
+ gpst_entry_temp.fields.evid_vdd_eff,
+ gpst_entry_temp.fields.evid_vcs_eff,
+ gpst_entry_temp.fields.maxreg_vdd,
+ gpst_entry_temp.fields.maxreg_vcs);
+
+ entry++;
+ }
+ if (rc) break;
+
+ // Set the characterized Pstate
+ if (gpst_entry_create(&(gpst->pstate[entry]), &(ops[i]))) {
+ rc = -GPST_INVALID_ENTRY;
+ break;
+ }
+
+ gpst_entry_temp.value = revle64(gpst->pstate[entry].value);
+ printf( ">> VPD Point Non UT entry %u pstate %x %-2d "
+ "evid_vdd = 0x%02llX (VRM-11) "
+ "evid_vcs = 0x%02llX (VRM-11) "
+ "evid_vdd_eff = 0x%02llX (iVID) "
+ "evid_vcs_eff = 0x%02llX (iVID) "
+ "maxreg_vdd = 0x%02llX (iVID) "
+ "maxreg_vcs = 0x%02llX (iVID) ",
+ entry,
+ pstate, pstate,
+ gpst_entry_temp.fields.evid_vdd,
+ gpst_entry_temp.fields.evid_vcs,
+ gpst_entry_temp.fields.evid_vdd_eff,
+ gpst_entry_temp.fields.evid_vcs_eff,
+ gpst_entry_temp.fields.maxreg_vdd,
+ gpst_entry_temp.fields.maxreg_vcs);
+
+ // The iVRM maximum pstate is set for each characterization point
+ // as the points are traversed. The last one processed by this
+ // clause is Turbo. As iVRMs are not engaged at the Turbo point
+ // itself, subtract 1.
+ gpst->ivrm_max_ps = ops[i].pstate - 1;
+ printf( " ivrm Pstate -> %d Op Point Pstate%d" TRACE_NEWLINE, gpst->ivrm_max_ps, ops[i].pstate);
+
+ // Set the number of entries from Psave to the iVRM maximum
+ // (Turbo Pstate - 1)
+ gpst->ivrm_entries = entry - 1;
+
+ // Save the entry for the post Turbo clause. Written for each iteration.
+ // Only the last one written matters
+ entry_turbo = entry;
+
+ printf( " entry_turbo -> %d" TRACE_NEWLINE, entry_turbo);
+
+ entry++;
}
- entry++;
}
if (rc) break;
@@ -578,7 +1063,7 @@ gpst_create(GlobalPstateTable *gpst,
gpst->pstate0_frequency_code[i] = revle16(fNom);
gpst->dpll_fmax_bias[i] = 0;
}
-
+
// Hardcode the vrm delay settings for GA1
// This should be set by gpst_stepping_setup() in the future.
gpst->pstate_stepsize = pstate_stepsize;
@@ -592,328 +1077,339 @@ gpst_create(GlobalPstateTable *gpst,
}
-/// Create a local Pstate table
+/// Create a local Pstate table
///
-/// \param gpst A pointer to a GlobalPstateTable structure for lookup.
+/// \param gpst A pointer to a GlobalPstateTable structure for lookup.
///
-/// \param lpsa Apointer to a LocalPstateArray structure to populate
+/// \param lpsa A pointer 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
+/// 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
+/// \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,
- double volt_int_vdd_bias,
+lpst_create(const GlobalPstateTable *gpst,
+ LocalPstateArray *lpsa,
+ const uint8_t dead_zone_5mv,
+ double volt_int_vdd_bias,
double volt_int_vcs_bias,
uint8_t *vid_incr_gt7_nonreg)
-{
- int rc = 0;
+{
+ int rc = 0;
int8_t i;
uint8_t j;
gpst_entry_t entry;
- uint32_t turbo_uv;
- uint32_t gpst_uv;
- uint32_t v_uv;
- uint32_t vdd_uv;
+ uint32_t turbo_uv;
+ uint32_t gpst_uv;
+ uint32_t v_uv;
+ uint32_t vdd_uv;
uint8_t v_ivid;
uint8_t gpst_ivid;
- uint8_t lpst_max_found = 0;
- uint32_t lpst_max_uv;
- uint8_t lpst_entries;
- uint8_t lpst_entries_div4;
- uint8_t gpst_index;
+ uint8_t 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_pstate;
- Pstate lpst_max_pstate = 0;
- uint8_t vid_incr[3] = {0,0,0};
+ 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 steps_below_curr;
uint8_t inc_step;
uint8_t dec_step;
-
+
do {
-
- // Basic pointer checks
+
+ // Basic pointer checks
if ((gpst == 0) || (lpsa == 0)) {
- rc = -LPST_INVALID_OBJECT;
- break;
- }
+ 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 = ivid2vuv(entry.fields.evid_vdd_eff, &turbo_uv); if (rc) break;
-
+
+ entry.value = revle64(gpst->pstate[(gpst->ivrm_entries)].value);
+ rc = ivid2vuv(entry.fields.evid_vdd_eff, &turbo_uv); if (rc) break;
+
+ printf("gpst->ivrm_entries = %u, turbo_uv = %u", gpst->ivrm_entries, turbo_uv);
+
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);
+ lpst_max_uv = turbo_uv - (dead_zone_5mv * 5000);
+
+ for (i = gpst->ivrm_entries ; i >= 0; i--) {
+ entry.value = revle64(gpst->pstate[i].value);
rc = ivid2vuv(entry.fields.evid_vdd_eff, &v_uv); if (rc) break;
- v_uv = (uint32_t) (v_uv * volt_int_vdd_bias);
-
+ v_uv = (uint32_t) (v_uv * volt_int_vdd_bias);
+
if (lpst_max_uv >= v_uv) {
lpst_max_found = 1;
lpst_max_pstate = gpst_pmax(gpst) - (gpst->entries - i - 1);
+ printf("lpst_max_pstate = %x" TRACE_NEWLINE, lpst_max_pstate);
break;
- }
+ }
}
-
- if (rc) break;
-
- // generate a warning if lpst max not found
+
+ 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;
+ break;
}
-
- lpst_entries = gpst->entries;
+
+ lpst_entries = gpst->ivrm_entries;
lpst_pmin = gpst->pmin;
-
+
+ printf("lpst_entries = %u" TRACE_NEWLINE, lpst_entries);
// ----------------------------------------------------------------------------
// now loop over gpst from 0 to lpst_entries and fill in lpst from data in gpst
// ----------------------------------------------------------------------------
gpst_index = 0;
- lpst_entries_div4 = lpst_entries/4;
+ lpst_entries_div4 = lpst_entries/4;
if ( lpst_entries % 4 != 0)
lpst_entries_div4++;
-
- // current lpst pstate value as table is created
+
+ // current lpst pstate value as table is created
lpst_pstate = gpst_pmin(gpst);
-
+
+ printf("lpst create before loop: lpst_entries_div4 = %d" TRACE_NEWLINE, lpst_entries_div4);
for (i = 0 ; i < lpst_entries_div4; i++) {
entry.value = revle64(gpst->pstate[gpst_index].value);
-
+
// compute ivid_vdd
rc = ivid2vuv(entry.fields.evid_vdd_eff, &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 = ivid2vuv(entry.fields.evid_vcs_eff, &v_uv); if (rc) break;
- v_uv = (uint32_t) (v_uv * volt_int_vcs_bias);
+ 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;
-
+ lpsa->pstate[i].fields.ivid_vcs = v_ivid;
+
+ // --------------------------------------------------------------
+ // compute increment for remaining 3 pstates for this lpst entry
// --------------------------------------------------------------
- // compute increment for remaining 3 pstates for this lpst entry
- // --------------------------------------------------------------
- vid_incr[0] = 0;
+ vid_incr[0] = 0;
vid_incr[1] = 0;
vid_incr[2] = 0;
-
+
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 = ivid2vuv(entry.fields.evid_vdd_eff, &vdd_uv); if (rc) break;
- vdd_uv = (uint32_t) (vdd_uv * volt_int_vdd_bias);
+ 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;
-
+ vid_incr[j] = 7;
+
// if in regulation, return an error
if (lpst_pstate <= lpst_max_pstate) {
- rc = -LPST_INCR_CLIP_ERROR ;
+ rc = TRACE_ERRORX(-LPST_INCR_CLIP_ERROR,
+ "lpst clip: lpst_pstate %x lpst_max_pstate %x",
+ lpst_pstate,
+ lpst_max_pstate
+ );
break;
- }
-
+ }
+
// if not in regulation, return a warning
- if (lpst_pstate > lpst_max_pstate) {
+ if (lpst_pstate > lpst_max_pstate) {
*vid_incr_gt7_nonreg = 1;
- }
- }
-
+ }
+ }
+
}
if (rc) break;
-
- lpsa->pstate[i].fields.ps1_vid_incr = vid_incr[0];
- lpsa->pstate[i].fields.ps2_vid_incr = vid_incr[1];
- lpsa->pstate[i].fields.ps3_vid_incr = vid_incr[2];
-
+ printf("lpst create after loop" TRACE_NEWLINE);
+
+ lpsa->pstate[i].fields.ps1_vid_incr = vid_incr[0];
+ lpsa->pstate[i].fields.ps2_vid_incr = vid_incr[1];
+ lpsa->pstate[i].fields.ps3_vid_incr = vid_incr[2];
+
// --------------------
// compute power ratios
- // --------------------
+ // --------------------
float sigma = 3;
float iac_wc;
float iac;
float vout;
float pwrratio_f;
uint8_t pwrratio;
-
+
// convert to mV and subract 100 mV (note: vdd_uv is the max of the vdd values for this lpst entry)
- vout = (float)((vdd_uv/1000) - 100);
-
+ vout = (float)((vdd_uv/1000) - 100);
+
// 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
pwrratio_f = iac / iac_wc;
-
+
if (pwrratio_f >= 1.0)
pwrratio = 63;
- else
+ 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;
-
+
+ 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
+ // - 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;
- entry.value = revle64(gpst->pstate[lpst_pstate - gpst_pmin(gpst) + j].value);
+ entry.value = revle64(gpst->pstate[lpst_pstate - gpst_pmin(gpst) + j].value);
rc = ivid2vuv(entry.fields.evid_vdd_eff, &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;
- }
-
+ break;
+ }
if (rc) break;
-
- // clip inc_step
- if (inc_step > 7)
+
+ // clip inc_step
+ if (inc_step > 7)
inc_step = 7;
-
+
lpsa->pstate[i].fields.inc_step = inc_step;
// 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;
- entry.value = revle64(gpst->pstate[lpst_pstate - gpst_pmin(gpst) - j].value);
+ entry.value = revle64(gpst->pstate[lpst_pstate - gpst_pmin(gpst) - j].value);
rc = ivid2vuv(entry.fields.evid_vdd_eff, &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;
- }
-
+ break;
+ }
if (rc) break;
-
- // clip dec_step
- if (dec_step > 7)
- dec_step = 7;
-
+
+ // clip dec_step
+ if (dec_step > 7)
+ dec_step = 7;
+
lpsa->pstate[i].fields.dec_step = dec_step;
// Byte reverse the entry into the image.
lpsa->pstate[i].value = revle64(lpsa->pstate[i].value);
-
+
gpst_index++;
if (gpst_index > lpst_entries)
- break;
-
+ break;
+
// point to next lpst pstate
- lpst_pstate++;
+ lpst_pstate++;
}
- // set these fields in lpst structure
+ // set these fields in lpst structure
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
+ } while (0);
+
+ return rc;
-// This routine will fully fill out the VDS region table even if
+} // 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)
-{
+{
uint8_t 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;
-
+ 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;
-
+
// 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;
- }
+ end_offset = 127;
+ }
}
-// This routine will fully fill out the VDS region table even if
+// 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)
-{
+{
uint8_t s;
uint8_t i;
uint32_t idx;
-
+
i = i_ivrm_parms->vin_table_setsperrow;
for (i = 0; i < i_ivrm_parms->vds_region_entries; i++)
{
@@ -929,8 +1425,8 @@ fill_vin_table( ivrm_parm_data_t* i_ivrm_parms,
pss->lpsa.vdsvin[idx].fields.pfet7 = i_ivrm_parms->forced_pfetstr_value;
// Byte reverse the entry into the image.
- pss->lpsa.vdsvin[idx].value = revle64(pss->lpsa.vdsvin[idx].value);
- }
+ pss->lpsa.vdsvin[idx].value = revle64(pss->lpsa.vdsvin[idx].value);
+ }
}
}
@@ -1039,17 +1535,17 @@ void simeq(int n, double A[], double Y[], double X[])
void fit_file(int n, uint8_t version, double C[], ivrm_cal_data_t* cal_data)
{
uint8_t i, j, k;
- int points;
+ int points;
double y;
double Vd, Vs;
double x[30]; /* at least 2n */
- double A[2500];
- double Y[50];
+ 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;
@@ -1065,9 +1561,9 @@ void fit_file(int n, uint8_t version, double C[], ivrm_cal_data_t* cal_data)
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;
-
+
+ points = cal_data->point_valid;
+
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
@@ -1076,31 +1572,31 @@ void fit_file(int n, uint8_t version, double C[], ivrm_cal_data_t* cal_data)
}
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];
- y = ((double)cal_data->point[k].drain_current)/1000; // uA
- }
+ if (version == 0) {
+ Vd = Vd_v1[k];
+ Vs = Vs_v1[k];
+ y = ((double)cal_data->point[k].drain_current)/1000; // uA
+ }
else if (version == 1 || version == 2 || version == 3) {
Vd = (double)cal_data->point[k].drain_voltage; // mV
Vs = (double)cal_data->point[k].source_voltage; // mV
- y = ((double)cal_data->point[k].drain_current)/1000; // uA
+ 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
- y = ((double)cal_data->point[k].drain_current)/1000; // uA
+ y = ((double)cal_data->point[k].drain_current)/1000; // uA
}
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
-
+
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
A[i*n+j] = A[i*n+j] + x[i]*x[j];
@@ -1108,9 +1604,9 @@ void fit_file(int n, uint8_t version, double C[], ivrm_cal_data_t* cal_data)
Y[i] = Y[i] + y*x[i];
}
}
-
+
simeq(n, A, Y, C);
-
+
} /* end fit_file */
void write_HWtab_bin(ivrm_parm_data_t* i_ivrm_parms,
@@ -1129,11 +1625,11 @@ void write_HWtab_bin(ivrm_parm_data_t* i_ivrm_parms,
double Ical[40][40];
double Iratio[40][40];
double Iratio_clip;
- uint8_t Iratio_int[40][40];
+ uint8_t Iratio_int[40][40];
uint32_t 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 = 600;
@@ -1142,7 +1638,7 @@ void write_HWtab_bin(ivrm_parm_data_t* i_ivrm_parms,
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);
@@ -1154,29 +1650,29 @@ void write_HWtab_bin(ivrm_parm_data_t* i_ivrm_parms,
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];
-
+
// clip at 3.875 and use for both temp calculations
- Iratio_clip = (Iratio[i][j]+1/16>3.875 ? 3.875 : Iratio[i][j]+1/16);
-// bug temp = (int) (Iratio[i][j]+1/16>3.875 ? 3.875 : Iratio[i][j]+1/16);
- temp = (int) Iratio_clip;
+ Iratio_clip = (Iratio[i][j]+1/16>3.875 ? 3.875 : Iratio[i][j]+1/16);
+// bug temp = (int) (Iratio[i][j]+1/16>3.875 ? 3.875 : Iratio[i][j]+1/16);
+ temp = (int) Iratio_clip;
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
temp = (int) ( (Iratio_clip - temp)*8 + 0.5);
temp = temp > 7 ? 7 : temp; // bug fix - clip to 7 if overflow
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;
+ Iratio_int[i][j] = ratio_val;
} else {
Iratio[i][j] = 0;
Iratio_int[i][j] = 0;
}
}
}
-
+
// 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;
+ 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];
@@ -1184,10 +1680,15 @@ void write_HWtab_bin(ivrm_parm_data_t* i_ivrm_parms,
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];
-
+ pss->lpsa.vdsvin[idx].fields.pfet7 = Iratio_int[(j*8)+7][i];
+
// Byte reverse the entry into the image.
- pss->lpsa.vdsvin[idx].value = revle64(pss->lpsa.vdsvin[idx].value);
+ pss->lpsa.vdsvin[idx].value = revle64(pss->lpsa.vdsvin[idx].value);
}
- }
+ }
} /* end fit_file */
+
+
+#ifdef __cplusplus
+} // end extern C
+#endif
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h
index 49d56eff3..928db5f10 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h
@@ -5,9 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2014 */
-/* [+] International Business Machines Corp. */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
/* [+] Google Inc. */
+/* [+] International Business Machines Corp. */
/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
@@ -26,7 +26,8 @@
#ifndef __PSTATE_TABLES_H__
#define __PSTATE_TABLES_H__
-// $Id: pstate_tables.h,v 1.10 2014/07/03 02:57:52 daviddu Exp $
+// $Id: pstate_tables.h,v 1.12 2015/06/01 19:02:17 stillgs Exp $
+
/// \file pstate_tables.h
/// \brief Code used to generate Pstate tables from real or imagined chip
@@ -36,10 +37,11 @@
// Constants associated with VRM stepping
-#define PSTATE_STEPSIZE_MAX 127
-#define VRM_STEPDELAY_RANGE_BITS 4
-#define LOG2_VRM_STEPDELAY_DIVIDER 3
-#define VRM_STEPDELAY_MAX 1600000
+#define PSTATE_STEPSIZE_MAX 127
+#define VRM_STEPDELAY_RANGE_BITS 4
+#define LOG2_VRM_STEPDELAY_DIVIDER 3
+#define VRM_STEPDELAY_MAX 1600000
+#define MAX_ACTIVE_CORES 12
#ifndef __ASSEMBLER__
@@ -48,32 +50,10 @@
extern "C" {
#endif
-/// A VPD operating point
-///
-/// VPD operating points are stored without load-line correction. Frequencies
-/// are in MHz, voltages are specified in units of 5mV, and characterization
-/// currents are specified in units of 500mA.
-///
-/// \bug The assumption is that the 'maxreg' points for the iVRM will also be
-/// supplied in the VPD in units of 5mv. If they are supplied in some other
-/// form then chip_characterization_create() will need to be modified.
-
-typedef struct {
-
- uint32_t vdd_5mv;
- uint32_t vcs_5mv;
- uint32_t vdd_maxreg_5mv;
- uint32_t vcs_maxreg_5mv;
- uint32_t idd_500ma;
- uint32_t ics_500ma;
- uint32_t frequency_mhz;
-
-} VpdOperatingPoint;
-
-
/// An internal operating point
///
-/// Internal operating points include characterization and load-line corrected
+/// Internal operating points include characterization (both the original,
+/// unbiased values and biased by external attributes) and load-line corrected
/// voltages for the external VRM. For the internal VRM, effective e-voltages
/// and maxreg voltages are stored. All voltages are stored as
/// uV. Characterization currents are in mA. Frequencies are in KHz. The
@@ -83,9 +63,11 @@ typedef struct {
typedef struct {
uint32_t vdd_uv;
- uint32_t vcs_uv;
+ uint32_t vcs_uv;
uint32_t vdd_corrected_uv;
uint32_t vcs_corrected_uv;
+ uint32_t vdd_corrected_wof_uv[MAX_ACTIVE_CORES];
+ uint32_t vcs_corrected_wof_uv[MAX_ACTIVE_CORES];
uint32_t vdd_ivrm_effective_uv;
uint32_t vcs_ivrm_effective_uv;
uint32_t vdd_maxreg_uv;
@@ -124,9 +106,11 @@ typedef struct {
typedef struct {
VpdOperatingPoint *vpd;
+ VpdOperatingPoint *vpd_unbiased;
OperatingPoint *ops;
OperatingPointParameters *parameters;
- int points;
+ uint32_t points;
+ uint32_t max_cores; // Needed for WOF
} ChipCharacterization;
@@ -145,11 +129,12 @@ chip_characterization_create(ChipCharacterization *characterization,
VpdOperatingPoint *vpd,
OperatingPoint *ops,
OperatingPointParameters *parameters,
- int points);
+ uint32_t points);
int
gpst_create(GlobalPstateTable *gpst,
- ChipCharacterization *characterization,
+ ChipCharacterization *characterization,
+ WOFElements *wof,
int pstate_stepsize,
int evrm_delay_ns);
@@ -201,9 +186,12 @@ void fit_file(int n,
void write_HWtab_bin(ivrm_parm_data_t* i_ivrm_parms,
double C[],
PstateSuperStructure* pss);
+
+int
+vid_mod_entry_create(WOFElements *wof, uint32_t entry, uint32_t cores, OperatingPoint *op);
#ifdef __cplusplus
-} // extern "C"
+} // end extern C
#endif
#endif // __ASSEMBLER__
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstates.c b/src/usr/hwpf/hwp/pstates/pstates/pstates.c
index 760ef0ad3..863d00634 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/pstates.c
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstates.c
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -20,7 +22,7 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: pstates.c,v 1.7 2014/02/18 16:07:35 jimyac Exp $
+// $Id: pstates.c,v 1.9 2015/06/01 19:02:17 stillgs Exp $
/// \file pstates.c
/// \brief Pstate routines required by OCC product firmware
@@ -29,6 +31,10 @@
#include "pgp_common.h"
#include "pstates.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/// Validate a VRM11 VID code
///
/// \param vid A VRM11 VID
@@ -410,3 +416,6 @@ int pstate_minmax_chk (const GlobalPstateTable* gpst,
return rc;
}
+#ifdef __cplusplus
+} // end extern C
+#endif
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstates.h b/src/usr/hwpf/hwp/pstates/pstates/pstates.h
index 8c5ea2b6d..fd0e876ea 100755
--- a/src/usr/hwpf/hwp/pstates/pstates/pstates.h
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstates.h
@@ -5,9 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2014 */
-/* [+] International Business Machines Corp. */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
/* [+] Google Inc. */
+/* [+] International Business Machines Corp. */
/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
@@ -26,17 +26,13 @@
#ifndef __PSTATES_H__
#define __PSTATES_H__
-// $Id: pstates.h,v 1.11 2014/05/27 15:33:49 daviddu Exp $
+// $Id: pstates.h,v 1.14 2015/06/01 19:02:17 stillgs Exp $
/// \file pstates.h
/// \brief Pstate structures and support routines for OCC product firmware
#include "pgp_common.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
////////////////////////////////////////////////////////////////////////////
// Global and Local Pstate Tables
////////////////////////////////////////////////////////////////////////////
@@ -52,7 +48,7 @@ extern "C" {
#define LOCAL_PSTATE_ARRAY_ENTRIES 32
/// The VDS/VIN table has 32 x 64-bit entries
-#define VDSVIN_ARRAY_ENTRIES 64
+#define VDSVIN_ARRAY_ENTRIES 64
/// The VRM-11 VID base voltage in micro-Volts
#define VRM11_BASE_UV 1612500
@@ -66,9 +62,45 @@ extern "C" {
/// The iVID step as an unsigned number (micro-Volts)
#define IVID_STEP_UV 6250
-/// CPM Inflection Points
+/// CPM Inflection Points
#define CPM_RANGES 8
+/// VPD #V Operating Points
+#define VPD_PV_POINTS 4
+#define VPD_PV_ORDER_STR {"PowerSave", "Nominal ", "Turbo ", "UltraTurbo"}
+#define POWERSAVE 0
+#define NOMINAL 1
+#define TURBO 2
+#define ULTRA 3
+
+/// IDDQ readings
+#define CORE_IDDQ_MEASUREMENTS 6
+#define CHIP_IDDQ_MEASUREMENTS 1
+
+#define CORE_IDDQ_ARRAY_VOLTAGES {0.80, 0.90, 1.00, 1.10, 1.20, 1.25}
+#define CHIP_IDDQ_ARRAY_VOLTAGES {1.10}
+
+/// Iddq LRPx and CRPx elements
+#define LRP_IDDQ_RECORDS CORE_IDDQ_MEASUREMENTS
+#define CRP_IDDQ_RECORDS CHIP_IDDQ_MEASUREMENTS
+#define IDDQ_READINGS_PER_IQ 2
+
+/// LRPx mapping to Core measurements 1 2 3 4 5 6
+/// Index 0 1 2 3 4 5
+#define CORE_IDDQ_MEASUREMENTS_ORDER { 1, 2, 3, 4, 5, 0}
+#define CORE_IDDQ_MEASUREMENT_VOLTAGES {"0.90", "1.00", "1.10", "1.20", "1.25", "0.80"}
+#define CORE_IDDQ_VALIDITY_CHECK { 1, 1, 1, 1, 1, 0}
+#define CORE_IDDQ_VALID_SECOND { 1, 1, 1, 1, 1, 0}
+
+// CRPx mapping to Chip measurements 0
+#define CHIP_IDDQ_MEASUREMENTS_ORDER { 0 }
+#define CHIP_IDDQ_MEASUREMENT_VOLTAGES {"1.10"}
+#define CHIP_IDDQ_VALID_SECOND { 0 }
+
+/// WOF Items
+#define NUM_ACTIVE_CORES 12
+#define MAX_UT_PSTATES 64 // Oversized
+
// Error/Panic codes for support routines
#define VRM11_INVALID_VOLTAGE 0x00876101
@@ -93,8 +125,8 @@ extern "C" {
#define GPST_BUG 0x00477806
#define GPST_PSTATE_GT_GPST_PMAX 0x00477807
-#define LPST_INVALID_OBJECT 0x00477901
-#define LPST_GPST_WARNING 0x00477902
+#define LPST_INVALID_OBJECT 0x00477901
+#define LPST_GPST_WARNING 0x00477902
#define LPST_INCR_CLIP_ERROR 0x00477903
/// PstateSuperStructure Magic Number
@@ -102,9 +134,9 @@ extern "C" {
/// This magic number identifies a particular version of the
/// PstateSuperStructure and its substructures. The version number should be
/// kept up to date as changes are made to the layout or contents of the
-/// structure.
+/// structure.
-#define PSTATE_SUPERSTRUCTURE_MAGIC 0x5053544154453033ull /* PSTATE03 */
+#define PSTATE_SUPERSTRUCTURE_MAGIC 0x5053544154453034ull /* PSTATE04 */
/// \defgroup pstate_options Pstate Options
@@ -135,10 +167,18 @@ extern "C" {
/// to come up at a low frequency.
#define PSTATE_FORCE_INITIAL_PMIN 0x10
+/// Flag to indicated that the 0.8V readings in the IDDQ Table are valid
+#define PSTATE_IDDQ_0P80V_VALID 0x20
+#define PSTATE_IDDQ_0P80V_INVALID ~PSTATE_IDDQ_0P80V_VALID
+
/// @}
#ifndef __ASSEMBLER__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdint.h>
#include <p8_ivrm.H>
@@ -220,7 +260,7 @@ typedef union lpst_entry {
uint64_t vdd_eco_pwrratio : 6;
uint64_t vcs_eco_pwrratio : 6;
uint64_t ps1_vid_incr : 3;
- uint64_t ps2_vid_incr : 3;
+ uint64_t ps2_vid_incr : 3;
uint64_t ps3_vid_incr : 3;
uint64_t reserved47 : 7;
uint64_t inc_step : 3;
@@ -232,7 +272,7 @@ typedef union lpst_entry {
uint64_t inc_step : 3;
uint64_t reserved47 : 7;
uint64_t ps3_vid_incr : 3;
- uint64_t ps2_vid_incr : 3;
+ uint64_t ps2_vid_incr : 3;
uint64_t ps1_vid_incr : 3;
uint64_t vcs_eco_pwrratio : 6;
uint64_t vdd_eco_pwrratio : 6;
@@ -263,29 +303,29 @@ typedef union vdsvin_entry {
#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 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;
+ 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;
+ 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;
@@ -397,12 +437,31 @@ typedef struct {
/// The Pstate for minimum core frequency in the system, defined by MRW
uint8_t pfloor;
+
+ /// The Pstate representing the Turbo VPD point
+ Pstate turbo_ps;
+
+ /// The Pstate representing the Nominal VPD point
+ Pstate nominal_ps;
+
+ /// The Pstate representing the PowerSave VPD point
+ Pstate powersave_ps;
+
+ /// The Pstate within the GPST which is the maximum for which iVRMs are
+ /// defined. This allows WOF Pstate and iVRM Pstates to be non-overlapping
+ /// to simplify characterization.
+ Pstate ivrm_max_ps;
+
+ /// The number of entries over which iVRM enablement is possible. The
+ /// starting entry is PMin.
+ uint8_t ivrm_entries;
+
} GlobalPstateTable;
/// This macro creates a properly-aligned Global Pstate table structure as a
-/// static initialization.
+/// static initialization.
#define GLOBAL_PSTATE_TABLE(x) \
GlobalPstateTable x \
@@ -482,12 +541,12 @@ typedef struct {
/// CPM Pstate ranges per mode
///
/// These Pstate range specifications apply to all chiplets operating in the
-/// same mode.
+/// same mode.
typedef union {
/// Forces alignment
- uint64_t quad[2];
+ uint64_t quad[2];
struct {
@@ -510,13 +569,181 @@ typedef union {
/// 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;
+/// A VPD operating point
+///
+/// VPD operating points are stored without load-line correction. Frequencies
+/// are in MHz, voltages are specified in units of 5mV, and characterization
+/// currents are specified in units of 500mA.
+///
+/// \bug The assumption is that the 'maxreg' points for the iVRM will also be
+/// supplied in the VPD in units of 5mv. If they are supplied in some other
+/// form then chip_characterization_create() will need to be modified.
+
+typedef struct {
+
+ uint32_t vdd_5mv;
+ uint32_t vcs_5mv;
+ uint32_t vdd_maxreg_5mv;
+ uint32_t vcs_maxreg_5mv;
+ uint32_t idd_500ma;
+ uint32_t ics_500ma;
+ uint32_t frequency_mhz;
+
+} VpdOperatingPoint;
+
+/// System Power Distribution Paramenters
+///
+/// Parameters set by system design that influence the power distribution
+/// for a rail to the processor module. This values are typically set in the
+/// system machine readable workbook and are used in the generation of the
+/// Global Pstate Table. This values are carried in the Pstate SuperStructure
+/// for use and/or reference by OCC firmware (eg the WOF algorithm)
+
+typedef struct {
+
+ /// Loadline
+ /// Impedance (binary microOhms) of the load line from a processor VDD VRM
+ /// to the Processor Module pins.
+ uint32_t loadline_uohm;
+
+ /// Distribution Loss
+ /// Impedance (binary in microOhms) of the VDD distribution loss sense point
+ /// to the circuit.
+ uint32_t distloss_uohm;
+
+ /// Distribution Offset
+ /// Offset voltage (binary in microvolts) to apply to the rail VRM
+ /// distribution to the processor module.
+ uint32_t distoffset_uv;
+
+} SysPowerDistParms;
+
+
+
+/// IDDQ Reading Type
+/// Each entry is 2 bytes. The values are in 10mA units; this allow for a
+/// maximum value of 655.36A represented.
+///
+typedef uint16_t iddq_entry_t;
+
+/// IDDQ Reading
+///
+/// Structure with "raw" and "temperature corrected" values. See VPD
+/// documentation for the correction function that is applied to the raw
+/// value to load the corrected value.
+///
+typedef union {
+ uint32_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ iddq_entry_t iddq_raw_value;
+ iddq_entry_t iddq_corrected_value;
+#else
+ iddq_entry_t iddq_corrected_value;
+ iddq_entry_t iddq_raw_value;
+#endif // _BIG_ENDIAN
+ } fields;
+
+} IddqReading;
+
+/// Iddq Table
+///
+/// A set of arrays of leakage values (Iddq) collected at various voltage
+/// conditions during manufacturing test that will feed into the Workload
+/// Optimized Frequency algorithms on the OCC. These values are not installed
+/// in any hardware facilities.
+///
+typedef struct {
+
+ /// IDDQ version
+ uint8_t iddq_version;
+
+ /// VDD IDDQ readings
+ IddqReading iddq_vdd[CORE_IDDQ_MEASUREMENTS];
+
+ /// VCS IDDQ readings
+ IddqReading iddq_vcs[CORE_IDDQ_MEASUREMENTS];
+
+ /// VIO IDDQ readings
+ IddqReading iddq_vio[CHIP_IDDQ_MEASUREMENTS];
+
+} IddqTable;
+
+
+
+/// UltraTurbo Segment VIDs by Core Count
+typedef struct {
+
+ /// Number of Segment Pstates
+ uint8_t ut_segment_pstates;
+
+ /// Maximum number of core possibly active
+ uint8_t ut_max_cores;
+
+ /// VDD VID modification
+ /// 1 core active = offset 0
+ /// 2 cores active = offset 1
+ /// ...
+ /// 12 cores active = offset 11
+ uint8_t ut_segment_vdd_vid[MAX_UT_PSTATES][NUM_ACTIVE_CORES];
+
+ /// VCS VID modification
+ /// 1 core active = offset 0
+ /// 2 cores active = offset 1
+ /// ...
+ /// 12 cores active = offset 11
+ uint8_t ut_segment_vcs_vid[MAX_UT_PSTATES][NUM_ACTIVE_CORES];
+
+} VIDModificationTable;
+
+/// Workload Optimized Frequency (WOF) Elements
+///
+/// Structure defining various control elements needed by the WOF algorithm
+/// firmware running on the OCC.
+///
+typedef struct {
+
+ /// WOF Enablement
+ uint8_t wof_enabled;
+
+ /// Operating points
+ ///
+ /// VPD operating points are stored without load-line correction. Frequencies
+ /// are in MHz, voltages are specified in units of 5mV, and currents are
+ /// in units of 500mA.
+ VpdOperatingPoint operating_points[VPD_PV_POINTS];
+
+ /// Loadlines and Distribution values for the VDD rail
+ SysPowerDistParms vdd_sysparm;
+
+ /// Loadlines and Distribution values for the VCS rail
+ SysPowerDistParms vcs_sysparm;
+
+ /// TDP<>RDP Current Factor
+ /// Value read from ??? VPD
+ /// Defines the scaling factor that converts current (amperage) value from
+ /// the Thermal Design Point to the Regulator Design Point (RDP) as input
+ /// to the Workload Optimization Frequency (WOF) OCC algorithm.
+ ///
+ /// This is a ratio value and has a granularity of 0.01 decimal. Data
+ /// is held in hexidecimal (eg 1.22 is represented as 122 and then converted
+ /// to hex 0x7A).
+ uint32_t tdp_rdp_factor;
+
+ /// UltraTurbo Segment VIDs by Core Count
+ VIDModificationTable ut_vid_mod;
+
+ uint8_t pad[4];
+
+} WOFElements;
+
/// The layout of the data created by the Pstate table creation firmware
///
/// This structure is only used for passing Pstate data from the FSP into OCC,
@@ -538,13 +765,19 @@ typedef struct {
/// Local Pstate Array
LocalPstateArray lpsa;
-
+
/// Resonant Clocking Setup
ResonantClockingSetup resclk;
-
+
/// CPM Pstate ranges
CpmPstateModeRanges cpmranges;
-
+
+ /// Iddq Table
+ IddqTable iddq;
+
+ /// WOF Controls
+ WOFElements wof;
+
} PstateSuperStructure;
@@ -561,25 +794,25 @@ int
bias_vid11(Vid11 vid, int bias, Vid11* biased_fcode);
int
-gpst_entry(const GlobalPstateTable* gpst,
- const Pstate pstate,
+gpst_entry(const GlobalPstateTable* gpst,
+ const Pstate pstate,
const int bias,
gpst_entry_t* entry);
-int
-freq2pState (const GlobalPstateTable* gpst,
- const uint32_t freq_khz,
+int
+freq2pState (const GlobalPstateTable* gpst,
+ const uint32_t freq_khz,
Pstate* pstate);
-
+
int
-gpst_vdd2pstate(const GlobalPstateTable* gpst,
- const uint8_t vdd,
+gpst_vdd2pstate(const GlobalPstateTable* gpst,
+ const uint8_t vdd,
Pstate* pstate,
gpst_entry_t* entry);
int
-pstate_minmax_chk (const GlobalPstateTable* gpst,
+pstate_minmax_chk (const GlobalPstateTable* gpst,
Pstate* pstate);
/// Return the Pmin value associated with a GlobalPstateTable
@@ -613,7 +846,7 @@ lpst_pmax(const LocalPstateArray* lpsa)
}
#ifdef __cplusplus
-} // extern "C"
+} // end extern C
#endif
#endif /* __ASSEMBLER__ */
diff --git a/src/usr/hwpf/hwp/pstates/pstates_common.mk b/src/usr/hwpf/hwp/pstates/pstates_common.mk
index bded93134..98dddd856 100644
--- a/src/usr/hwpf/hwp/pstates/pstates_common.mk
+++ b/src/usr/hwpf/hwp/pstates/pstates_common.mk
@@ -54,6 +54,10 @@ OBJS += pstate_tables.o
OBJS += freqVoltageSvc.o
OBJS += proc_set_max_pstate.o
+## allow FAPI macros in c files
+CFLAGS += -D __FAPI
+CC_OVERRIDE = 1
+
## NOTE: add a new directory onto the vpaths when you add a new HWP
##@ VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/???
VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/pstates/pstates
OpenPOWER on IntegriCloud