summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Dahle <dedahle@us.ibm.com>2013-06-12 09:59:55 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-07-08 10:31:17 -0500
commit7a2c484cc9c574302beb70cfff449bb40d26c2e2 (patch)
tree0c4cbf7a0be714163f639ac1eacf2c151c360395
parent0e8072c8c3aa49ce9e75c468f4e14e80893d56f0 (diff)
downloadtalos-hostboot-7a2c484cc9c574302beb70cfff449bb40d26c2e2.tar.gz
talos-hostboot-7a2c484cc9c574302beb70cfff449bb40d26c2e2.zip
Integrate pstate-building HWPs into Hostboot.
Transferred pstate files from FSP code. Edited files to compile on Hostboot. Change-Id: I04ff6ba489e77277afe27cff9544aea1367c150e RTC: 73048 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/4979 Tested-by: Jenkins Server Reviewed-by: MIKE J. JONES <mjjones@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--src/usr/hwpf/hwp/include/pgp_common.h (renamed from src/usr/hwpf/hwp/build_winkle_images/p8_set_pore_bar/pgp_common.h)45
-rw-r--r--src/usr/hwpf/hwp/makefile3
-rw-r--r--src/usr/hwpf/hwp/pstates/makefile57
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c229
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/lab_pstates.c486
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/lab_pstates.h101
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.C490
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.H88
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml63
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.C138
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.H49
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/proc_get_voltage_errors.xml37
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstate_tables.c716
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstate_tables.h157
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstates.c395
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/pstates.h512
-rwxr-xr-xsrc/usr/hwpf/hwp/pstates/pstates/ssx.h103
-rw-r--r--src/usr/hwpf/makefile4
18 files changed, 3648 insertions, 25 deletions
diff --git a/src/usr/hwpf/hwp/build_winkle_images/p8_set_pore_bar/pgp_common.h b/src/usr/hwpf/hwp/include/pgp_common.h
index 2fb33877a..9cdeb185c 100644
--- a/src/usr/hwpf/hwp/build_winkle_images/p8_set_pore_bar/pgp_common.h
+++ b/src/usr/hwpf/hwp/include/pgp_common.h
@@ -1,26 +1,25 @@
-/* IBM_PROLOG_BEGIN_TAG
- * This is an automatically generated prolog.
- *
- * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_set_pore_bar/pgp_common.h $
- *
- * IBM CONFIDENTIAL
- *
- * COPYRIGHT International Business Machines Corp. 2012
- *
- * p1
- *
- * Object Code Only (OCO) source materials
- * Licensed Internal Code Source Materials
- * IBM HostBoot Licensed Internal Code
- *
- * The source code for this program is not published or other-
- * wise divested of its trade secrets, irrespective of what has
- * been deposited with the U.S. Copyright Office.
- *
- * Origin: 30
- *
- * IBM_PROLOG_END_TAG
- */
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/include/pgp_common.h $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2012,2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
// $Id: pgp_common.h,v 1.2 2012/08/13 16:11:58 stillgs Exp $
#ifndef __PGP_COMMON_H__
diff --git a/src/usr/hwpf/hwp/makefile b/src/usr/hwpf/hwp/makefile
index 7a611a9b0..d2e881656 100644
--- a/src/usr/hwpf/hwp/makefile
+++ b/src/usr/hwpf/hwp/makefile
@@ -47,7 +47,8 @@ SUBDIRS = dmi_training.d sbe_centaur_init.d mc_config.d \
dram_training.d activate_powerbus.d build_winkle_images.d \
core_activate.d dram_initialization.d edi_ei_initialization.d \
establish_system_smp.d bus_training.d occ.d tod_init.d \
- nest_chiplets.d start_payload.d thread_activate.d slave_sbe.d
+ nest_chiplets.d start_payload.d thread_activate.d slave_sbe.d \
+ pstates.d
include mvpd_accessors/mvpd.mk
include utility_procedures/utils.mk
diff --git a/src/usr/hwpf/hwp/pstates/makefile b/src/usr/hwpf/hwp/pstates/makefile
new file mode 100644
index 000000000..529f366a6
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/makefile
@@ -0,0 +1,57 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/hwpf/hwp/pstates/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2013
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or otherwise
+# divested of its trade secrets, irrespective of what has been
+# deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END_TAG
+ROOTPATH = ../../../../..
+
+MODULE = pstates
+
+## support for Targeting and fapi
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp
+
+## pointer to common HWP files
+EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/include
+
+## NOTE: add the base istep dir here.
+##@ EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/@istepname
+EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/pstates
+
+## Include sub dirs
+## NOTE: add a new EXTRAINCDIR when you add a new HWP
+##@ EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/???
+EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/pstates/pstates
+
+## NOTE: add new object files when you add a new HWP
+OBJS = gpstCheckByte.o \
+ lab_pstates.o \
+ p8_build_pstate_datablock.o \
+ proc_get_voltage.o \
+ pstates.o \
+ pstate_tables.o
+
+## 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
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c b/src/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c
new file mode 100755
index 000000000..bd4f88f12
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c
@@ -0,0 +1,229 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/gpstCheckByte.c $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: gpstCheckByte.c,v 1.1 2012/10/16 16:30:15 jimyac Exp $
+
+/// \file gpamCheckByte.c
+/// \brief Generate Pstate table check byte - Generated by genGpstCheckByte.tcl
+
+#include <stdint.h>
+
+#define BIT(x, n) (((x) >> (63 - (n))) & 1)
+
+uint8_t
+gpstCheckByte(uint64_t gpstEntry)
+{
+ int cb[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+ cb[0] ^= BIT(gpstEntry, 0);
+ cb[0] ^= BIT(gpstEntry, 1);
+ cb[0] ^= BIT(gpstEntry, 2);
+ cb[0] ^= BIT(gpstEntry, 3);
+ cb[0] ^= BIT(gpstEntry, 4);
+ cb[0] ^= BIT(gpstEntry, 5);
+ cb[0] ^= BIT(gpstEntry, 6);
+ cb[0] ^= BIT(gpstEntry, 7);
+ cb[0] ^= BIT(gpstEntry, 24);
+ cb[0] ^= BIT(gpstEntry, 25);
+ cb[0] ^= BIT(gpstEntry, 26);
+ cb[0] ^= BIT(gpstEntry, 28);
+ cb[0] ^= BIT(gpstEntry, 33);
+ cb[0] ^= BIT(gpstEntry, 38);
+ cb[0] ^= BIT(gpstEntry, 42);
+ cb[0] ^= BIT(gpstEntry, 43);
+ cb[0] ^= BIT(gpstEntry, 44);
+ cb[0] ^= BIT(gpstEntry, 45);
+ cb[0] ^= BIT(gpstEntry, 52);
+ cb[0] ^= BIT(gpstEntry, 53);
+ cb[0] ^= BIT(gpstEntry, 54);
+ cb[0] ^= BIT(gpstEntry, 55);
+ cb[1] ^= BIT(gpstEntry, 0);
+ cb[1] ^= BIT(gpstEntry, 3);
+ cb[1] ^= BIT(gpstEntry, 4);
+ cb[1] ^= BIT(gpstEntry, 7);
+ cb[1] ^= BIT(gpstEntry, 8);
+ cb[1] ^= BIT(gpstEntry, 9);
+ cb[1] ^= BIT(gpstEntry, 10);
+ cb[1] ^= BIT(gpstEntry, 11);
+ cb[1] ^= BIT(gpstEntry, 12);
+ cb[1] ^= BIT(gpstEntry, 13);
+ cb[1] ^= BIT(gpstEntry, 14);
+ cb[1] ^= BIT(gpstEntry, 15);
+ cb[1] ^= BIT(gpstEntry, 32);
+ cb[1] ^= BIT(gpstEntry, 33);
+ cb[1] ^= BIT(gpstEntry, 34);
+ cb[1] ^= BIT(gpstEntry, 36);
+ cb[1] ^= BIT(gpstEntry, 41);
+ cb[1] ^= BIT(gpstEntry, 46);
+ cb[1] ^= BIT(gpstEntry, 50);
+ cb[1] ^= BIT(gpstEntry, 51);
+ cb[1] ^= BIT(gpstEntry, 52);
+ cb[1] ^= BIT(gpstEntry, 53);
+ cb[2] ^= BIT(gpstEntry, 4);
+ cb[2] ^= BIT(gpstEntry, 5);
+ cb[2] ^= BIT(gpstEntry, 6);
+ cb[2] ^= BIT(gpstEntry, 7);
+ cb[2] ^= BIT(gpstEntry, 8);
+ cb[2] ^= BIT(gpstEntry, 11);
+ cb[2] ^= BIT(gpstEntry, 12);
+ cb[2] ^= BIT(gpstEntry, 15);
+ cb[2] ^= BIT(gpstEntry, 16);
+ cb[2] ^= BIT(gpstEntry, 17);
+ cb[2] ^= BIT(gpstEntry, 18);
+ cb[2] ^= BIT(gpstEntry, 19);
+ cb[2] ^= BIT(gpstEntry, 20);
+ cb[2] ^= BIT(gpstEntry, 21);
+ cb[2] ^= BIT(gpstEntry, 22);
+ cb[2] ^= BIT(gpstEntry, 23);
+ cb[2] ^= BIT(gpstEntry, 40);
+ cb[2] ^= BIT(gpstEntry, 41);
+ cb[2] ^= BIT(gpstEntry, 42);
+ cb[2] ^= BIT(gpstEntry, 44);
+ cb[2] ^= BIT(gpstEntry, 49);
+ cb[2] ^= BIT(gpstEntry, 54);
+ cb[3] ^= BIT(gpstEntry, 2);
+ cb[3] ^= BIT(gpstEntry, 3);
+ cb[3] ^= BIT(gpstEntry, 4);
+ cb[3] ^= BIT(gpstEntry, 5);
+ cb[3] ^= BIT(gpstEntry, 12);
+ cb[3] ^= BIT(gpstEntry, 13);
+ cb[3] ^= BIT(gpstEntry, 14);
+ cb[3] ^= BIT(gpstEntry, 15);
+ cb[3] ^= BIT(gpstEntry, 16);
+ cb[3] ^= BIT(gpstEntry, 19);
+ cb[3] ^= BIT(gpstEntry, 20);
+ cb[3] ^= BIT(gpstEntry, 23);
+ cb[3] ^= BIT(gpstEntry, 24);
+ cb[3] ^= BIT(gpstEntry, 25);
+ cb[3] ^= BIT(gpstEntry, 26);
+ cb[3] ^= BIT(gpstEntry, 27);
+ cb[3] ^= BIT(gpstEntry, 28);
+ cb[3] ^= BIT(gpstEntry, 29);
+ cb[3] ^= BIT(gpstEntry, 30);
+ cb[3] ^= BIT(gpstEntry, 31);
+ cb[3] ^= BIT(gpstEntry, 48);
+ cb[3] ^= BIT(gpstEntry, 49);
+ cb[3] ^= BIT(gpstEntry, 50);
+ cb[3] ^= BIT(gpstEntry, 52);
+ cb[4] ^= BIT(gpstEntry, 1);
+ cb[4] ^= BIT(gpstEntry, 6);
+ cb[4] ^= BIT(gpstEntry, 10);
+ cb[4] ^= BIT(gpstEntry, 11);
+ cb[4] ^= BIT(gpstEntry, 12);
+ cb[4] ^= BIT(gpstEntry, 13);
+ cb[4] ^= BIT(gpstEntry, 20);
+ cb[4] ^= BIT(gpstEntry, 21);
+ cb[4] ^= BIT(gpstEntry, 22);
+ cb[4] ^= BIT(gpstEntry, 23);
+ cb[4] ^= BIT(gpstEntry, 24);
+ cb[4] ^= BIT(gpstEntry, 27);
+ cb[4] ^= BIT(gpstEntry, 28);
+ cb[4] ^= BIT(gpstEntry, 31);
+ cb[4] ^= BIT(gpstEntry, 32);
+ cb[4] ^= BIT(gpstEntry, 33);
+ cb[4] ^= BIT(gpstEntry, 34);
+ cb[4] ^= BIT(gpstEntry, 35);
+ cb[4] ^= BIT(gpstEntry, 36);
+ cb[4] ^= BIT(gpstEntry, 37);
+ cb[4] ^= BIT(gpstEntry, 38);
+ cb[4] ^= BIT(gpstEntry, 39);
+ cb[5] ^= BIT(gpstEntry, 0);
+ cb[5] ^= BIT(gpstEntry, 1);
+ cb[5] ^= BIT(gpstEntry, 2);
+ cb[5] ^= BIT(gpstEntry, 4);
+ cb[5] ^= BIT(gpstEntry, 9);
+ cb[5] ^= BIT(gpstEntry, 14);
+ cb[5] ^= BIT(gpstEntry, 18);
+ cb[5] ^= BIT(gpstEntry, 19);
+ cb[5] ^= BIT(gpstEntry, 20);
+ cb[5] ^= BIT(gpstEntry, 21);
+ cb[5] ^= BIT(gpstEntry, 28);
+ cb[5] ^= BIT(gpstEntry, 29);
+ cb[5] ^= BIT(gpstEntry, 30);
+ cb[5] ^= BIT(gpstEntry, 31);
+ cb[5] ^= BIT(gpstEntry, 32);
+ cb[5] ^= BIT(gpstEntry, 35);
+ cb[5] ^= BIT(gpstEntry, 36);
+ cb[5] ^= BIT(gpstEntry, 39);
+ cb[5] ^= BIT(gpstEntry, 40);
+ cb[5] ^= BIT(gpstEntry, 41);
+ cb[5] ^= BIT(gpstEntry, 42);
+ cb[5] ^= BIT(gpstEntry, 43);
+ cb[5] ^= BIT(gpstEntry, 44);
+ cb[5] ^= BIT(gpstEntry, 45);
+ cb[5] ^= BIT(gpstEntry, 46);
+ cb[5] ^= BIT(gpstEntry, 47);
+ cb[6] ^= BIT(gpstEntry, 8);
+ cb[6] ^= BIT(gpstEntry, 9);
+ cb[6] ^= BIT(gpstEntry, 10);
+ cb[6] ^= BIT(gpstEntry, 12);
+ cb[6] ^= BIT(gpstEntry, 17);
+ cb[6] ^= BIT(gpstEntry, 22);
+ cb[6] ^= BIT(gpstEntry, 26);
+ cb[6] ^= BIT(gpstEntry, 27);
+ cb[6] ^= BIT(gpstEntry, 28);
+ cb[6] ^= BIT(gpstEntry, 29);
+ cb[6] ^= BIT(gpstEntry, 36);
+ cb[6] ^= BIT(gpstEntry, 37);
+ cb[6] ^= BIT(gpstEntry, 38);
+ cb[6] ^= BIT(gpstEntry, 39);
+ cb[6] ^= BIT(gpstEntry, 40);
+ cb[6] ^= BIT(gpstEntry, 43);
+ cb[6] ^= BIT(gpstEntry, 44);
+ cb[6] ^= BIT(gpstEntry, 47);
+ cb[6] ^= BIT(gpstEntry, 48);
+ cb[6] ^= BIT(gpstEntry, 49);
+ cb[6] ^= BIT(gpstEntry, 50);
+ cb[6] ^= BIT(gpstEntry, 51);
+ cb[6] ^= BIT(gpstEntry, 52);
+ cb[6] ^= BIT(gpstEntry, 53);
+ cb[6] ^= BIT(gpstEntry, 54);
+ cb[6] ^= BIT(gpstEntry, 55);
+ cb[7] ^= BIT(gpstEntry, 16);
+ cb[7] ^= BIT(gpstEntry, 17);
+ cb[7] ^= BIT(gpstEntry, 18);
+ cb[7] ^= BIT(gpstEntry, 20);
+ cb[7] ^= BIT(gpstEntry, 25);
+ cb[7] ^= BIT(gpstEntry, 30);
+ cb[7] ^= BIT(gpstEntry, 34);
+ cb[7] ^= BIT(gpstEntry, 35);
+ cb[7] ^= BIT(gpstEntry, 36);
+ cb[7] ^= BIT(gpstEntry, 37);
+ cb[7] ^= BIT(gpstEntry, 44);
+ cb[7] ^= BIT(gpstEntry, 45);
+ cb[7] ^= BIT(gpstEntry, 46);
+ cb[7] ^= BIT(gpstEntry, 47);
+ cb[7] ^= BIT(gpstEntry, 48);
+ cb[7] ^= BIT(gpstEntry, 51);
+ cb[7] ^= BIT(gpstEntry, 52);
+ cb[7] ^= BIT(gpstEntry, 55);
+ return
+ (cb[0] << 7) |
+ (cb[1] << 6) |
+ (cb[2] << 5) |
+ (cb[3] << 4) |
+ (cb[4] << 3) |
+ (cb[5] << 2) |
+ (cb[6] << 1) |
+ (cb[7] << 0);
+}
+
diff --git a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c
new file mode 100755
index 000000000..2e7767927
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c
@@ -0,0 +1,486 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/lab_pstates.c $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: lab_pstates.c,v 1.7 2013/06/12 20:01:35 mjjones Exp $
+
+/// \file lab_pstates.c
+/// \brief Lab-only (as opposed to product-procedure) support for Pstates.
+///
+/// Lab-only Pstate support is separated from generic Pstate support to reduce
+/// the size of OCC product firmware images.
+
+#include "ssx.h"
+// jwy #include "ppc32.h"
+#include "lab_pstates.h"
+// jwy #include "pmc_register_addresses.h"
+// jwy #include "pmc_firmware_registers.h"
+// jwy #include "pcbs_register_addresses.h"
+// jwy #include "pcbs_firmware_registers.h"
+
+/// Convert a voltage in microvolts to a VRM-11 VID code, rounding the implied
+/// voltage as required.
+///
+/// \param v_uv Voltage in micro-volts
+///
+/// \param round \a round >= 0 indicate round voltage up, while \a round < 0
+/// implies round voltage down
+///
+/// \param vrm11_vid A pointer to the location of the final VID code. This
+/// location is updated even if the final VID code is invalid.
+///
+/// \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.
+
+int
+vuv2vrm11(uint32_t v_uv, int round, uint8_t *vrm11_vid)
+{
+ int32_t offset, vid;
+
+ offset = VRM11_BASE_UV - v_uv;
+ vid = offset / VRM11_STEP_UV;
+
+ if (((offset % VRM11_STEP_UV) != 0) && (round < 0)) {
+ vid++;
+ }
+
+ *vrm11_vid = vid;
+ return vid11_validate(vid);
+}
+
+
+/// Convert a VRM-11 VID code to a voltage in microvolts
+
+int
+vrm112vuv(uint8_t vrm11_vid, uint32_t *v_uv)
+{
+ *v_uv= VRM11_BASE_UV - (vrm11_vid * VRM11_STEP_UV);
+ return vid11_validate(vrm11_vid);
+}
+
+
+/// Convert a voltage in microvolts to an internal VID code, rounding the
+/// implied voltage as required.
+///
+/// \param v_uv Voltage in micro-volts
+///
+/// \param round \a round >= 0 indicate round voltage up, while \a round < 0
+/// implies round voltage down
+///
+/// \param ivid A pointer to the location of the final VID code. This
+/// location is updated even the event of errors.
+///
+/// \retval 0 Success
+///
+/// \retval -IVID_INVALID_VOLTAGE If \a v_uv can not be converted to a legal
+/// IVID encoding.
+
+int
+vuv2ivid(uint32_t v_uv, int round, uint8_t *ivid)
+{
+ int rc;
+ int32_t offset, vid;
+
+ offset = v_uv - IVID_BASE_UV;
+ vid = offset / IVID_STEP_UV;
+
+ if (((offset % IVID_STEP_UV) != 0) && (round >= 0)) {
+ vid++;
+ }
+
+ *ivid = vid;
+ if ((vid < 0) || (vid > 0x7f)) {
+ rc = -IVID_INVALID_VOLTAGE;
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+
+/// Convert an iVID code to a voltage in microvolts
+
+int
+ivid2vuv(uint8_t ivid, uint32_t *v_uv)
+{
+ if (ivid > 0x7f) {
+ return -IVID_INVALID_VOLTAGE;
+ } else {
+ *v_uv= IVID_BASE_UV + (ivid * IVID_STEP_UV);
+ 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.
+
+int
+sprintf_10uv(char *s, uint32_t v_uv)
+{
+ return sprintf(s, "%d.%05d", v_uv / 1000000, (v_uv % 1000000) / 10);
+}
+
+/// Format an IVID code as 10 microvolts into a user-supplied string. The
+/// string \a s must be able to store at least FORMAT_10UV_STRLEN characters.
+
+int
+sprintf_ivid(char *s, uint8_t ivid)
+{
+ int rc;
+ uint32_t v_uv;
+
+ if ((rc = ivid2vuv(ivid, &v_uv)) != 0) {
+ return rc;
+ }
+ return sprintf_10uv(s, v_uv);
+}
+
+/// Format a VRM-11 VID code as 10 microvolts into a user-supplied string. The
+/// string \a s must be able to store at least FORMAT_10UV_STRLEN characters.
+
+int
+sprintf_vrm11(char *s, uint8_t vrm11)
+{
+ int rc;
+ uint32_t v_uv;
+
+ if ((rc = vrm112vuv(vrm11, &v_uv)) != 0) {
+ strcpy(s, FORMAT_10UV_ERROR);
+ } else {
+ rc = sprintf_10uv(s, v_uv);
+ }
+ return rc;
+}
+
+#ifdef FAPIECMD
+
+/// Format a voltage in microvolts as 10 microvolts to a stream.
+
+int
+fprintf_10uv(FILE *stream, uint32_t v_uv)
+{
+ int rc;
+ char s[FORMAT_10UV_STRLEN];
+
+ rc = sprintf_10uv(s, v_uv);
+ if (rc > 0) {
+ rc = fputs(s, stream);
+ }
+ return rc;
+}
+
+
+/// Format a VRM-11 VID code as 10 microvolts to a stream.
+
+int
+fprintf_vrm11(FILE *stream, uint8_t vrm11)
+{
+ int rc;
+ char s[FORMAT_10UV_STRLEN];
+
+ rc = sprintf_vrm11(s, vrm11);
+ if (rc > 0) {
+ rc = fputs(s, stream);
+ }
+ return rc;
+}
+
+
+/// Format an iVID code as 10 microvolts to a stream.
+
+int
+fprintf_ivid(FILE *stream, uint8_t ivid)
+{
+ int rc;
+ char s[FORMAT_10UV_STRLEN];
+
+ rc = sprintf_ivid(s, ivid);
+ 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.
+
+#ifdef _BIG_ENDIAN
+
+#define revle16(x) x
+#define revle32(x) x
+#define revle64(x) x
+
+#else
+
+uint16_t revle16(uint16_t i_x);
+uint32_t revle32(uint32_t i_x);
+uint64_t revle64(uint64_t i_x);
+
+#endif
+
+
+/// Print a GlobalPstateTable structure on a given stream
+///
+/// \param stream The output stream
+///
+/// \param gpst The Global Pstate Table to print
+
+void
+gpst_print(FILE *stream, GlobalPstateTable *gpst)
+{
+ // Endian-corrected scalar Pstate fields
+
+ uint32_t options;
+ uint32_t pstate0_frequency_khz, frequency_step_khz;
+ uint8_t entries, pstate_stepsize, vrm_stepdelay_range, vrm_stepdelay_value;
+ Pstate pmin, pvsafe, psafe;
+
+ // Endian-corrected vector Pstate fields
+
+ gpst_entry_t entry;
+
+ // Other local variables
+
+ int i;
+ uint8_t evid_vdd, evid_vcs, evid_vdd_eff, evid_vcs_eff,
+ maxreg_vdd, maxreg_vcs;
+ int8_t pstate;
+ char evid_vdd_str[FORMAT_10UV_STRLEN];
+ char evid_vcs_str[FORMAT_10UV_STRLEN];
+ char evid_vdd_eff_str[FORMAT_10UV_STRLEN];
+ char evid_vcs_eff_str[FORMAT_10UV_STRLEN];
+ char maxreg_vdd_str[FORMAT_10UV_STRLEN];
+ char maxreg_vcs_str[FORMAT_10UV_STRLEN];
+
+ // Get endian-corrected scalars
+
+ options = revle32(gpst->options.options);
+ pstate0_frequency_khz = revle32(gpst->pstate0_frequency_khz);
+ frequency_step_khz = revle32(gpst->frequency_step_khz);
+ entries = gpst->entries;
+ pstate_stepsize = gpst->pstate_stepsize;
+ vrm_stepdelay_range = gpst->vrm_stepdelay_range;
+ vrm_stepdelay_value = gpst->vrm_stepdelay_value;
+ pmin = gpst->pmin;
+ pvsafe = gpst->pvsafe;
+ psafe = gpst->psafe;
+
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream, "Global Pstate Table @ %p\n", gpst);
+ 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);
+ fprintf(stream, "Pstate 0 Frequency = %u KHz\n", pstate0_frequency_khz);
+ fprintf(stream, "Pstate 0 Frequency Code (per core) :");
+ for (i = 0; i < PGP_NCORES; i++) {
+ if ((i != 0) && ((i % 4) == 0)) {
+ fprintf(stream, "\n ");
+ }
+ fprintf(stream, " 0x%03x", revle16(gpst->pstate0_frequency_code[i]));
+ }
+ fprintf(stream, "\n");
+ fprintf(stream, "DPLL Fmax Bias (per core) :");
+ for (i = 0; i < PGP_NCORES; i++) {
+ fprintf(stream, " %d", gpst->dpll_fmax_bias[i]);
+ }
+ fprintf(stream, "\n");
+ fprintf(stream, "Pstate Step Size %u, VRM Range %u, VRM Delay %u\n",
+ pstate_stepsize, vrm_stepdelay_range, vrm_stepdelay_value);
+ fprintf(stream, "Pvsafe %d, Psafe %d\n", pvsafe, psafe);
+
+ if (options == 0) {
+ fprintf(stream, "No Options\n");
+ } else {
+ fprintf(stream, "Options 0x%08x:\n", options);
+ if (options & PSTATE_NO_COPY_GPST) {
+ fprintf(stream, " PSTATE_NO_COPY_GPST\n");
+ }
+ if (options & PSTATE_NO_INSTALL_GPST) {
+ fprintf(stream, " PSTATE_NO_INSTALL_GPST\n");
+ }
+ if (options & PSTATE_NO_INSTALL_LPSA) {
+ fprintf(stream, " PSTATE_NO_INSTALL_LPSA\n");
+ }
+ if (options & PSTATE_NO_INSTALL_RESCLK) {
+ fprintf(stream, " PSTATE_NO_INSTALL_RESCLK\n");
+ }
+ if (options & PSTATE_FORCE_INITIAL_PMIN) {
+ fprintf(stream, " PSTATE_FORCE_INITIAL_PMIN\n");
+ }
+ }
+ 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);
+
+ evid_vcs = entry.fields.evid_vcs;
+ sprintf_vrm11(evid_vcs_str, evid_vcs);
+
+ evid_vdd_eff = entry.fields.evid_vdd_eff;
+ sprintf_ivid(evid_vdd_eff_str, evid_vdd_eff);
+
+ evid_vcs_eff = entry.fields.evid_vcs_eff;
+ sprintf_ivid(evid_vcs_eff_str, evid_vcs_eff);
+
+ maxreg_vdd = entry.fields.maxreg_vdd;
+ sprintf_ivid(maxreg_vdd_str, maxreg_vdd);
+
+ maxreg_vcs = entry.fields.maxreg_vcs;
+ sprintf_ivid(maxreg_vcs_str, maxreg_vcs);
+
+ pstate = gpst_pmin(gpst) + i;
+
+ fprintf(stream,
+ "%3d %+4d "
+ "%4d "
+ "0x%02x %s "
+ "0x%02x %s "
+ "0x%02x %s "
+ "0x%02x %s "
+ "0x%02x %s "
+ "0x%02x %s\n",
+ i, pstate,
+ (pstate0_frequency_khz + (frequency_step_khz * pstate)) / 1000,
+ evid_vdd, evid_vdd_str,
+ evid_vcs, evid_vcs_str,
+ evid_vdd_eff, evid_vdd_eff_str,
+ evid_vcs_eff, evid_vcs_eff_str,
+ maxreg_vdd, maxreg_vdd_str,
+ maxreg_vcs, maxreg_vcs_str);
+ }
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+}
+
+
+/// Print a LocalPstateArray structure on a given stream
+///
+/// \param stream The output stream
+///
+/// \param lpsa The Local Pstate Array to print
+///
+/// \todo Replace the hex dump with a decoded Local Pstate Table + ivrm table
+
+void
+lpsa_print(FILE* stream, LocalPstateArray* lpsa)
+{
+ int i;
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream, "Local Pstate Array @ %p\n", lpsa);
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+
+ fprintf(stream, "%d Entries from %+d to %+d\n",
+ lpsa->entries, lpst_pmin(lpsa), lpst_pmax(lpsa));
+ fprintf(stream, "Step Delay Rising %u, Step Delay Falling %u\n",
+ lpsa->stepdelay_rising,
+ lpsa->stepdelay_lowering);
+
+ fprintf(stream, "Array :\n");
+ for (i = 0; i < LOCAL_PSTATE_ARRAY_ENTRIES; i+= 4) {
+ fprintf(stream, " 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n",
+ (unsigned long long)(lpsa->pstate[i].value),
+ (unsigned long long)(lpsa->pstate[i + 1].value),
+ (unsigned long long)(lpsa->pstate[i + 2].value),
+ (unsigned long long)(lpsa->pstate[i + 3].value));
+ }
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+}
+
+
+/// Print a Resonant Clocking Setup structure on a given stream
+///
+/// \param stream The output stream
+///
+/// \param resclk The ResonantClockingSetup to print
+
+void
+resclk_print(FILE* stream, ResonantClockingSetup* resclk)
+{
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+ fprintf(stream, "Resonant Clocking Setup @ %p\n", resclk);
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+
+ fprintf(stream, "Full Clock Sector Buffer Pstate : %d\n",
+ resclk->full_csb_ps);
+ fprintf(stream, "Low Frequency Resonant Lower Pstate : %d\n",
+ resclk->res_low_lower_ps);
+ fprintf(stream, "Low Frequency Resonant Upper Pstate : %d\n",
+ resclk->res_low_upper_ps);
+ fprintf(stream, "High Frequency Resonant Lower Pstate : %d\n",
+ resclk->res_high_lower_ps);
+ fprintf(stream, "High Frequency Resonant Upper Pstate : %d\n",
+ resclk->res_high_upper_ps);
+
+ fprintf(stream,
+ "---------------------------------------------------------------------------------------------------------\n");
+}
+
+
+/// Print a PstateSuperStructure on a given stream
+///
+/// \param stream The output stream
+///
+/// \param pss The PstateSuperStructure to print
+
+void
+pss_print(FILE* stream, PstateSuperStructure* pss)
+{
+ fprintf(stream,
+ "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+ fprintf(stream, "PstateSuperStructure @ %p\n", pss);
+ fprintf(stream,
+ "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+
+ gpst_print(stream, &(pss->gpst));
+ lpsa_print(stream, &(pss->lpsa));
+ resclk_print(stream, &(pss->resclk));
+
+ fprintf(stream,
+ "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+}
+
+#endif // FAPIECMD
+
+
diff --git a/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h
new file mode 100755
index 000000000..5a1b614ca
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h
@@ -0,0 +1,101 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/lab_pstates.h $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __LAB_PSTATES_H__
+#define __LAB_PSTATES_H__
+
+// $Id: lab_pstates.h,v 1.4 2013/06/12 20:01:48 mjjones Exp $
+
+/// \file lab_pstates.h
+/// \brief Lab-only (as opposed to product-procedure) support for Pstates.
+
+#include <stdint.h>
+
+// jwy #include "ssx_io.h"
+#include "pstates.h"
+
+// Error/panic codes
+
+#define IVID_INVALID_VOLTAGE 0x00484301
+#define PSTATE_STATUS_REPORT_SCOM_ERROR 0x00777701
+
+/// String storage requirement for strings used of arguments of
+/// sprintf_10uv, sprintf_vrm11() and sprintf_ivid().
+///
+/// \todo Replace with a typedef
+#define FORMAT_10UV_STRLEN 8
+
+#define FORMAT_10UV_ERROR "<Error>"
+
+#define ROUND_VOLTAGE_UP 1
+#define ROUND_VOLTAGE_DOWN -1
+
+#ifndef __ASSEMBLER__
+
+int
+vuv2vrm11(uint32_t v_uv, int round, uint8_t *vrm11_vid);
+
+int
+vrm112vuv(uint8_t vrm11_vid, uint32_t *v_uv);
+
+int
+vuv2ivid(uint32_t v_uv, int round, uint8_t *ivid);
+
+int
+ivid2vuv(uint8_t ivid, uint32_t *v_uv);
+
+int
+sprintf_10uv(char *s, uint32_t v_uv);
+
+int
+sprintf_ivid(char *s, uint8_t ivid);
+
+int
+sprintf_vrm11(char *s, uint8_t vrm11);
+
+#ifdef FAPIECMD
+
+int
+fprintf_10uv(FILE *stream, uint32_t v_uv);
+
+int
+fprintf_vrm11(FILE *stream, uint8_t vrm11);
+
+int
+fprintf_ivid(FILE *stream, uint8_t ivid);
+
+void
+gpst_print(FILE* stream, GlobalPstateTable* gpst);
+
+void
+lpsa_print(FILE* stream, LocalPstateArray* lpsa);
+
+void
+resclk_print(FILE* stream, ResonantClockingSetup* resclk);
+
+void
+pss_print(FILE* stream, PstateSuperStructure* pss);
+#endif // FAPIECMD
+
+#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
new file mode 100755
index 000000000..ba0d6be88
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.C
@@ -0,0 +1,490 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: p8_build_pstate_datablock.C,v 1.14 2013/06/12 20:05:23 mjjones 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
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//------------------------------------------------------------------------------
+// *! OWNER NAME: Jim Yacynych Email: jimyac@us.ibm.com
+// *!
+
+/// \file p8_build_pstate_datablock.C
+/// \brief
+///
+/// \todo
+/// High-level procedure flow:
+/// \verbatim
+///
+/// Procedure Prereq:
+/// o System clocks are running
+/// \endverbatim
+//------------------------------------------------------------------------------
+
+
+// ----------------------------------------------------------------------
+// Includes
+// ----------------------------------------------------------------------
+#include <fapi.H>
+#include "pstate_tables.h"
+#include "lab_pstates.h"
+#include "pstates.h"
+
+#include "p8_build_pstate_datablock.H"
+
+extern "C" {
+
+using namespace fapi;
+
+// ----------------------------------------------------------------------
+// Function prototypes
+// ----------------------------------------------------------------------
+ReturnCode proc_get_mvpd_data (const Target& i_target, uint32_t attr_mvpd_data[PV_D][PV_W]);
+ReturnCode proc_get_attributes (const Target& i_target, AttributeList *attr_list);
+// ----------------------------------------------------------------------
+// Function definitions
+// ----------------------------------------------------------------------
+/// \param[in] i_target Chip Target
+/// \param[in/out] *io_pss Reference to PstateSuperStructure
+
+/// \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;
+
+ double freq_bias = 1.0;
+ double volt_bias_vdd = 1.0;
+ double volt_bias_vcs = 1.0;
+
+ uint32_t frequency_step_khz = 0;
+ uint32_t attr_mvpd_voltage_control[PV_D][PV_W];
+
+ FAPI_INF("Executing p8_build_pstate_datablock ....");
+
+ // -------------------------
+ // get all attributes needed
+ // -------------------------
+ l_rc = proc_get_attributes(i_target , &attr );
+ if (l_rc)
+ return l_rc;
+
+ // -----------
+ // get #V data
+ // -----------
+ // clear array
+ memset(attr_mvpd_voltage_control, 0, sizeof(attr_mvpd_voltage_control));
+
+ l_rc = proc_get_mvpd_data(i_target , attr_mvpd_voltage_control);
+ if (l_rc)
+ return l_rc;
+
+ // ----------------------------------------------------
+ // Check Valid Frequency and Voltage Biasing Attributes
+ // - cannot have both up and down bias set
+ // ----------------------------------------------------
+ if (attr.attr_freq_bias_up > 0 && attr.attr_freq_bias_down > 0) {
+ FAPI_ERR("**** ERROR : Frequency bias up and down both defined");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_FREQ_BIAS_ERROR);
+ return l_rc;
+ }
+
+ if (attr.attr_voltage_ext_bias_up > 0 && attr.attr_voltage_ext_bias_down > 0) {
+ FAPI_ERR("**** ERROR : External Frequency bias up and down both defined");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_EXT_VOLTAGE_BIAS_ERROR);
+ return l_rc;
+ }
+
+ if (attr.attr_voltage_int_bias_up > 0 && attr.attr_voltage_int_bias_down > 0) {
+ FAPI_ERR("**** ERROR : Internal Frequency bias up and down both defined");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_INT_VOLTAGE_BIAS_ERROR);
+ return l_rc;
+ }
+
+ // --------------------------------------------------------------------
+ // Apply specified Frequency and Voltage Biasing to attr_mvpd_voltage_control
+ // - convert freq/voltage to double
+ // - compute biased freq/voltage and round
+ // - convert back to integer
+ // - align frequency to frequency_step_khz (attr_freq_proc_refclock/attr_proc_dpll_divider)
+ // - are (double) and (int) required???
+ // --------------------------------------------------------------------
+ frequency_step_khz = (attr.attr_freq_proc_refclock*1000)/attr.attr_proc_dpll_divider;
+
+ freq_bias = 1.0 + (0.01 * (double)attr.attr_freq_bias_up) - (0.01 * (double)attr.attr_freq_bias_down); // at least one bias value is guaranteed to be 0
+ volt_bias_vdd = 1.0 + (0.01 * (double)attr.attr_voltage_ext_bias_up) - (0.01 * (double)attr.attr_voltage_ext_bias_down); // at least one bias value is guaranteed to be 0
+ volt_bias_vcs = 1.0 + (0.01 * (double)attr.attr_voltage_ext_bias_up) - (0.01 * (double)attr.attr_voltage_ext_bias_down); // at least one bias value is guaranteed to be 0
+
+ // loop over each bucket
+ for (i=0; i <= 4; i++) {
+ attr_mvpd_voltage_control[i][0] = (uint32_t) ((( (double)attr_mvpd_voltage_control[i][0]) * freq_bias) + 0.5);
+
+ // align to frequency step as defined by attr_proc_refclk_frequency/attr_proc_dpll_divider
+ // jwy FIXME:caused float exception attr_mvpd_voltage_control[i][0] = (attr_mvpd_voltage_control[i][0] + (frequency_step_khz - (attr_mvpd_voltage_control[i][0]%frequency_step_khz))%frequency_step_khz);
+
+ attr_mvpd_voltage_control[i][1] = (uint32_t) ((( (double)attr_mvpd_voltage_control[i][1]) * volt_bias_vdd) + 0.5); // vdd
+ attr_mvpd_voltage_control[i][3] = (uint32_t) ((( (double)attr_mvpd_voltage_control[i][3]) * volt_bias_vcs) + 0.5); // vcs
+ }
+
+ // -----------------------------------------------
+ // populate VpdOperatingPoint with MVPD attributes
+ // -----------------------------------------------
+ // 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;
+ }
+
+ // -------------------------------------------------------------------
+ // 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; // pstate0 is turbo
+ s132a_parms.frequency_step_khz = frequency_step_khz; // ATTR_REFCLK_FREQUENCY/ATTR_DPLL_DIVIDER
+
+ s132a_parms.vdd_load_line_uohm = 570; // hardcoded values to use temporarily per Adrian 4/11
+ s132a_parms.vcs_load_line_uohm = 570; // hardcoded values to use temporarily per Adrian 4/11
+ s132a_parms.vdd_distribution_uohm = 500; // hardcoded values to use temporarily per Adrian 4/11
+ s132a_parms.vcs_distribution_uohm = 800; // hardcoded values to use temporarily per Adrian 4/11
+
+ // --------------------------------------
+ // 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;
+
+ // ------------------------------
+ // Clear the PstateSuperStructure and install the magic number
+ // ------------------------------
+ memset(io_pss, 0, sizeof(*io_pss));
+ (*io_pss).magic = revle64(PSTATE_SUPERSTRUCTURE_MAGIC);
+
+ // ---------------------------
+ // Finish the characterization
+ // ---------------------------
+ characterization = &s132a_characterization;
+
+ rc = chip_characterization_create(characterization,
+ characterization->vpd,
+ characterization->ops,
+ characterization->parameters,
+ characterization->points);
+
+ if (rc) {
+ int & RETURN_CODE = rc;
+ FAPI_ERR("**** ERROR : Procedure chip_characterization_create() returned %d", rc);
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_CHIP_CHARACTERIZE_ERROR);
+ return l_rc;
+ }
+
+ // ------------------------------
+ // Create the Global Pstate table
+ // ------------------------------
+ rc = gpst_create(&((*io_pss).gpst),
+ characterization,
+ PSTATE_STEPSIZE,
+ EVRM_DELAY_NS);
+
+ FAPI_DBG("gpst pmin = %d gpst entries = %d", (*io_pss).gpst.pmin, (*io_pss).gpst.entries);
+ FAPI_DBG("attr_freq_proc_refclock = %d khz", (attr.attr_freq_proc_refclock*1000));
+ FAPI_DBG("pstate0_freq = %d frequency_step = %d", s132a_parms.pstate0_frequency_khz, s132a_parms.frequency_step_khz);
+ FAPI_DBG("vpd pmin = %d vpd pmax = %d vpd points = %d", s132a_characterization.ops[0].pstate, s132a_characterization.ops[s132a_characterization.points - 1].pstate, s132a_characterization.points);
+
+ if (rc) {
+ int & RETURN_CODE = rc;
+ FAPI_ERR("**** ERROR : Procedure gpst_create() returned %d", rc);
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ERROR);
+ return l_rc;
+ }
+
+// jwy // ---------------------
+// jwy // calculate safe_pstate
+// jwy // ---------------------
+// jwy Pstate psafe_pstate;
+// jwy rc = freq2pState(&((*io_pss).gpst), (attr.attr_pm_safe_frequency * 1000), &psafe_pstate);
+// jwy
+// jwy if (rc) {
+// jwy fprintf(stderr, " freq2pState() returned %d\n", rc);
+// jwy exit(1);
+// jwy }
+// jwy
+// jwy // pstate bounds checking
+// jwy Pstate pmax;
+// jwy pmax = (*io_pss).gpst.pmin + (*io_pss).gpst.entries - 1;
+// jwy
+// jwy if (psafe_pstate > pmax) {
+// jwy fprintf(stderr, " safe frequency pstate(%d) is greater than max pstate(%d)\n", psafe_pstate, pmax);
+// jwy exit(1);
+// jwy }
+// jwy
+// jwy if (psafe_pstate < (*io_pss).gpst.pmin)
+// jwy psafe_pstate = (*io_pss).gpst.pmin;
+// jwy
+// jwy (*io_pss).gpst.psafe = psafe_pstate;
+// jwy
+// jwy // -----------------------
+// jwy // calculate pvsafe pstate
+// jwy // -----------------------
+// jwy Pstate pvsafe_pstate;
+// jwy Vid11 pvsafe_vrm11;
+// jwy gpst_entry_t entry;
+// jwy
+// jwy rc = vuv2vrm11((attr.attr_pm_safe_voltage*1000), 1, &pvsafe_vrm11); // assume attr_pm_safe_voltage is in millivolts
+// jwy rc = gpst_vdd2pstate(&((*io_pss).gpst), pvsafe_vrm11, &pvsafe_pstate, &entry);
+// jwy (*io_pss).gpst.pvsafe = pvsafe_pstate;
+
+
+
+ // Force optional overrides
+ (*io_pss).gpst.options.options = revle32(revle32((*io_pss).gpst.options.options) |
+ PSTATE_NO_INSTALL_LPSA |
+ PSTATE_NO_INSTALL_RESCLK |
+ PSTATE_FORCE_INITIAL_PMIN);
+ // ------------------------------
+ // Create the Global Pstate table
+ // ------------------------------
+ rc = lpst_create( &((*io_pss).gpst), &((*io_pss).lpsa), DEAD_ZONE_5MV);
+
+ if (rc) {
+// int & RETURN_CODE = rc;
+ FAPI_ERR("**** ERROR : Procedure lpst_create() returned %d", rc);
+ // FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ERROR);
+ // return l_rc;
+ }
+
+ // print global pstate table
+// jwy gpst_print(stdout, &(*io_pss).gpst);
+
+// Attributes to write
+// -------------------
+// uint32_t ATTR_PM_PSTATE0_FREQUENCY // Binary in Khz
+
+ return l_rc;
+}
+
+
+
+/// \brief Get needed attributes
+/// \param[in] i_target => Chip Target
+/// \param[inout] attr => pointer to attribute list structure
+
+ReturnCode proc_get_attributes(const Target& i_target, AttributeList *attr) {
+ ReturnCode l_rc;
+
+ // --------------------------
+ // attributes not yet defined
+ // --------------------------
+ attr->attr_dpll_bias = 0;
+ attr->attr_undervolting = 0;
+ attr->attr_freq_bias_up = 0;
+ attr->attr_freq_bias_down = 0;
+ attr->attr_voltage_ext_bias_up = 0;
+ attr->attr_voltage_ext_bias_down = 0;
+ attr->attr_voltage_int_bias_up = 0;
+ attr->attr_voltage_int_bias_down = 0;
+
+ attr->attr_dpll_bias = 0;
+ attr->attr_undervolting = 0;
+ attr->attr_pm_safe_voltage = 925; // assume millivolts until it is defined in attraibute
+ attr->attr_proc_dpll_divider = 4;
+
+ l_rc = FAPI_ATTR_GET(ATTR_FREQ_PROC_REFCLOCK, NULL, attr->attr_freq_proc_refclock); if (l_rc) return l_rc;
+// jwy l_rc = FAPI_ATTR_GET(ATTR_PROC_DPLL_DIVIDER, NULL, attr->attr_proc_dpll_divider); if (l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_FREQ_CORE_MAX, NULL, attr->attr_freq_core_max); if (l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_PROC_R_LOADLINE, NULL, attr->attr_proc_r_loadline); if (l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_PROC_R_DISTLOSS, NULL, attr->attr_proc_r_distloss); if (l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_PROC_VRM_VOFFSET, NULL, attr->attr_proc_vrm_voffset); if (l_rc) return l_rc;
+
+ l_rc = FAPI_ATTR_GET(ATTR_PM_SAFE_FREQUENCY, NULL, attr->attr_pm_safe_frequency); if (l_rc) return l_rc;
+
+ l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_FULL_CLOCK_SECTOR_BUFFER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_full_clock_sector_buffer_frequency); if (l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_LOW_BAND_LOWER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_low_band_lower_frequency); if (l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_LOW_BAND_UPPER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_low_band_upper_frequency); if (l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_HIGH_BAND_LOWER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_high_band_lower_frequency); if (l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_PM_RESONANT_CLOCK_HIGH_BAND_UPPER_FREQUENCY, NULL, attr->attr_pm_resonant_clock_high_band_upper_frequency); if (l_rc) return l_rc;
+
+ return l_rc;
+}
+
+/// \brief Get #V data and put into array
+/// \param[in] i_target => Chip Target
+/// \param[inout] attr_mvpd_data => 5x5 array to hold the #V data
+
+ReturnCode proc_get_mvpd_data(const Target& i_target, uint32_t attr_mvpd_data[PV_D][PV_W]) {
+ ReturnCode l_rc;
+ std::vector<fapi::Target> l_exChiplets;
+ uint8_t l_functional = 0;
+ uint8_t * l_buffer = reinterpret_cast<uint8_t *>(malloc(512) );
+ uint32_t l_bufferSize = 512;
+ uint32_t l_record = 0;
+ uint32_t chiplet_mvpd_data[PV_D][PV_W];
+ uint8_t j = 0;
+ uint8_t i = 0;
+ uint8_t ii = 0;
+ uint8_t first_chplt = 1;
+
+ // -----------------------------------------------------------------
+ // 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!");
+ return l_rc;
+ }
+
+ for (j=0; j < l_exChiplets.size(); j++) {
+
+ // Determine if it's functional
+ l_rc = FAPI_ATTR_GET(ATTR_FUNCTIONAL, &l_exChiplets[j], l_functional);
+ if (l_rc) {
+ FAPI_ERR("fapiGetAttribute of ATTR_FUNCTIONAL error");
+ return l_rc;
+ }
+ else {
+
+ if ( l_functional ) {
+ l_bufferSize = 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");
+ return l_rc;
+ }
+
+ // set l_record to appropriate lprx record (add core number to lrp0)
+ l_record = (uint32_t)fapi::MVPD_RECORD_LRP0 + l_chipNum;
+
+ // 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");
+ return l_rc;
+ }
+
+ // check buffer size
+ if (l_bufferSize < MVPD_BUFFER_SIZE) {
+ FAPI_ERR("**** ERROR : Worng size buffer returned from fapiGetMvpdField => %d", l_bufferSize );
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_DATABLOCK_MVPD_BUFFER_SIZE_ERROR);
+ return l_rc;
+ }
+
+ // 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) ) ))
+ l_buffer++;
+
+ for (i=0; i<=4; i++) {
+
+ for (ii=0; ii<=4; ii++) {
+ chiplet_mvpd_data[i][ii] = (uint32_t) UINT16_GET(l_buffer);
+ FAPI_DBG("%04X %-6d", chiplet_mvpd_data[i][ii], chiplet_mvpd_data[i][ii]);
+ // increment to next MVPD value in buffer
+ l_buffer+= 2;
+ }
+ }
+
+ // 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 bucket 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]) ) {
+
+ FAPI_ERR("**** ERROR : Procedure gpst_create() returned ");
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_PSTATE_MVPD_CHIPLET_VOLTAGE_NOT_EQUAL);
+ return l_rc;
+ }
+ }
+
+ // 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];
+ }
+ }
+ } // end if l_functional
+ else { // Not Functional so skip it
+ }
+ }
+ } // end for loop
+
+ return l_rc;
+
+} // end proc_get_mvpd_data
+
+
+} //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
new file mode 100755
index 000000000..e883fc819
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.H
@@ -0,0 +1,88 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: p8_build_pstate_datablock.H,v 1.7 2013/05/03 15:57:32 jimyac Exp $
+#ifndef _P8_BUILD_PSTATE_DATABLOCK_H_
+#define _P8_BUILD_PSTATE_DATABLOCK_H_
+
+#include <fapi.H>
+
+// function pointer typedef definition for HWP call support
+typedef fapi::ReturnCode (*p8_build_pstate_datablock_FP_t) (const fapi::Target&, PstateSuperStructure*);
+
+extern "C" {
+
+//------------------------------------------------------------------------------
+// Function prototype
+//------------------------------------------------------------------------------
+/// \brief Build Pstate Tables
+/// \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);
+
+} // extern "C"
+
+#define S132A_POINTS 3
+#define PSTATE_STEPSIZE 1
+#define EVRM_DELAY_NS 100
+#define DEAD_ZONE_5MV 20
+#define MVPD_BUFFER_SIZE 51
+
+// #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
+const uint8_t pv_op_order[S132A_POINTS] = {1, 0, 2};
+
+typedef struct {
+ uint32_t attr_freq_core_max; // = 0; // MHz
+ uint32_t attr_proc_r_loadline; // = 0; // Impedance (binary in microOhms)
+ uint32_t attr_proc_r_distloss; // = 0; // Impedance (binary in microOhms)
+ uint32_t attr_proc_vrm_voffset; // = 0; // Offset voltage (binary in microvolts)
+
+ uint32_t attr_freq_proc_refclock; // = 133 ; // Mhz
+ uint32_t attr_proc_dpll_divider; // = 4;
+
+ uint32_t attr_freq_bias_up; // = 0;
+ uint32_t attr_freq_bias_down; // = 0;
+ uint32_t attr_voltage_ext_bias_up; // = 0;
+ uint32_t attr_voltage_ext_bias_down; // = 0;
+ uint32_t attr_voltage_int_bias_up; // = 0;
+ uint32_t attr_voltage_int_bias_down; // = 0;
+
+ uint32_t attr_dpll_bias;
+ uint32_t attr_undervolting;
+ uint32_t attr_pm_safe_voltage;
+ uint8_t attr_pm_safe_frequency; // = 0; // pstate value -128 thru 127 *** FIXME - comes in as unsigned, how to I make signed???
+
+ uint32_t attr_pm_resonant_clock_full_clock_sector_buffer_frequency; // = 0; // Mhz
+ uint32_t attr_pm_resonant_clock_low_band_lower_frequency; // = 0; // Mhz
+ uint32_t attr_pm_resonant_clock_low_band_upper_frequency; // = 0; // Mhz
+ uint32_t attr_pm_resonant_clock_high_band_lower_frequency; // = 0; // Mhz
+ uint32_t attr_pm_resonant_clock_high_band_upper_frequency; // = 0; // Mhz
+
+} AttributeList;
+
+#endif
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
new file mode 100755
index 000000000..04d3585c8
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml
@@ -0,0 +1,63 @@
+<!-- IBM_PROLOG_BEGIN_TAG -->
+<!-- This is an automatically generated prolog. -->
+<!-- -->
+<!-- $Source: src/usr/hwpf/hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml $ -->
+<!-- -->
+<!-- IBM CONFIDENTIAL -->
+<!-- -->
+<!-- COPYRIGHT International Business Machines Corp. 2013 -->
+<!-- -->
+<!-- p1 -->
+<!-- -->
+<!-- Object Code Only (OCO) source materials -->
+<!-- Licensed Internal Code Source Materials -->
+<!-- IBM HostBoot Licensed Internal Code -->
+<!-- -->
+<!-- The source code for this program is not published or otherwise -->
+<!-- divested of its trade secrets, irrespective of what has been -->
+<!-- deposited with the U.S. Copyright Office. -->
+<!-- -->
+<!-- Origin: 30 -->
+<!-- -->
+<!-- IBM_PROLOG_END_TAG -->
+<!-- $Id: p8_build_pstate_datablock_errors.xml,v 1.5 2013/05/03 16:10:11 jimyac Exp $ -->
+<!-- Error definitions for p8_build_pstate_datablock procedure -->
+<hwpErrors>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_MVPD_BUFFER_SIZE_ERROR</rc>
+ <description>MVPD Buffer returned is wrong size</description>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_MVPD_CHIPLET_VOLTAGE_NOT_EQUAL</rc>
+ <description>MVPD Bucket Frequency was not equal per chiplet</description>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_FREQ_BIAS_ERROR</rc>
+ <description>Cannot have both up and down bias set</description>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_EXT_VOLTAGE_BIAS_ERROR</rc>
+ <description>Cannot have both up and down bias set</description>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_INT_VOLTAGE_BIAS_ERROR</rc>
+ <description>Cannot have both up and down bias set</description>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_CHIP_CHARACTERIZE_ERROR</rc>
+ <description>Procedure chip_characterization_create() returned an error</description>
+ <ffdc>RETURN_CODE</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_PSTATE_DATABLOCK_GPST_CREATE_ERROR</rc>
+ <description>Procedure gpst_create() returned an error</description>
+ <ffdc>RETURN_CODE</ffdc>
+ </hwpError>
+</hwpErrors>
diff --git a/src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.C b/src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.C
new file mode 100755
index 000000000..f3c0631ec
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.C
@@ -0,0 +1,138 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: proc_get_voltage.C,v 1.5 2013/05/02 17:33:30 jimyac Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_get_voltage.C,v $
+//------------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2012
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//------------------------------------------------------------------------------
+// *! OWNER NAME: Jim Yacynych Email: jimyac@us.ibm.com
+// *!
+
+/// \file proc_get_voltage.C
+/// \brief
+///
+/// \todo
+/// High-level procedure flow:
+/// \verbatim
+///
+/// Procedure Prereq:
+/// o System clocks are running
+/// \endverbatim
+//------------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------
+// Includes
+// ----------------------------------------------------------------------
+#include <fapi.H>
+
+#include "pstate_tables.h"
+#include "lab_pstates.h"
+#include "pstates.h"
+
+#include "proc_get_voltage.H"
+
+extern "C" {
+
+using namespace fapi;
+
+// ----------------------------------------------------------------------
+// Function prototypes
+// ----------------------------------------------------------------------
+//ReturnCode freq2pState(uint32_t freq, PstateSuperStructure *pss, int32_t& pstate);
+
+// ----------------------------------------------------------------------
+// Function definitions
+// ----------------------------------------------------------------------
+/// \param[in] i_target Chip Target
+/// \param[in] i_freq_mhz frequency in Mhz
+/// \param[out] *o_vdd_vid vdd vid value
+/// \param[out] *o_vcs_vid vcs vid value
+
+/// \retval FAPI_RC_SUCCESS
+/// \retval ERROR defined in xml
+
+ReturnCode
+proc_get_voltage(const Target& i_target, const uint32_t i_freq_mhz, uint8_t& o_vdd_vid, uint8_t& o_vcs_vid)
+{
+ fapi::ReturnCode l_rc;
+ int rc = 0;
+ PstateSuperStructure pss;
+ gpst_entry_t entry;
+ Pstate freq_pstate = 0;
+ Pstate pmax = 0;
+ uint8_t freq_pstate_index = 0;
+
+ // -----------------------------
+ // create pstate super structure
+ // -----------------------------
+ FAPI_INF("Executing p8_build_pstate_datablock");
+
+ FAPI_EXEC_HWP(l_rc, p8_build_pstate_datablock, i_target, &pss);
+ if (!l_rc.ok()) {
+ FAPI_ERR("Error calling p8_build_pstate_datablock");
+ return l_rc;
+ }
+
+ // ----------------------
+ // convert freq to pstate
+ // ----------------------
+ rc = freq2pState(&(pss.gpst), (i_freq_mhz*1000), &freq_pstate);
+
+ if (rc) {
+ int & RETURN_CODE = rc;
+ FAPI_ERR("**** ERROR : Procedure freq2pState() returned %d", rc);
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_GET_VOLTAGE_FREQ2PSTATE_ERROR);
+ return l_rc;
+ }
+
+ // ----------------------
+ // pstate bounds checking
+ // ----------------------
+ pmax = pss.gpst.pmin + pss.gpst.entries - 1;
+
+ FAPI_DBG("freq_pstate = %d pmax = %d pmin = %d entries = %d i_freq_mhz = %d\n", freq_pstate, pmax, pss.gpst.pmin, pss.gpst.entries, i_freq_mhz);
+
+ if (freq_pstate > pmax) {
+ FAPI_ERR("**** ERROR : Pstate for given frequency is greater than pmax %d > %d (pmax)", freq_pstate, pmax);
+ FAPI_SET_HWP_ERROR(l_rc, RC_PROCPM_GET_VOLTAGE_FREQ_PSTATE_GT_PMAX_ERROR);
+ return l_rc;
+ }
+
+ if (freq_pstate < pss.gpst.pmin) {
+ freq_pstate = pss.gpst.pmin;
+ }
+
+ // --------------------------------------------------------
+ // convert pstate to pstate table index and lookup voltages
+ // --------------------------------------------------------
+ freq_pstate_index = freq_pstate - pss.gpst.pmin;
+ entry.value = revle64(pss.gpst.pstate[freq_pstate_index].value);
+ o_vdd_vid = entry.fields.evid_vdd;
+ o_vcs_vid = entry.fields.evid_vcs;
+ return l_rc;
+}
+
+} //end extern C
+
diff --git a/src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.H b/src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.H
new file mode 100755
index 000000000..737e58d5f
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.H
@@ -0,0 +1,49 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: proc_get_voltage.H,v 1.3 2012/12/10 19:28:57 jimyac Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_get_voltage.H,v $
+#ifndef _proc_get_voltage_H_
+#define _proc_get_voltage_H_
+
+#include <fapi.H>
+#include "p8_build_pstate_datablock.H"
+
+// function pointer typedef definition for HWP call support
+typedef fapi::ReturnCode (*proc_get_voltage_FP_t) (const fapi::Target&,const uint32_t, uint8_t &, uint8_t &);
+
+extern "C" {
+
+//------------------------------------------------------------------------------
+// Function prototype
+//------------------------------------------------------------------------------
+/// \brief Build Pstate Tables
+/// \param[in] i_target Chip Target
+/// \param[in] i_freq_mhz frequency in Mhz
+/// \param[out] o_vdd_vid vdd value for given frequency
+/// \param[out] o_vcs_vid vcs value for given frequency
+
+fapi::ReturnCode proc_get_voltage(const fapi::Target& i_target, const uint32_t i_freq_mhz, uint8_t& o_vdd_vid, uint8_t& o_vcs_vid);
+
+} // extern "C"
+
+#endif
diff --git a/src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage_errors.xml b/src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage_errors.xml
new file mode 100755
index 000000000..f74331a2b
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage_errors.xml
@@ -0,0 +1,37 @@
+<!-- IBM_PROLOG_BEGIN_TAG -->
+<!-- This is an automatically generated prolog. -->
+<!-- -->
+<!-- $Source: src/usr/hwpf/hwp/pstates/pstates/proc_get_voltage_errors.xml $ -->
+<!-- -->
+<!-- IBM CONFIDENTIAL -->
+<!-- -->
+<!-- COPYRIGHT International Business Machines Corp. 2013 -->
+<!-- -->
+<!-- p1 -->
+<!-- -->
+<!-- Object Code Only (OCO) source materials -->
+<!-- Licensed Internal Code Source Materials -->
+<!-- IBM HostBoot Licensed Internal Code -->
+<!-- -->
+<!-- The source code for this program is not published or otherwise -->
+<!-- divested of its trade secrets, irrespective of what has been -->
+<!-- deposited with the U.S. Copyright Office. -->
+<!-- -->
+<!-- Origin: 30 -->
+<!-- -->
+<!-- IBM_PROLOG_END_TAG -->
+<!-- $Id: proc_get_voltage_errors.xml,v 1.5 2013/05/03 16:10:12 jimyac Exp $ -->
+<!-- Error definitions for proc_get_voltage procedure -->
+<hwpErrors>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_GET_VOLTAGE_FREQ_PSTATE_GT_PMAX_ERROR</rc>
+ <description>Pstate for given frequency is greater than pmax</description>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROCPM_GET_VOLTAGE_FREQ2PSTATE_ERROR</rc>
+ <description>Procedure freq2pState() returned an error</description>
+ <ffdc>RETURN_CODE</ffdc>
+ </hwpError>
+</hwpErrors>
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c
new file mode 100755
index 000000000..5212b1a76
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c
@@ -0,0 +1,716 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/pstate_tables.c $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: pstate_tables.c,v 1.8 2013/06/12 20:02:07 mjjones Exp $
+
+/// \file pstate_tables.c
+/// \brief This file contains code used to generate Pstate tables from real or
+/// imagined chip characterizations.
+///
+/// This code is never run as part of OCC firmware, as Pstate tables are
+/// always "given" to OCC either from the FSP (OCC product firmware), or by
+/// being built-in the image (lab images).
+
+#include <stdint.h>
+#include <stdio.h>
+#include "lab_pstates.h"
+#include "pstate_tables.h"
+
+
+#define MAX(X, Y) \
+ ({ \
+ typeof (X) __x = (X); \
+ typeof (Y) __y = (Y); \
+ (__x > __y) ? __x : __y; \
+ })
+
+static int
+cntlz32(uint32_t x)
+{
+ return __builtin_clz(x);
+}
+
+
+/// Byte-reverse a 16-bit integer if on a little-endian machine
+
+uint16_t
+revle16(uint16_t i_x)
+{
+ uint16_t rx;
+
+#ifndef _BIG_ENDIAN
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[1];
+ prx[1] = pix[0];
+#else
+ rx = i_x;
+#endif
+
+ return rx;
+}
+
+
+/// Byte-reverse a 32-bit integer if on a little-endian machine
+
+uint32_t
+revle32(uint32_t i_x)
+{
+ uint32_t rx;
+
+#ifndef _BIG_ENDIAN
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[3];
+ prx[1] = pix[2];
+ prx[2] = pix[1];
+ prx[3] = pix[0];
+#else
+ rx = i_x;
+#endif
+
+ return rx;
+}
+
+
+/// Byte-reverse a 64-bit integer if on a little-endian machine
+
+uint64_t
+revle64(const uint64_t i_x)
+{
+ uint64_t rx;
+
+#ifndef _BIG_ENDIAN
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[7];
+ prx[1] = pix[6];
+ prx[2] = pix[5];
+ prx[3] = pix[4];
+ prx[4] = pix[3];
+ prx[5] = pix[2];
+ prx[6] = pix[1];
+ prx[7] = pix[0];
+#else
+ rx = i_x;
+#endif
+
+ return rx;
+}
+
+/// Create a ChipCharacterization from an array of VPD operating points and
+/// characterization parameters.
+///
+/// \param characterization An uninitialized or unused ChipCharacterization
+/// structure.
+///
+/// \param vpd An initialized array of VpdOperatingPoints, sorted by increasing
+/// frequency. Note that there must be at least 1 DPLL frequency code step (1
+/// Pstate step) between each VPD operating point in order to use the
+/// characterization to create a Pstate table.
+///
+/// \param ops An uninitialized array of OperatingPoint, this array will be
+/// intialized by this API.
+///
+/// \param parameters An initialized OperatingPointParameters structure
+///
+/// \param points The (non-negative) number of operating points
+///
+/// \retval 0 Success
+///
+/// \returns Other return codes indicate errors.
+
+int
+chip_characterization_create(ChipCharacterization *characterization,
+ VpdOperatingPoint *vpd,
+ OperatingPoint *ops,
+ OperatingPointParameters *parameters,
+ int points)
+{
+ int rc, i;
+ uint32_t pstate0_code;
+ uint8_t gpst_points = 0; // jwy
+ uint32_t curr_pstate_code = 0; // jwy
+ uint32_t next_pstate_code = 0; // jwy
+
+
+ do {
+ rc = 0;
+
+ if ((characterization == 0) || (parameters == 0)) {
+ rc = -GPST_INVALID_OBJECT;
+ break;
+ }
+ if ((vpd == 0) || (points <= 0)) {
+ rc = -GPST_INVALID_ARGUMENT;
+ break;
+ }
+
+ characterization->vpd = vpd;
+ characterization->ops = ops;
+ characterization->parameters = parameters;
+ characterization->points = points;
+
+ // Now convert the array of VPD operating point to the array of
+ // internal operating points
+ //
+ // For frequencies and characterization voltages and currents this is
+ // simple math. Creating load-line corrected volatges requires
+ // multiplying worst-case currents by the effective load-line
+ // resistance.
+ //
+ // Note that the Pstate computation is made relative to the Pstate 0
+ // frequency code (DPLL input). It's done this way so that
+ // frequencies with non-integral codes always round down (to lower
+ // frequencies).
+
+ pstate0_code =
+ parameters->pstate0_frequency_khz / parameters->frequency_step_khz;
+
+ for (i = 0; i < points; i++) {
+
+ // jwy 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) {
+ next_pstate_code = vpd[i+1].frequency_mhz * 1000 / parameters->frequency_step_khz;
+ }
+
+ 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;
+
+ ops[gpst_points].idd_ma = vpd[i].idd_500ma * 500;
+ ops[gpst_points].ics_ma = vpd[i].ics_500ma * 500;
+
+ ops[gpst_points].frequency_khz = vpd[i].frequency_mhz * 1000;
+
+ // 'Corrected' voltages values add in the load-line & distribution IR drop
+
+ 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].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
+
+ // iVRM 'Effective' voltages are set to the measured voltages
+
+ ops[gpst_points].vdd_ivrm_effective_uv = ops[gpst_points].vdd_uv;
+ ops[gpst_points].vcs_ivrm_effective_uv = ops[gpst_points].vcs_uv;
+
+ ops[gpst_points].pstate =
+ (ops[gpst_points].frequency_khz / parameters->frequency_step_khz) -
+ pstate0_code;
+
+ 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
+ characterization->points = gpst_points;
+
+ } while (0);
+
+ return rc;
+}
+
+
+// Set up GPST Pstate stepping parameters
+//
+// \param gpst A GlobalPstateTable object to be initialized with the stepping
+// setup.
+//
+// \param pstate_stepsize Unsigned 7 bit (baby-) stepsize for Pstate
+// transitions between the Global Pstate Actual and the Global Pstate
+// Target. The value 0 is considered illegal here.
+//
+// \param vrm_delay_ns This value defines the voltage settling delay (in
+// nano-seconds) after each voltage change sequenced by the GPSM. This
+// includes all voltage changes \e except those explicitly managed by
+// firmware manipulation of the SPIVID interface. Legal values range from 0
+// up to approximately 1,600,000 (1.6ms). The VRM step delay is stored using
+// an exponential encoding. The step delay computed here is a
+// normalized (if possible) exponential encoding for highest accuracy.
+//
+// \note The caller is responsible for the mode-correctness of this call.
+// The call should only be made when the GPSM is quiesced.
+//
+// \retval 0 Success
+//
+// \retval -GPST_INVALID_ARGUMENT Either argument was invalid in some way.
+
+#define NEST_FREQUENCY_KHZ 2400000
+
+int
+gpst_stepping_setup(GlobalPstateTable* gpst,
+ int pstate_stepsize,
+ int vrm_delay_ns)
+{
+ uint32_t cycles;
+ int rc, sigbits, stepdelay_range, stepdelay_value;
+
+ do {
+ rc = 0;
+
+ if ((pstate_stepsize <= 0) ||
+ (pstate_stepsize > PSTATE_STEPSIZE_MAX) ||
+ (vrm_delay_ns < 0) ||
+ (vrm_delay_ns > VRM_STEPDELAY_MAX)) {
+ rc = -GPST_INVALID_ARGUMENT;
+ break;
+ }
+
+ // Compute the number of pervasive / 2 cycles implied by the delay.
+ // This is the frequency of the VRM stepper 'tick'. The base time
+ // source for VRM stepping is therefore nest clock / 8.
+
+ cycles = (((NEST_FREQUENCY_KHZ / 1000) * vrm_delay_ns) / 1000) /
+ (1 << LOG2_VRM_STEPDELAY_DIVIDER);
+
+ // Normalize the exponential encoding
+
+ sigbits = 32 - cntlz32(cycles);
+ stepdelay_range = (sigbits - VRM_STEPDELAY_RANGE_BITS);
+
+ if (stepdelay_range < 0)
+ {
+ stepdelay_range = 0;
+ }
+
+ stepdelay_value = cycles >> (stepdelay_range + LOG2_VRM_STEPDELAY_DIVIDER);
+
+ if (stepdelay_range > ((1u << VRM_STEPDELAY_RANGE_BITS) - 1)) {
+ rc = -GPST_INVALID_ARGUMENT;
+ break;
+ }
+
+ gpst->pstate_stepsize = pstate_stepsize;
+ gpst->vrm_stepdelay_range = stepdelay_range;
+ gpst->vrm_stepdelay_value = stepdelay_value;
+
+ } while (0);
+
+ return rc;
+}
+
+
+// Create (initialize) a GPST entry from an operating point.
+//
+// Most of the voltages are straightforward - note that vuv2vrm11 rounds the
+// voltages safely.
+//
+// The specification requires that Vcs be given as a signed offset. The Vcs
+// offset is a simple signed number of VID steps (not a crazy inverted
+// encoding like the Vdd VID code). We're always going to round the VCS offset
+// up (greater Vdiff). A fine point - we add the original offset to the
+// VRM-11 form of the voltage, not the original voltage, further potentially
+// increasing Vdiff.
+//
+// -*- NB : Note a subtle point about endianess here: The gpst_entry_t is
+// coded to allow the correct creation of the uint64_t form of the object on
+// big/little endian machines. However, the 'gpe' pointer here is a pointer
+// to a structure in a memory image, and using the host-endian form of the
+// structure is wrong - in this case we always need to use the big-endian
+// form! So we first construct the entry as an integer, then reverse it into
+// the image.
+
+static int
+gpst_entry_create(gpst_entry_t *entry, OperatingPoint *op)
+{
+ int rc;
+ uint8_t vid;
+// jwy int32_t vcs_offset;
+// jwy uint32_t vdd_uv;
+ gpst_entry_t gpe;
+
+ do {
+
+ // Clear the entry and do the straightforward conversions
+
+ gpe.value = 0;
+
+#define __SET(type, round, gpe_field, op_field) \
+ rc = vuv2##type(op->op_field, round, &vid); \
+ 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);
+
+ // Add the check byte
+
+ uint8_t gpstCheckByte(uint64_t gpstEntry);
+ gpe.fields.ecc = gpstCheckByte(gpe.value);
+
+ } while (0);
+
+ // Byte reverse the entry into the image.
+
+ entry->value = revle64(gpe.value);
+ return rc;
+}
+
+
+// Linear interpolation of voltages
+
+static uint32_t
+interpolate(uint32_t base, uint32_t next, int step, int steps)
+{
+ return base + (((next - base) * step) / steps);
+}
+
+
+/// Create a global Pstate table from an array of internal operating points
+///
+/// \param gpst A pointer to a GlobalPstateTable structure. This structure
+/// must not currently be in use as the PMC Global Pstate Table.
+///
+/// \param characterization An initialized ChipCharacterization. The
+/// operating point table must be sorted in ascending order by both Pstate and
+/// (uncorrected) Vdd and Vcs voltages. The range of Pstates in the table must
+/// also physicaly fit within the physical number of entries.
+///
+/// \param pstate_stepsize Pstate step size
+///
+/// \param evrm_delay_ns External VRM delay in nano-seconds
+///
+/// This routine creates a GlobalPstateTable by linear interpolation of
+/// corrected voltages between characterized operating points.
+///
+/// Defaults - Can be overidden later:
+///
+/// - The Psafe is always set to the minimum Pstate
+/// - The dpll_fmax_bias is set to 0 for all cores
+/// - The undervolting bias is set to 0
+/// - The pstate0_frequency_code is det to the default value for all cores.
+///
+/// This routine always checks for errors
+///
+/// \retval 0 Success
+///
+/// \retval -GPST_INVALID_OBJECT Either the \a gpst or \a ops were NULL (0) or
+/// obviously invalid or incorrectly initialized.
+///
+/// \retval -GPST_INVALID_ARGUMENT This code indicates one of several types of
+/// errors that may occur in the \a ops.
+///
+/// \retval -VRM_INVALID_VOLTAGE A characterized or interpolated voltage can
+/// not be represented as a VRM-11 VID code.
+
+int
+gpst_create(GlobalPstateTable *gpst,
+ ChipCharacterization *characterization,
+ int pstate_stepsize,
+ int evrm_delay_ns)
+{
+ OperatingPoint *ops, interp;
+ int rc, points, i, entry, pstate;
+ int32_t pmin, pmax;
+ uint8_t fNom;
+
+ do {
+ rc = 0;
+
+ // Basic pointer checks
+
+ if ((gpst == 0) || (characterization == 0)) {
+ rc = -GPST_INVALID_OBJECT;
+ break;
+ }
+
+ // Check for null or illegal operating point tables
+
+ ops = characterization->ops;
+ points = characterization->points;
+
+ if ((ops == 0) || (points <= 0)) {
+ rc = -GPST_INVALID_OBJECT;
+ break;
+ }
+
+ pmin = ops[0].pstate;
+ pmax = ops[points - 1].pstate;
+
+ // 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
+ // table of operating points does not include operating points for
+ // frequencies below Fmax@Vmin.
+
+ if ((pmin < PSTATE_MIN) ||
+ (pmax > PSTATE_MAX) ||
+ ((pmax - pmin + 1) > GLOBAL_PSTATE_TABLE_ENTRIES)) {
+ rc = -GPST_INVALID_ARGUMENT;
+ 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;
+ break;
+ }
+ }
+ if (rc) break;
+
+ // Update the table from VPD/system parameters, then default the
+ // pstate0_frequency_code (fNom) to the 'nominal' code and set the
+ // DPLL bias to 0.
+
+ gpst->pstate0_frequency_khz =
+ revle32(characterization->parameters->pstate0_frequency_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.
+ // The gpst_entry_create() function then creates the GPST entry from
+ // the operating point. Only the voltages are interpolated, and they
+ // are all interpolated in units of micro-Volts.
+
+ 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;
+ 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;
+
+#define __INTERPOLATE(field) \
+ do { \
+ interp.field = \
+ interpolate(ops[i - 1].field, ops[i].field, \
+ (pstate - ops[i - 1].pstate), \
+ (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;
+ }
+ entry++;
+ }
+ if (rc) break;
+
+ // Set the characterized Pstate
+ if (gpst_entry_create(&(gpst->pstate[entry]), &(ops[i]))) {
+ rc = -GPST_INVALID_ENTRY;
+ break;
+ }
+ entry++;
+ }
+ if (rc) break;
+
+ // Fill in the defaults
+
+ gpst->pvsafe = gpst->pmin;
+
+ fNom = revle32(gpst->pstate0_frequency_khz) /
+ revle32(gpst->frequency_step_khz);
+
+ for (i = 0; i < PGP_NCORES; i++) {
+ gpst->pstate0_frequency_code[i] = revle16(fNom);
+ gpst->dpll_fmax_bias[i] = 0;
+ }
+
+ } while (0);
+
+ return rc;
+}
+
+
+
+int
+lpst_create(const GlobalPstateTable *gpst, LocalPstateArray *lpsa, const uint8_t dead_zone_5mv)
+{
+ int rc = 0;
+ int i,j;
+ gpst_entry_t entry;
+ uint32_t turbo_uv;
+ uint32_t v_uv;
+ uint32_t vdd_uv;
+ uint8_t v_ivid;
+ uint32_t lpst_max_uv;
+ uint8_t lpst_entries;
+ uint8_t lpst_entries_div4;
+ uint8_t gpst_index;
+ Pstate lpst_pmin;
+ uint8_t vid_incr[3] = {0,0,0};
+
+ do {
+
+ // Basic pointer checks
+ if (lpsa == 0) {
+ rc = -LPST_INVALID_OBJECT;
+ break;
+ }
+
+ // ------------------------------------------------------------------
+ // find lspt_max in gpst
+ // - lpst_max is gpst entry that is equal to (turbo_vdd - deadzone)
+ // ------------------------------------------------------------------
+ entry.value = revle64(gpst->pstate[(gpst->entries)-1].value);
+ rc = vrm112vuv(entry.fields.evid_vdd, &turbo_uv);
+ lpst_max_uv = turbo_uv - (dead_zone_5mv * 5000);
+
+ for (i = gpst->entries -1 ; i >= 0; i--) {
+ entry.value = revle64(gpst->pstate[i].value);
+ vrm112vuv(entry.fields.evid_vdd, &v_uv);
+
+ if (lpst_max_uv >= v_uv)
+ break;
+ }
+
+ lpst_entries = i + 1;
+ lpst_pmin = 0 - lpst_entries + 1;
+
+// jwy printf("turbo_uv = %d lpst_max_uv = %d entries = %d lpst_pmin = %d\n", turbo_uv, lpst_max_uv, lpst_entries, lpst_pmin);
+
+ // ----------------------------------------------------------------------------
+ // 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;
+ if ( lpst_entries % 4 != 0)
+ lpst_entries_div4++;
+
+ for (i = 0 ; i < lpst_entries_div4; i++) {
+ entry.value = revle64(gpst->pstate[gpst_index].value);
+
+ // compute ivid_vdd
+ rc = vrm112vuv(entry.fields.evid_vdd, &vdd_uv);
+ rc = vuv2ivid(vdd_uv, ROUND_VOLTAGE_DOWN, &v_ivid);
+ lpsa->pstate[i].fields.ivid_vdd = v_ivid;
+
+ // compute ivid_vcs
+ rc = vrm112vuv(entry.fields.evid_vcs, &v_uv);
+ rc = vuv2ivid(v_uv, ROUND_VOLTAGE_DOWN, &v_ivid);
+ lpsa->pstate[i].fields.ivid_vcs = v_ivid;
+
+ // --------------------------------------------------------------
+ // compute increment for remaining 3 pstates for this lpst entry
+ // --------------------------------------------------------------
+ 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;
+
+ entry.value = revle64(gpst->pstate[gpst_index].value);
+ rc = vrm112vuv(entry.fields.evid_vdd, &vdd_uv);
+ rc = vuv2ivid(vdd_uv, ROUND_VOLTAGE_DOWN, &v_ivid);
+ vid_incr[j] = v_ivid - lpsa->pstate[i].fields.ivid_vdd;
+ }
+
+ 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 = 0;
+ float iac_wc;
+ float iac;
+ float vout;
+ float pwrratio_f;
+ uint8_t pwrratio;
+
+ // convert to mV (note: vdd_uv is the max of the vdd values for this lpst entry)
+ vout = (float)(vdd_uv/1000);
+
+ // 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;
+ 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;
+
+ // ??? what should these be ??? set to 1 for now
+ lpsa->pstate[i].fields.inc_step = 1;
+ lpsa->pstate[i].fields.dec_step = 1;
+
+// jwy printf (" %d %X %X %f %d %d %d %d\n", i, (uint32_t)lpsa->pstate[i].fields.ivid_vdd, (uint32_t)lpsa->pstate[i].fields.ivid_vcs, pwrratio_f, pwrratio, vid_incr[0], vid_incr[1], vid_incr[2]);
+
+ // Byte reverse the entry into the image.
+ lpsa->pstate[i].value = revle64(lpsa->pstate[i].value);
+
+ gpst_index++;
+ if (gpst_index > lpst_entries)
+ break;
+ }
+
+ // set these fields in lpst structure
+ lpsa->pmin = lpst_pmin;
+ lpsa->entries = lpst_entries;
+
+ } while (0);
+
+ return rc;
+
+} // end lpst_create
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h
new file mode 100755
index 000000000..f4dd6b275
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h
@@ -0,0 +1,157 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/pstate_tables.h $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PSTATE_TABLES_H__
+#define __PSTATE_TABLES_H__
+
+// $Id: pstate_tables.h,v 1.6 2013/05/02 17:33:31 jimyac Exp $
+
+/// \file pstate_tables.h
+/// \brief Code used to generate Pstate tables from real or imagined chip
+/// characterizations.
+
+#include "pstates.h"
+
+// 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
+
+
+#ifndef __ASSEMBLER__
+
+/// 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
+/// 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
+/// Pstate of the operating point (as a potentially out-of-bounds value) is
+/// also stored.
+
+typedef struct {
+
+ uint32_t vdd_uv;
+ uint32_t vcs_uv;
+ uint32_t vdd_corrected_uv;
+ uint32_t vcs_corrected_uv;
+ uint32_t vdd_ivrm_effective_uv;
+ uint32_t vcs_ivrm_effective_uv;
+ uint32_t vdd_maxreg_uv;
+ uint32_t vcs_maxreg_uv;
+ uint32_t idd_ma;
+ uint32_t ics_ma;
+ uint32_t frequency_khz;
+ int32_t pstate;
+
+} OperatingPoint;
+
+
+/// Constants required to compute and interpolate operating points
+///
+/// The nominal frequency and frequency step-size is given in Hz. Load-line
+/// and on-chip distribution resistances are given in micro-Ohms.
+///
+/// \todo Confirm that the "eVID V[dd,cs] Eff" correction is modeled as a simple
+/// resistance similar to the load line.
+
+typedef struct {
+
+ uint32_t pstate0_frequency_khz;
+ uint32_t frequency_step_khz;
+ uint32_t vdd_load_line_uohm;
+ uint32_t vcs_load_line_uohm;
+ uint32_t vdd_distribution_uohm;
+ uint32_t vcs_distribution_uohm;
+
+} OperatingPointParameters;
+
+
+/// A chip characterization
+
+typedef struct {
+
+ VpdOperatingPoint *vpd;
+ OperatingPoint *ops;
+ OperatingPointParameters *parameters;
+ int points;
+
+} ChipCharacterization;
+
+
+uint16_t
+revle16(uint16_t i_x);
+
+uint32_t
+revle32(uint32_t x);
+
+uint64_t
+revle64(const uint64_t i_x);
+
+int
+chip_characterization_create(ChipCharacterization *characterization,
+ VpdOperatingPoint *vpd,
+ OperatingPoint *ops,
+ OperatingPointParameters *parameters,
+ int points);
+
+int
+gpst_create(GlobalPstateTable *gpst,
+ ChipCharacterization *characterization,
+ int pstate_stepsize,
+ int evrm_delay_ns);
+
+
+int
+lpst_create(const GlobalPstateTable *gpst,
+ LocalPstateArray *lpsa,
+ const uint8_t dead_zone_5mv);
+
+
+#endif // __ASSEMBLER__
+
+#endif // __PSTATE_TABLES_H__
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstates.c b/src/usr/hwpf/hwp/pstates/pstates/pstates.c
new file mode 100755
index 000000000..32ee1ec94
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstates.c
@@ -0,0 +1,395 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/pstates.c $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: pstates.c,v 1.4 2013/06/12 20:02:12 mjjones Exp $
+
+/// \file pstates.c
+/// \brief Pstate routines required by OCC product firmware
+
+#include "ssx.h"
+#include "pgp_common.h"
+#include "pstates.h"
+
+/// Validate a VRM11 VID code
+///
+/// \param vid A VRM11 VID
+///
+/// \retval 0 The VID is valid
+///
+/// \retval -VID11_UNDERFLOW The Vid code is a low 'power off' VID (0 or 1)
+///
+/// \retval -VID11_OVERFLOW The Vid code is a high 'power off' VID (0xfe or 0xff)
+
+int
+vid11_validate(Vid11 vid)
+{
+ int rc;
+
+ if (vid < VID11_MIN) {
+
+ rc = -VID11_UNDERFLOW;
+
+ } else if (vid > VID11_MAX) {
+
+ rc = -VID11_OVERFLOW;
+
+ } else {
+
+ rc = 0;
+
+ }
+
+ return rc;
+}
+
+
+/// Bias a Pstate with saturation
+///
+/// \param pstate The initial Pstate to bias
+///
+/// \param bias The signed bias amount
+///
+/// \param biased_pstate The final biased Pstate
+///
+/// This API adds a signed bias to the \a pstate and returns the saturated sum
+/// as \a biased_pstate. Any application that biases Pstates should use this
+/// API rather than simple addition/subtraction.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -PSTATE_OVERFLOW The biased Pstate saturated at PSTATE_MAX.
+///
+/// \retval -PSTATE_UNDERFLOW The biased Pstate saturated at PSTATE_MIN.
+
+int
+bias_pstate(Pstate pstate, int bias, Pstate* biased_pstate)
+{
+ int rc, int_pstate;
+
+ int_pstate = (int)pstate + bias;
+ if (int_pstate != (Pstate)int_pstate) {
+ if (bias < 0) {
+ *biased_pstate = PSTATE_MIN;
+ rc = -PSTATE_UNDERFLOW;
+ } else {
+ *biased_pstate = PSTATE_MAX;
+ rc = -PSTATE_OVERFLOW;
+ }
+ } else {
+ *biased_pstate = int_pstate;
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
+/// Bias a DPLL frequency code with saturation and bounds checking
+///
+/// \param fcode The initial frequency code to bias
+///
+/// \param bias The signed bias amount
+///
+/// \param biased_fcode The final biased frequency code
+///
+/// This API adds a signed bias to the \a fcode and returns the saturated and
+/// bounded sum as \a biased_fcode. Any application that biases frequency
+/// codes should use this API rather than simple addition/subtraction.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -DPLL_OVERFLOW The biased frequency code saturated at DPLL_MAX.
+///
+/// \retval -DPLL_UNDERFLOW The biased frequency code saturated at DPLL_MIN.
+
+int
+bias_frequency(DpllCode fcode, int bias, DpllCode* biased_fcode)
+{
+ int rc;
+ unsigned uint_fcode;
+
+ uint_fcode = (unsigned)fcode + bias;
+ if (uint_fcode != (DpllCode)uint_fcode) {
+ if (bias < 0) {
+ *biased_fcode = DPLL_MIN;
+ rc = -DPLL_UNDERFLOW;
+ } else {
+ *biased_fcode = DPLL_MAX;
+ rc = -DPLL_OVERFLOW;
+ }
+ } else if (uint_fcode < DPLL_MIN) {
+ *biased_fcode = DPLL_MIN;
+ rc = -DPLL_UNDERFLOW;
+ } else {
+ *biased_fcode = uint_fcode;
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
+/// Bias a VRM11 VID code with saturation and bounds checking
+///
+/// \param vid The initial vid code to bias
+///
+/// \param bias The signed bias amount
+///
+/// \param biased_vid The final biased VID code
+///
+/// This API adds a signed bias to the \a vid and returns the saturated and
+/// bounded sum as \a biased_vid. Any application that biases VID codes
+/// should use this API rather than simple addition/subtraction.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -VID11_OVERFLOW The biased VID code saturated at VID11_MAX.
+///
+/// \retval -VID11_UNDERFLOW The biased VID code saturated at VID11__MIN.
+
+int
+bias_vid11(Vid11 vid, int bias, Vid11* biased_vid)
+{
+ int rc;
+ unsigned uint_vid;
+
+ uint_vid = (unsigned)vid + bias;
+ if (uint_vid != (DpllCode)uint_vid) {
+ if (bias < 0) {
+ *biased_vid = VID11_MIN;
+ rc = -VID11_UNDERFLOW;
+ } else {
+ *biased_vid = VID11_MAX;
+ rc = -VID11_OVERFLOW;
+ }
+ } else {
+
+ rc = vid11_validate(uint_vid);
+ *biased_vid = uint_vid;
+
+ }
+
+ return rc;
+}
+
+
+/// Retrieve an entry from the Global Pstate Table abstraction
+///
+/// \param gpst An initialized GlobalPstateTable structure.
+///
+/// \param pstate The Pstate index of the entry to fetch
+///
+/// \param bias This is a signed bias. The entry searched is the \a pstate +
+/// \a bias entry.
+///
+/// \param entry A pointer to a gpst_entry_t to hold the returned data.
+///
+/// This routine functions similar to PMC harwdare. When a Pstate is
+/// requested the index is first biased (under/over-volted) and clipped to the
+/// defined bounds, then the Pstate entry is returned.
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -GPST_PSTATE_CLIPPED_HIGH The requested Pstate does not exist in
+/// the table. The maximum Pstate entry in the table has been returned.
+///
+/// \retval -GPST_PSTATE_CLIPPED_LOW The requested Pstate does not exist in
+/// the table. The minimum Pstate entry in the table has been returned.
+///
+/// The following return codes are considered errors:
+///
+/// \retval -GPST_INVALID_OBJECT The Global Pstate Table is either null (0) or
+/// otherwise invalid.
+
+int
+gpst_entry(const GlobalPstateTable *gpst,
+ const Pstate pstate,
+ int bias,
+ gpst_entry_t *entry)
+{
+ int rc, index;
+ Pstate biased_pstate;
+
+ if (gpst == 0) {
+ return -GPST_INVALID_OBJECT;
+ }
+
+ rc = bias_pstate(pstate, bias, &biased_pstate);
+
+ if ((rc == -PSTATE_UNDERFLOW) || (pstate < gpst_pmin(gpst))) {
+
+ rc = -GPST_PSTATE_CLIPPED_LOW;
+ index = 0;
+
+ } else if ((rc == -PSTATE_OVERFLOW) || (pstate > gpst_pmax(gpst))) {
+
+ rc = -GPST_PSTATE_CLIPPED_HIGH;
+ index = gpst->entries - 1;
+
+ } else {
+
+ rc = 0;
+ index = pstate - gpst_pmin(gpst);
+
+ }
+
+ *entry = gpst->pstate[index];
+
+ return rc;
+}
+
+
+/// Translate a Vdd VID code to the closest Pstate in a Global Pstate table.
+///
+/// \param gpst The GlobalPstateTable to search
+///
+/// \param vdd A VID code representing an external VDD voltage
+///
+/// \param pstate The Pstate most closely matching the \a vid.
+///
+/// \param entry The GlobalPstateTable entry of the returned \a pstate.
+///
+/// This routine assumes that Pstate voltages increase monotonically from
+/// lower to higher Pstates. The algorithm operates from lowest to highest
+/// voltage, scanning until the Pstate voltage is >= the VID voltage. Thus
+/// the algorithm effectively rounds up voltage (unless clipped at the highest
+/// Pstate).
+///
+/// The following return codes are not considered errors:
+///
+/// \retval 0 Success
+///
+/// \retval -GPST_PSTATE_CLIPPED_HIGH The requested voltage does not exist in
+/// the table. The highest legal Pstate is returned.
+///
+/// \retval -GPST_PSTATE_CLIPPED_LOW The requested voltage does not exist in
+/// the table. The lowest legal Pstate in the table is returned.
+///
+/// The following return codes are considered errors:
+///
+/// \retval -VRM_INVALID_VOLTAGE The \a vid is invalid.
+///
+/// \retval -GPST_INVALID_OBJECT The \a gpst argument is NULL (0).
+
+// Recall that VID codes _decrease_ as voltage _increases_
+
+#ifdef _BIG_ENDIAN
+
+#define revle16(x) x
+#define revle32(x) x
+#define revle64(x) x
+
+#else
+
+uint16_t revle16(uint16_t i_x);
+uint32_t revle32(uint32_t i_x);
+uint64_t revle64(uint64_t i_x);
+
+#endif
+
+int
+gpst_vdd2pstate(const GlobalPstateTable* gpst,
+ const Vid11 vdd,
+ Pstate* pstate,
+ gpst_entry_t* entry)
+{
+ size_t i;
+ int rc;
+ gpst_entry_t entry_rev; // jwy
+
+
+ if (gpst == 0) {
+ return -GPST_INVALID_OBJECT;
+ }
+
+ do {
+ rc =vid11_validate(vdd);
+ if (rc) break;
+
+ // Search for the Pstate that contains (close to) the requested
+ // voltage, then handle special cases.
+
+ for (i = 0; i < gpst->entries; i++) {
+ entry_rev.value = revle64(gpst->pstate[i].value); // jwy
+
+// jwy if (gpst->pstate[i].fields.evid_vdd <= vdd) {
+ if (entry_rev.fields.evid_vdd <= vdd) { // jwy
+ break;
+ }
+ }
+
+ if (i == gpst->entries) {
+
+ *pstate = gpst_pmax(gpst);
+ *entry = gpst->pstate[i - 1];
+ rc = -GPST_PSTATE_CLIPPED_HIGH;
+
+// jwy } else if ((i == 0) && (gpst->pstate[i].fields.evid_vdd < vdd)) {
+ } else if ((i == 0) && (entry_rev.fields.evid_vdd < vdd)) {
+
+ *pstate = gpst_pmin(gpst);
+ *entry = gpst->pstate[0];
+ rc = -GPST_PSTATE_CLIPPED_LOW;
+
+ } else {
+
+ rc = bias_pstate(gpst_pmin(gpst), i, pstate);
+ if (rc) break;
+
+ *entry = gpst->pstate[i];
+ }
+ } while (0);
+ return rc;
+}
+
+int freq2pState (const GlobalPstateTable* gpst,
+ const uint32_t freq_khz,
+ Pstate* pstate)
+{
+ int rc = 0;
+ int32_t pstate32 = 0;
+
+ // ----------------------------------
+ // compute pstate for given frequency
+ // ----------------------------------
+ pstate32 = ((int32_t)((freq_khz - revle32(gpst->pstate0_frequency_khz)))) / (int32_t)revle32(gpst->frequency_step_khz);
+ *pstate = (Pstate)pstate32;
+
+ // ------------------------------
+ // perform pstate bounds checking
+ // ------------------------------
+ if (pstate32 < PSTATE_MIN)
+ rc = -PSTATE_LT_PSTATE_MIN;
+
+ if (pstate32 > PSTATE_MAX)
+ rc = -PSTATE_GT_PSTATE_MAX;
+
+ return rc;
+}
diff --git a/src/usr/hwpf/hwp/pstates/pstates/pstates.h b/src/usr/hwpf/hwp/pstates/pstates/pstates.h
new file mode 100755
index 000000000..b0f8e77d4
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/pstates.h
@@ -0,0 +1,512 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/pstates.h $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PSTATES_H__
+#define __PSTATES_H__
+
+// $Id: pstates.h,v 1.6 2013/05/02 17:33:33 jimyac Exp $
+
+/// \file pstates.h
+/// \brief Pstate structures and support routines for OCC product firmware
+
+#include "pgp_common.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Global and Local Pstate Tables
+////////////////////////////////////////////////////////////////////////////
+
+/// The Global Pstate Table must be 1KB-aligned in SRAM. The alignment is
+/// specified in the traditional log2 form.
+#define GLOBAL_PSTATE_TABLE_ALIGNMENT 10
+
+/// The Global Pstate table has 128 * 8-byte entries
+#define GLOBAL_PSTATE_TABLE_ENTRIES 128
+
+/// The Local Pstate array has 96 x 64-bit entries
+#define LOCAL_PSTATE_ARRAY_ENTRIES 96
+
+/// The VRM-11 VID base voltage in micro-Volts
+#define VRM11_BASE_UV 1612500
+
+/// The VRM-11 VID step as an unsigned number (micro-Volts)
+#define VRM11_STEP_UV 6250
+
+/// The iVID base voltage in micro-Volts
+#define IVID_BASE_UV 600000
+
+/// The iVID step as an unsigned number (micro-Volts)
+#define IVID_STEP_UV 6250
+
+// Error/Panic codes for support routines
+
+#define VRM11_INVALID_VOLTAGE 0x00876101
+
+#define PSTATE_OVERFLOW 0x00778a01
+#define PSTATE_UNDERFLOW 0x00778a02
+
+#define PSTATE_LT_PSTATE_MIN 0x00778a03
+#define PSTATE_GT_PSTATE_MAX 0x00778a04
+
+#define DPLL_OVERFLOW 0x00d75501
+#define DPLL_UNDERFLOW 0x00d75502
+
+#define VID11_OVERFLOW 0x00843101
+#define VID11_UNDERFLOW 0x00843102
+
+#define GPST_INVALID_OBJECT 0x00477801
+#define GPST_INVALID_ARGUMENT 0x00477802
+#define GPST_INVALID_ENTRY 0x00477803
+#define GPST_PSTATE_CLIPPED_LOW 0x00477804
+#define GPST_PSTATE_CLIPPED_HIGH 0x00477805
+#define GPST_BUG 0x00477806
+
+#define LPST_INVALID_OBJECT 0x00477901
+
+
+
+/// PstateSuperStructure Magic Number
+///
+/// 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.
+
+#define PSTATE_SUPERSTRUCTURE_MAGIC 0x5053544154453031ull /* PSTATE01 */
+
+
+/// \defgroup pstate_options Pstate Options
+///
+/// These are flag bits for the \a options field of the PstateOptions
+/// structure.
+///
+/// @{
+
+/// gpsm_gpst_install() - Bypass copying the Pstate table from the
+/// PstateSuperStructure into the aligned global location.
+#define PSTATE_NO_COPY_GPST 0x01
+
+/// gpsm_gpst_install() - Bypass Global Pstate Table installation and setup.
+#define PSTATE_NO_INSTALL_GPST 0x02
+
+/// gpsm_lpsa_install() - Bylass Local Pstate Array installation and setup
+#define PSTATE_NO_INSTALL_LPSA 0x04
+
+/// gpsm_resclk_install - Bypass resonant clocking Pstate limit setup
+#define PSTATE_NO_INSTALL_RESCLK 0x08
+
+/// gpsm_enable_pstates() - Force the system to the minimum Pstate at
+/// initialization
+///
+/// This mode is added as a workaround for the case that the SPIVID interface
+/// is not working correctly during initial bringup. This forces Pstate mode
+/// to come up at a low frequency.
+#define PSTATE_FORCE_INITIAL_PMIN 0x10
+
+/// @}
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/// A Global Pstate Table Entry, in the form of a packed 'firmware register'
+///
+/// Global Pstate table entries are referenced by OCC firmware, for example
+/// in procedures that do 'manual' Pstate manipulation.
+
+typedef union gpst_entry {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t evid_vdd : 8;
+ uint64_t evid_vcs : 8;
+ uint64_t reserved16 : 1;
+ uint64_t evid_vdd_eff : 7;
+ uint64_t reserved24 : 1;
+ uint64_t evid_vcs_eff : 7;
+ uint64_t reserved32 : 1;
+ uint64_t maxreg_vdd : 7;
+ uint64_t reserved40 : 1;
+ uint64_t maxreg_vcs : 7;
+ uint64_t reserved48 : 8;
+ uint64_t ecc : 8;
+#else
+ uint64_t ecc : 8;
+ uint64_t reserved48 : 8;
+ uint64_t maxreg_vcs : 7;
+ uint64_t reserved40 : 1;
+ uint64_t maxreg_vdd : 7;
+ uint64_t reserved32 : 1;
+ uint64_t evid_vcs_eff : 7;
+ uint64_t reserved24 : 1;
+ uint64_t evid_vdd_eff : 7;
+ uint64_t reserved16 : 1;
+ uint64_t evid_vcs : 8;
+ uint64_t evid_vdd : 8;
+#endif // _BIG_ENDIAN
+ } fields;
+
+} gpst_entry_t;
+
+
+/// A Local Pstate Table Entry, in the form of a packed 'firmware register'
+///
+/// This structure is provided for reference only; Currently the OCC firmware
+/// does not manupulate Local Pstate table entries, however it is possible
+/// that future lab applications will require this.
+
+typedef union lpst_entry {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t ivid_vdd : 7;
+ uint64_t ivid_vcs : 7;
+ uint64_t vdd_core_pwrratio : 6;
+ uint64_t vcs_core_pwrratio : 6;
+ 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 ps3_vid_incr : 3;
+ uint64_t reserved47 : 7;
+ uint64_t inc_step : 3;
+ uint64_t dec_step : 3;
+ uint64_t reserved60 : 4;
+#else
+ uint64_t reserved60 : 4;
+ uint64_t dec_step : 3;
+ uint64_t inc_step : 3;
+ uint64_t reserved47 : 7;
+ uint64_t ps3_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;
+ uint64_t vcs_core_pwrratio : 6;
+ uint64_t vdd_core_pwrratio : 6;
+ uint64_t ivid_vcs : 7;
+ uint64_t ivid_vdd : 7;
+#endif // _BIG_ENDIAN
+ } fields;
+
+} lpst_entry_t;
+
+
+/// Standard options controlling Pstate setup and GPSM procedures
+
+typedef struct {
+
+ /// Option flags; See \ref pstate_options
+ uint32_t options;
+
+ /// Pad structure to 8 bytes. Could also be used for other options later.
+ uint32_t pad;
+
+} PstateOptions;
+
+
+/// An abstract Global Pstate table
+///
+/// The GlobalPstateTable is an abstraction of a set of voltage/frequency
+/// operating points along with hardware limits. Besides the hardware global
+/// Pstate table, the abstract table contains enough extra information to make
+/// it the self-contained source for setting up and managing voltage and
+/// frequency in either Hardware or Firmware Pstate mode.
+///
+/// When installed in PMC, Global Pstate table indices are adjusted such that
+/// the defined Pstates begin with table entry 0. The table need not be full -
+/// the \a pmin and \a entries fields define the minimum and maximum Pstates
+/// represented in the table. However at least 1 entry must be defined to
+/// create a legal table.
+///
+/// Note that Global Pstate table structures to be mapped into PMC hardware
+/// must be 1KB-aligned. This requirement is fullfilled by ensuring that
+/// instances of this structure are 1KB-aligned.
+
+typedef struct {
+
+ /// The Pstate table
+ gpst_entry_t pstate[GLOBAL_PSTATE_TABLE_ENTRIES];
+
+ /// Pstate options
+ ///
+ /// The options are included as part of the GlobalPstateTable so that they
+ /// are available to all procedures after gpsm_initialize().
+ PstateOptions options;
+
+ /// The frequency associated with Pstate[0] in KHz
+ uint32_t pstate0_frequency_khz;
+
+ /// The frequency step in KHz
+ uint32_t frequency_step_khz;
+
+ /// The DPLL frequency code corresponding to Pstate 0
+ ///
+ /// This frequency code is installed in the PCB Slave as the DPLL Fnom
+ /// when the Pstate table is activated. Normally this frequency code is
+ /// computed as
+ ///
+ /// pstate0_frequency_khz / frequency_step_khz
+ ///
+ /// however it may be replaced by any other code as a way to
+ /// transparently bias frequency on a per-core basis.
+ DpllCode pstate0_frequency_code[PGP_NCORES];
+
+ /// The DPLL Fmax bias
+ ///
+ /// This bias value (default 0, range -8 to +7 frequency ticks) is
+ /// installed when the Pstate table is installed. The value is allowed to
+ /// vary per core. This bias value will usually be set to a small
+ /// positive number to provide a small amount of frequency headroom for
+ /// the CPM-DPLL voltage control algorithm.
+ ///
+ /// \bug Hardware currently specifies this field as unsigned for the
+ /// computation of frequency stability in
+ /// dpll_freqout_mode_en. (HW217404). This issue will be fixed in
+ /// Venice. Since we never plan to use this mode no workaround or
+ /// mitigation is provided by GPSM procedures.
+
+ int8_t dpll_fmax_bias[PGP_NCORES];
+
+ /// The number of entries defined in the table.
+ uint8_t entries;
+
+ /// The minimum Pstate in the table
+ ///
+ /// Note that gpsi_min = pmin - PSTATE_MIN, gpsi_max = pmin + entries - 1.
+ Pstate pmin;
+
+ /// The "Safe" Global Pstate
+ ///
+ /// This Pstate is installed in the PMC and represents the safe-mode
+ /// voltage.
+ Pstate pvsafe;
+
+ /// The "Safe" Local Pstate
+ ///
+ /// This Pstate is installed in the PCB Slaves and represents the
+ /// safe-mode frequency.
+ Pstate psafe;
+
+ /// Step size of Global Pstate steps
+ uint8_t pstate_stepsize;
+
+ /// The exponent of the exponential encoding of Pstate stepping delay
+ uint8_t vrm_stepdelay_range;
+
+ /// The significand of the exponential encoding of Pstate stepping delay
+ uint8_t vrm_stepdelay_value;
+
+ /// Pad structure to 8-byte alignment
+ uint8_t pad;
+
+} GlobalPstateTable;
+
+
+/// This macro creates a properly-aligned Global Pstate table structure as a
+/// static initialization.
+
+#define GLOBAL_PSTATE_TABLE(x) \
+ GlobalPstateTable x \
+ ALIGNED_ATTRIBUTE(POW2_32(GLOBAL_PSTATE_TABLE_ALIGNMENT)) \
+ SECTION_ATTRIBUTE(".noncacheable") \
+ = {.entries = 0}
+
+
+/// An opaque Local Pstate Array
+///
+/// An array local to each core contains the Local Pstate Table, Vds table and
+/// Vin table. The array contents are presented to OCC firmware as an opaque
+/// set of 96 x 64-bit entries which are simply installed verbatim into each
+/// core. Every core stores the same table.
+///
+/// When installed in the core, Local Pstate table indices are adjusted such
+/// that the defined Pstates begin with table entry 0. The table need not be
+/// full - the \a pmin and \a entries fields define the minimum and maximum
+/// Pstates represented in the table. However at least 1 entry must be
+/// defined to create a legal table.
+
+typedef struct {
+
+ /// The array contents
+ lpst_entry_t pstate[LOCAL_PSTATE_ARRAY_ENTRIES];
+
+ /// The number of entries defined in the Local Pstate Table
+ uint8_t entries;
+
+ /// The minimum Pstate in the Local Pstate table
+ ///
+ /// Note that lpsi_min = pmin - PSTATE_MIN, lpsi_max = pmin + entries - 1.
+ Pstate pmin;
+
+ /// Pstate step delay for rising iVRM voltages
+ uint8_t stepdelay_rising;
+
+ /// Pstate step delay for falling iVRM voltages
+ uint8_t stepdelay_lowering;
+
+ /// Pad structure to 8-byte alignment
+ uint8_t pad[4];
+
+} LocalPstateArray;
+
+
+/// Resonant Clocking setup parameters
+///
+/// All Pstate parameters are specified in terms of Pstates as defined in the
+/// current PstateSuperStructure.
+
+typedef struct {
+
+ /// Full Clock Sector Buffer Pstate
+ Pstate full_csb_ps;
+
+ /// Low-Frequency Resonant Lower Pstate
+ Pstate res_low_lower_ps;
+
+ /// Low-Frequency Resonant Upper Pstate
+ Pstate res_low_upper_ps;
+
+ /// High-Frequency Resonant Lower Pstate
+ Pstate res_high_lower_ps;
+
+ /// High-Frequency Resonant Upper Pstate
+ Pstate res_high_upper_ps;
+
+ /// Pad structure to 8-byte alignment
+ uint8_t pad[3];
+
+} ResonantClockingSetup;
+
+
+
+/// 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,
+/// therefore there is no alignment requirement. The \gpst member is copied
+/// to an aligned location, and the \a lpsa and \a resclk members are directly
+/// installed in hardware.
+///
+/// Both the master and slave OCCs (in DCM-mode) install their Pstate tables
+/// independently via the API gpsm_initialize(). At that point the
+/// PstateSuperStructure can be discarded.
+
+typedef struct {
+
+ /// Magic Number
+ uint64_t magic;
+
+ /// Global Pstate Table
+ GlobalPstateTable gpst;
+
+ /// Local Pstate Array
+ LocalPstateArray lpsa;
+
+ /// Resonant Clocking Setup
+ ResonantClockingSetup resclk;
+
+} PstateSuperStructure;
+
+
+int
+vid11_validate(Vid11 vid);
+
+int
+bias_pstate(Pstate pstate, int bias, Pstate* biased_pstate);
+
+int
+bias_frequency(DpllCode fcode, int bias, DpllCode* biased_fcode);
+
+int
+bias_vid11(Vid11 vid, int bias, Vid11* biased_fcode);
+
+int
+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,
+ Pstate* pstate);
+
+int
+gpst_vdd2pstate(const GlobalPstateTable* gpst,
+ const uint8_t vdd,
+ Pstate* pstate,
+ gpst_entry_t* entry);
+
+
+/// Return the Pmin value associated with a GlobalPstateTable
+static inline Pstate
+gpst_pmin(const GlobalPstateTable* gpst)
+{
+ return gpst->pmin;
+}
+
+
+/// Return the Pmax value associated with a GlobalPstateTable
+static inline Pstate
+gpst_pmax(const GlobalPstateTable* gpst)
+{
+ return (int)(gpst->pmin) + (int)(gpst->entries) - 1;
+}
+
+/// Return the Pmin value associated with a LocalPstateTable
+static inline Pstate
+lpst_pmin(const LocalPstateArray* lpsa)
+{
+ return lpsa->pmin;
+}
+
+
+/// Return the Pmax value associated with a GlobalPstateTable
+static inline Pstate
+lpst_pmax(const LocalPstateArray* lpsa)
+{
+ return (int)(lpsa->pmin) + (int)(lpsa->entries) - 1;
+}
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PSTATES_H__ */
diff --git a/src/usr/hwpf/hwp/pstates/pstates/ssx.h b/src/usr/hwpf/hwp/pstates/pstates/ssx.h
new file mode 100755
index 000000000..a0be01120
--- /dev/null
+++ b/src/usr/hwpf/hwp/pstates/pstates/ssx.h
@@ -0,0 +1,103 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/pstates/pstates/ssx.h $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __SSX_H__
+#define __SSX_H__
+
+// $ID$
+
+/// \file ssx.h
+/// \brief Dummy "ssx.h" for X86 testing
+
+#define __SSX__
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#endif /* __ASSEMBLER__ */
+
+#ifndef __ASSEMBLER__
+
+#define MIN(X, Y) \
+ ({ \
+ typeof (X) __x = (X); \
+ typeof (Y) __y = (Y); \
+ (__x < __y) ? __x : __y; })
+
+#define MAX(X, Y) \
+ ({ \
+ typeof (X) __x = (X); \
+ typeof (Y) __y = (Y); \
+ (__x > __y) ? __x : __y; \
+ })
+
+#endif /* __ASSEMBLER__ */
+
+
+#define SSX_ERROR_CHECK_API 1
+#define SSX_ERROR_CHECK_KERNEL 1
+#define SSX_ERROR_PANIC 1
+
+#define SSX_NONCRITICAL 0
+#define SSX_CRITICAL 1
+
+#define SSX_INVALID_ARGUMENT 0x00888005
+#define SSX_INVALID_OBJECT 0x0088800e
+
+typedef int SsxMachineContext;
+
+static inline void
+ssx_critical_section_enter(int priority, SsxMachineContext *ctx)
+{}
+
+static inline void
+ssx_critical_section_exit(SsxMachineContext *ctx)
+{}
+
+
+#define SSX_PANIC(code) \
+ do { \
+ fprintf(stderr, "%s : %d : PANIC : 0x%08x\n", \
+ __FUNCTION__, __LINE__, code); \
+ exit(1); \
+ } while (0)
+
+
+/// This macro encapsulates error handling boilerplate in the SSX API
+/// functions, for errors that do not occur in critical sections.
+
+#define SSX_ERROR_IF(condition, code) \
+ if (condition) { \
+ if (SSX_ERROR_PANIC) { \
+ SSX_PANIC(code); \
+ } else { \
+ return -(code); \
+ } \
+ }
+
+#define printk(...) printf(__VA_ARGS__)
+
+#endif /* __SSX_H__ */
diff --git a/src/usr/hwpf/makefile b/src/usr/hwpf/makefile
index 20a31d4c2..390263b75 100644
--- a/src/usr/hwpf/makefile
+++ b/src/usr/hwpf/makefile
@@ -83,7 +83,9 @@ HWP_ERROR_XML_FILES = hwp/fapiHwpErrorInfo.xml \
hwp/dmi_training/cen_dmi_scominit_errors.xml \
hwp/sbe_centaur_init/cen_xip_customize_errors.xml \
hwp/tod_init/proc_tod_utils/proc_tod_utils.xml \
- hwp/mc_config/mss_eff_config/opt_memmap_errors.xml
+ hwp/mc_config/mss_eff_config/opt_memmap_errors.xml \
+ hwp/pstates/pstates/p8_build_pstate_datablock_errors.xml \
+ hwp/pstates/pstates/proc_get_voltage_errors.xml
## these get generated into obj/genfiles/AttributeIds.H
HWP_ATTR_XML_FILES = hwp/memory_attributes.xml \
OpenPOWER on IntegriCloud