summaryrefslogtreecommitdiffstats
path: root/src/occ_405
diff options
context:
space:
mode:
authormbroyles <mbroyles@us.ibm.com>2019-03-26 13:14:53 -0500
committerMartha Broyles <mbroyles@us.ibm.com>2019-04-23 13:45:01 -0500
commitcf4c143eb571de19c03d1c66e963feb6bed4f190 (patch)
treefaebe0e25f483ecb30c0d98517c3ec1e5c71d52a /src/occ_405
parent91d3487ed586ba53e6bc34111c374a581aa52060 (diff)
downloadtalos-occ-cf4c143eb571de19c03d1c66e963feb6bed4f190.tar.gz
talos-occ-cf4c143eb571de19c03d1c66e963feb6bed4f190.zip
WOF changes for OCS and freq tracking
Change-Id: I8c609ad1404c08b8d203a48be65cf3b45adfa3ae RTC: 204891 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/75026 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com> Reviewed-by: William A. Bryan <wilbryan@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Diffstat (limited to 'src/occ_405')
-rwxr-xr-xsrc/occ_405/amec/amec_parm.h9
-rwxr-xr-xsrc/occ_405/amec/amec_parm_table.c9
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_dbug_cmd.c75
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_dbug_cmd.h24
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp.h10
-rw-r--r--src/occ_405/common.h2
-rwxr-xr-xsrc/occ_405/errl/errl.h4
-rwxr-xr-xsrc/occ_405/main.c10
-rwxr-xr-xsrc/occ_405/sensor/sensor_enum.h1
-rwxr-xr-xsrc/occ_405/sensor/sensor_info.c1
-rwxr-xr-xsrc/occ_405/sensor/sensor_table.c3
-rw-r--r--src/occ_405/wof/wof.c544
-rw-r--r--src/occ_405/wof/wof.h33
13 files changed, 532 insertions, 193 deletions
diff --git a/src/occ_405/amec/amec_parm.h b/src/occ_405/amec/amec_parm.h
index f696d3b..3c58100 100755
--- a/src/occ_405/amec/amec_parm.h
+++ b/src/occ_405/amec/amec_parm.h
@@ -192,6 +192,15 @@ typedef enum
PARM_PGPE_WOF_DW1,
PARM_PGPE_WOF_DW2,
PARM_PGPE_WOF_DW3,
+ PARM_OCS_DIRTY,
+ PARM_OCS_CEFF_UP_ADDR,
+ PARM_OCS_CEFF_DOWN_ADDR,
+ PARM_OCS_CALC_ADDR,
+ PARM_VDD_TDP_100UV,
+ PARM_OCS_NOT_DIRTY_TYPE0_CNT,
+ PARM_OCS_NOT_DIRTY_TYPE1_CNT,
+ PARM_OCS_DIRTY_TYPE0_CNT,
+ PARM_OCS_DIRTY_TYPE1_CNT,
// End WOF Parameters
AMEC_PARM_NUMBER_OF_PARAMETERS
} AMEC_PARM_ENUM;
diff --git a/src/occ_405/amec/amec_parm_table.c b/src/occ_405/amec/amec_parm_table.c
index 089826f..7a5d0c3 100755
--- a/src/occ_405/amec/amec_parm_table.c
+++ b/src/occ_405/amec/amec_parm_table.c
@@ -266,6 +266,15 @@ amec_parm_t g_amec_parm_list[] = {
AMEC_PARM_UINT64(PARM_PGPE_WOF_DW1, "PGPE_WOF_dw1", &g_amec_sys.wof.pgpe_wof_values_dw1 ),
AMEC_PARM_UINT64(PARM_PGPE_WOF_DW2, "PGPE_WOF_dw2", &g_amec_sys.wof.pgpe_wof_values_dw2 ),
AMEC_PARM_UINT64(PARM_PGPE_WOF_DW3, "PGPE_WOF_dw3", &g_amec_sys.wof.pgpe_wof_values_dw3 ),
+ AMEC_PARM_UINT8(PARM_OCS_DIRTY,"OCS_DIRTY_BITS", &g_amec_sys.wof.ocs_dirty),
+ AMEC_PARM_UINT16(PARM_OCS_CEFF_UP_ADDR,"OcsFixedUpAmt", &g_amec_sys.wof.ocs_increase_ceff),
+ AMEC_PARM_UINT16(PARM_OCS_CEFF_DOWN_ADDR,"OcsFixedDownAmt", &g_amec_sys.wof.ocs_decrease_ceff),
+ AMEC_PARM_UINT16(PARM_OCS_CALC_ADDR,"OCS_CALC_ADDR", &g_amec_sys.wof.vdd_oc_ceff_add),
+ AMEC_PARM_UINT32(PARM_VDD_TDP_100UV,"VDD_TDP_100UV", &g_amec_sys.wof.vdd_avg_tdp_100uv),
+ AMEC_PARM_UINT32(PARM_OCS_NOT_DIRTY_TYPE0_CNT,"NotDirtyTyp0Cnt", &g_amec_sys.wof.ocs_not_dirty_count),
+ AMEC_PARM_UINT32(PARM_OCS_NOT_DIRTY_TYPE1_CNT,"NotDirtyTyp1Cnt", &g_amec_sys.wof.ocs_not_dirty_type1_count),
+ AMEC_PARM_UINT32(PARM_OCS_DIRTY_TYPE0_CNT,"DirtyTyp0Cnt", &g_amec_sys.wof.ocs_dirty_type0_count),
+ AMEC_PARM_UINT32(PARM_OCS_DIRTY_TYPE1_CNT,"DirtyTyp1Cnt", &g_amec_sys.wof.ocs_dirty_type1_count),
// End WOF parameters
};
diff --git a/src/occ_405/cmdh/cmdh_dbug_cmd.c b/src/occ_405/cmdh/cmdh_dbug_cmd.c
index 72ba707..9f7fe72 100755
--- a/src/occ_405/cmdh/cmdh_dbug_cmd.c
+++ b/src/occ_405/cmdh/cmdh_dbug_cmd.c
@@ -46,6 +46,7 @@
#include "chom.h"
#include "wof.h"
#include "gpu.h"
+#include "p9_pstates_occ.h"
//*************************************************************************/
// Externs
@@ -53,6 +54,7 @@
extern uint64_t G_inject_dimm;
uint8_t G_injected_epow_asserted = 0;
extern gpe_shared_data_t G_shared_gpe_data;
+extern OCCPstateParmBlock G_oppb;
//*************************************************************************/
// Macros
@@ -95,7 +97,7 @@ void cmdh_dbug_get_trace (const cmdh_fsp_cmd_t * i_cmd_ptr,
cmdh_fsp_rsp_t * o_rsp_ptr)
{
UINT l_rc = 0;
- UINT l_trace_buffer_size = CMDH_FSP_RSP_SIZE-CMDH_DBUG_FSP_RESP_LEN-8; // tmgt reserved 8 bytes
+ UINT l_trace_buffer_size = CMDH_FSP_RSP_DATA_SIZE;
UINT16 l_trace_size = 0;
cmdh_dbug_get_trace_query_t *l_get_trace_query_ptr = (cmdh_dbug_get_trace_query_t*) i_cmd_ptr;
cmdh_dbug_get_trace_resp_t *l_get_trace_resp_ptr = (cmdh_dbug_get_trace_resp_t*) o_rsp_ptr;
@@ -584,6 +586,69 @@ void cmdh_dbug_force_wof_reset( const cmdh_fsp_cmd_t * i_cmd_ptr,
G_rsp_status = ERRL_RC_SUCCESS;
}
+void cmdh_dbug_dump_oppb( const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ // Put important contents used by OCC for WOF into INFO trace buffer
+ print_oppb();
+
+ // return the full OPPB (up to max return size) in the response buffer
+ uint16_t l_len = (sizeof(G_oppb) > CMDH_FSP_RSP_DATA_SIZE ) ? CMDH_FSP_RSP_DATA_SIZE : sizeof(G_oppb);
+
+ memcpy((void*)&(o_rsp_ptr->data[0]),
+ (void*)&(G_oppb),
+ l_len);
+
+ // Fill in the response data length
+ o_rsp_ptr->data_length[0] = CONVERT_UINT16_UINT8_HIGH(l_len);
+ o_rsp_ptr->data_length[1] = CONVERT_UINT16_UINT8_LOW(l_len);
+
+ G_rsp_status = ERRL_RC_SUCCESS;
+}
+
+// Function Specification
+//
+// Name: cmdh_dbug_wof_ocs
+//
+// Description: Writes data related to OCS support
+//
+// End Function Specification
+void cmdh_dbug_wof_ocs( const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ const cmdh_dbug_wof_ocs_cmd_t * l_cmd_ptr = (cmdh_dbug_wof_ocs_cmd_t*) i_cmd_ptr;
+ cmdh_dbug_wof_ocs_rsp_t * l_rsp_ptr = (cmdh_dbug_wof_ocs_rsp_t*) o_rsp_ptr;
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_resp_data_length = sizeof(g_amec->wof.ocs_increase_ceff) + sizeof(g_amec->wof.ocs_decrease_ceff);
+
+ // Do sanity check on the function inputs
+ if ((NULL == l_cmd_ptr) || (NULL == l_rsp_ptr))
+ {
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ }
+ else
+ {
+ // Save the OCS up and down addrs
+ g_amec->wof.ocs_increase_ceff = l_cmd_ptr->ceff_up_amount;
+ g_amec->wof.ocs_decrease_ceff = l_cmd_ptr->ceff_down_amount;
+
+ TRAC_INFO("DEBUG - OCS Ceff Adders written up[%d] down[%d]",
+ g_amec->wof.ocs_increase_ceff, g_amec->wof.ocs_decrease_ceff);
+
+ // Fill in response data
+ l_rsp_ptr->ceff_up_amount = g_amec->wof.ocs_increase_ceff;
+ l_rsp_ptr->ceff_down_amount = g_amec->wof.ocs_decrease_ceff;
+ }
+
+ // Fill in response data length
+ if( l_rsp_ptr != NULL )
+ {
+ l_rsp_ptr->data_length[0] = CONVERT_UINT16_UINT8_HIGH(l_resp_data_length);
+ l_rsp_ptr->data_length[1] = CONVERT_UINT16_UINT8_LOW(l_resp_data_length);
+ }
+ G_rsp_status = l_rc;
+ return;
+}
// Function Specification
@@ -1184,6 +1249,14 @@ void cmdh_dbug_cmd (const cmdh_fsp_cmd_t * i_cmd_ptr,
cmdh_dbug_wof_control(i_cmd_ptr, o_rsp_ptr);
break;
+ case DBUG_WOF_OCS:
+ cmdh_dbug_wof_ocs(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case DBUG_DUMP_OPPB:
+ cmdh_dbug_dump_oppb(i_cmd_ptr, o_rsp_ptr);
+ break;
+
default:
TRAC_ERR("cmdh_dbug_cmd: Debug sub command 0x%02X not valid", l_sub_cmd);
G_rsp_status = ERRL_RC_INVALID_DATA;
diff --git a/src/occ_405/cmdh/cmdh_dbug_cmd.h b/src/occ_405/cmdh/cmdh_dbug_cmd.h
index f1a5e51..2baea27 100755
--- a/src/occ_405/cmdh/cmdh_dbug_cmd.h
+++ b/src/occ_405/cmdh/cmdh_dbug_cmd.h
@@ -59,7 +59,7 @@ typedef enum
DBUG_GET_TRACE = 0x03,
DBUG_CLEAR_TRACE = 0x04,
DBUG_ALLOW_TRACE = 0x05,
-// free = 0x06,
+ DBUG_DUMP_OPPB = 0x06,
DBUG_GET_AME_SENSOR = 0x07,
DBUG_DUMP_GPU_TIMINGS = 0x08,
DBUG_PEEK = 0x09,
@@ -93,7 +93,8 @@ typedef enum
DBUG_DUMP_APSS_DATA = 0x25,
DBUG_DUMP_AME_SENSOR = 0x26,
DBUG_CLEAR_AME_SENSOR = 0x27,
- DBUG_WOF_CONTROL = 0x28
+ DBUG_WOF_CONTROL = 0x28,
+ DBUG_WOF_OCS = 0x29
} DBUG_CMD;
//*************************************************************************/
@@ -128,6 +129,7 @@ typedef struct __attribute__ ((packed))
}cmdh_dbug_get_sensor_query_t;
// Max number of sensors that can be returned with cmdh_dbug_get_ame_sensor command
+
#define CMDH_DBUG_MAX_NUM_SENSORS 50
// Size of standard response header (5 bytes) plus checksum (2 bytes)
#define CMDH_DBUG_FSP_RESP_LEN 7
@@ -232,6 +234,24 @@ typedef struct __attribute__ ((packed))
uint8_t checksum[CMDH_FSP_CHECKSUM_SIZE];
} cmdh_dbug_wof_control_rsp_t;
+// DBUG_WOF_OCS command struct
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header; // Standard command header
+ uint8_t sub_cmd; // Debug sub-command
+ uint16_t ceff_up_amount; // OCS Ceff Addr going up
+ uint16_t ceff_down_amount; // OCS Ceff Addr going down
+} cmdh_dbug_wof_ocs_cmd_t;
+
+// DBUG_WOF_OCS response struct
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint16_t ceff_up_amount;
+ uint16_t ceff_down_amount;
+ uint8_t checksum[CMDH_FSP_CHECKSUM_SIZE];
+} cmdh_dbug_wof_ocs_rsp_t;
+
// DBUG_ALLOW_TRACE command struct
typedef struct __attribute__ ((packed))
{
diff --git a/src/occ_405/cmdh/cmdh_fsp.h b/src/occ_405/cmdh/cmdh_fsp.h
index 6a59367..7e5d4c8 100755
--- a/src/occ_405/cmdh/cmdh_fsp.h
+++ b/src/occ_405/cmdh/cmdh_fsp.h
@@ -76,8 +76,12 @@
#define CMDH_FSP_RSP_SIZE 4096
// Response: Seq + Cmd + RC - 3 bytes
#define CMDH_FSP_SEQ_CMD_RC_SIZE 3
+// Response: Extra bytes TMGT needs for HWSV overhead - 8 bytes
+#define CMDH_FSP_TMGT_EXTRA_SIZE 8
+
// Response: Maximum "Data" Field Length
#define CMDH_FSP_RSP_DATA_SIZE (CMDH_FSP_RSP_SIZE - \
+ CMDH_FSP_TMGT_EXTRA_SIZE - \
CMDH_FSP_DATALEN_SIZE - \
CMDH_FSP_CHECKSUM_SIZE - \
CMDH_FSP_SEQ_CMD_RC_SIZE )
@@ -314,7 +318,11 @@ extern uint8_t G_rsp_status;
// To set flags: tmgtclient -X 0x40 --data 0x1f<4 byte value for G_internal_flags>
extern uint32_t G_internal_flags;
#define INT_FLAG_DISABLE_24X7 0x00000001
-#define INT_FLAG_ENABLE_VDD_CURRENT_READ 0x00000008
+#define INT_FLAG_ENABLE_VDD_CURRENT_READ 0x00000008 // only applies if have at least PGPE P9' support
+#define INT_FLAG_ENABLE_OCS_HOLD_NEW 0x00000010 // only applies if P10_OCS is enabled
+#define INT_FLAG_ENABLE_P10_OCS 0x00000020 // will really only be enabled if also have at least PGPE P9' support
+#define INT_FLAG_DISABLE_CEFF_TRACKING 0x00000040 // enabled by default with PGPE P9' support
+#define INT_FLAG_ENABLE_WOF_CHAR_TEST 0x00000080 // special WOF testing mode requested by Frank
void notifyCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond);
void clearCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond);
diff --git a/src/occ_405/common.h b/src/occ_405/common.h
index cabaadb..82cbfab 100644
--- a/src/occ_405/common.h
+++ b/src/occ_405/common.h
@@ -34,6 +34,8 @@
#define ALLOW_OPAL_TRACE 0x0008
#define ALLOW_MEM_TRACE 0x0010
#define ALLOW_AVSBUS_TRACE 0x0020
+#define ALLOW_WOF_OCS_TRACE 0x0040
+#define ALLOW_CEFF_RATIO_VDD_TRACE 0x0080
// Start of SRAM memory
#define SRAM_START_ADDRESS_405 0xFFF40000
diff --git a/src/occ_405/errl/errl.h b/src/occ_405/errl/errl.h
index 57da76f..5a8774c 100755
--- a/src/occ_405/errl/errl.h
+++ b/src/occ_405/errl/errl.h
@@ -316,7 +316,7 @@ typedef enum {
ERRH_GPE0_NOT_IDLE = 0x16,
ERRH_GPE1_NOT_IDLE = 0x17,
ERRH_24X7_DISABLED = 0x18,
- ERRH_CEFF_RATIO_VDD_EXCURSION = 0x19,
+ ERRH_CEFF_RATIO_VDD_EXCURSION = 0x19, // P9 prime: OCS Dirty+type '1' (Act)
ERRH_AVSBUS_VDD_TEMPERATURE = 0x1A,
ERRH_OVER_PCAP_IGNORED = 0x1B,
ERRH_VFRT_TIMEOUT_IGNORED = 0x1C,
@@ -325,7 +325,7 @@ typedef enum {
ERRH_VDD_CURRENT_ROLLOVER_MAX = 0x1F,
ERRH_CORE_SMALL_DROOP = 0x20,
ERRH_CACHE_LARGE_DROOP = 0x21,
- ERRH_RESERVED22 = 0x22,
+ ERRH_OCS_DIRTY_BLOCK = 0x22, // P9 prime: OCS Dirty+type '0' (block)
ERRH_RESERVED23 = 0x23,
ERRH_RESERVED24 = 0x24,
ERRH_RESERVED25 = 0x25,
diff --git a/src/occ_405/main.c b/src/occ_405/main.c
index 309edb4..ad2f791 100755
--- a/src/occ_405/main.c
+++ b/src/occ_405/main.c
@@ -82,6 +82,8 @@ uint8_t G_max_vfrt_chances = MAX_VFRT_CHANCES_EVERY_8TH_TICK;
// timeout, as number of WOF ticks, for PGPE WOF Control command
uint8_t G_max_wof_control_chances = MAX_WOF_CONTROL_CHANCES_EVERY_8TH_TICK;
+uint32_t G_max_ceff_ratio = MAX_CEFF_RATIO;
+
extern uint32_t __ssx_boot; // Function address is 32 bits
extern uint32_t G_occ_phantom_critical_count;
extern uint32_t G_occ_phantom_noncritical_count;
@@ -475,6 +477,14 @@ void read_wof_header(void)
// Initialize wof init state to zero
g_amec->wof.wof_init_state = WOF_DISABLED;
+ // Initialize OCS increase/decrease amounts to one step
+ g_amec->wof.ocs_increase_ceff = g_amec->wof.vdd_step;
+ g_amec->wof.ocs_decrease_ceff = g_amec->wof.vdd_step;
+
+ // calculate max ceff ratio from header info
+ G_max_ceff_ratio = ( g_amec->wof.vdd_start +
+ (g_amec->wof.vdd_step * (g_amec->wof.vdd_size - 1) ) );
+
}while( 0 );
// Check for errors and log, if any
diff --git a/src/occ_405/sensor/sensor_enum.h b/src/occ_405/sensor/sensor_enum.h
index 80b8ea7..d2a0aed 100755
--- a/src/occ_405/sensor/sensor_enum.h
+++ b/src/occ_405/sensor/sensor_enum.h
@@ -726,6 +726,7 @@ enum e_gsid
CEFFVDDRATIO,
CEFFVDNRATIO,
VRATIO,
+ OCS_ADDR,
// ------------------------------------------------------
// END of Sensor List (this must be last entry)
diff --git a/src/occ_405/sensor/sensor_info.c b/src/occ_405/sensor/sensor_info.c
index 8013e39..b622608 100755
--- a/src/occ_405/sensor/sensor_info.c
+++ b/src/occ_405/sensor/sensor_info.c
@@ -392,6 +392,7 @@ const sensor_info_t G_sensor_info[] =
SENSOR_INFO_T_ENTRY( CEFFVDDRATIO, "%\0", AMEC_SENSOR_TYPE_WOF, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_EVERY_8TH_TICK_HZ, AMEFP( 1,-2) ),
SENSOR_INFO_T_ENTRY( CEFFVDNRATIO, "%\0", AMEC_SENSOR_TYPE_WOF, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_EVERY_8TH_TICK_HZ, AMEFP( 1,-2) ),
SENSOR_INFO_T_ENTRY( VRATIO, " \0", AMEC_SENSOR_TYPE_WOF, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_EVERY_8TH_TICK_HZ, AMEFP( 1, 0) ),
+ SENSOR_INFO_T_ENTRY( OCS_ADDR, "%\0", AMEC_SENSOR_TYPE_WOF, AMEC_SENSOR_LOC_PROC, AMEC_SENSOR_NONUM, AMEEFP_EVERY_8TH_TICK_HZ, AMEFP( 1, -2) ),
};
// Cause a compile error if we don't have all the sensors in the enum in the initialization list.
diff --git a/src/occ_405/sensor/sensor_table.c b/src/occ_405/sensor/sensor_table.c
index d7ca9b5..77f0005 100755
--- a/src/occ_405/sensor/sensor_table.c
+++ b/src/occ_405/sensor/sensor_table.c
@@ -445,7 +445,7 @@ const sensor_ptr_t G_amec_sensor_list[] =
SENSOR_PTR( CEFFVDDRATIO, &g_amec_sys.wof_sensors.ceff_ratio_vdd_sensor),
SENSOR_PTR( CEFFVDNRATIO, &g_amec_sys.wof_sensors.ceff_ratio_vdn_sensor),
SENSOR_PTR( VRATIO, &g_amec_sys.wof_sensors.v_ratio_sensor),
-
+ SENSOR_PTR( OCS_ADDR, &g_amec_sys.wof_sensors.ocs_addr_sensor),
};
STATIC_ASSERT( (NUMBER_OF_SENSORS_IN_LIST != (sizeof(G_amec_sensor_list)/sizeof(sensor_ptr_t))) );
STATIC_ASSERT( (MAX_AMEC_SENSORS < (sizeof(G_amec_sensor_list)/sizeof(sensor_ptr_t))) );
@@ -640,6 +640,7 @@ const minisensor_ptr_t G_amec_mini_sensor_list[] INIT_SECTION =
SENSOR_PTR( CEFFVDDRATIO, NULL),
SENSOR_PTR( CEFFVDNRATIO, NULL),
SENSOR_PTR( VRATIO, NULL),
+ SENSOR_PTR( OCS_ADDR, NULL),
};
STATIC_ASSERT( (NUMBER_OF_SENSORS_IN_LIST != (sizeof(G_amec_mini_sensor_list)/sizeof(uint16_t *))) );
STATIC_ASSERT( (MAX_AMEC_SENSORS < (sizeof(G_amec_mini_sensor_list)/sizeof(uint16_t *))) );
diff --git a/src/occ_405/wof/wof.c b/src/occ_405/wof/wof.c
index 5be68a5..1426e6f 100644
--- a/src/occ_405/wof/wof.c
+++ b/src/occ_405/wof/wof.c
@@ -51,6 +51,7 @@ extern uint32_t G_nest_frequency_mhz;
extern volatile pstateStatus G_proc_pstate_status;
extern uint8_t G_occ_interrupt_type;
extern bool G_pgpe_shared_sram_V_I_readings;
+extern uint16_t G_allow_trace_flags;
//******************************************************************************
// Globals
@@ -279,6 +280,10 @@ void call_wof_main( void )
L_vfrt_last_chance = MAX_VFRT_CHANCES;
L_wof_control_last_chance = MAX_WOF_CONTROL_CHANCES;
+ // reset OC ceff adder
+ g_wof->vdd_oc_ceff_add = 0;
+ sensor_update(AMECSENSOR_PTR(OCS_ADDR), (uint16_t)g_wof->vdd_oc_ceff_add);
+
// calculate initial vfrt, send gpeRequest
// Initial vfrt is the last vfrt in Main memory
send_initial_vfrt_to_pgpe();
@@ -609,13 +614,35 @@ uint8_t calc_quad_step_from_start( void )
*/
uint32_t calc_vfrt_mainstore_addr( void )
{
- // Wof tables address calculation
- // (Base_addr +
- // (sizeof VFRT * (total active quads * ( (g_wof->vdn_step_from_start * vdd_size) + (g_wof->vdd_step_from_start) ) + (g_wof->quad_step_from_start))))
- g_wof->vfrt_mm_offset = g_wof->vfrt_block_size *
- (( g_wof->active_quads_size *
- ((g_wof->vdn_step_from_start * g_wof->vdd_size) +
- g_wof->vdd_step_from_start) ) + g_wof->quad_step_from_start);
+ static bool L_trace_char_test = true;
+
+ // skip calculation and return first table if WOF Char testing is enabled
+ if(G_internal_flags & INT_FLAG_ENABLE_WOF_CHAR_TEST)
+ {
+ if(L_trace_char_test)
+ {
+ INTR_TRAC_IMP("Entered WOF char testing using first VRT!");
+ L_trace_char_test = false;
+ }
+
+ g_wof->vfrt_mm_offset = 0;
+ }
+ else
+ {
+ if(!L_trace_char_test)
+ {
+ INTR_TRAC_IMP("Exited WOF char testing calculating VRT!");
+ L_trace_char_test = true;
+ }
+
+ // Wof tables address calculation
+ // (Base_addr +
+ // (sizeof VFRT * (total active quads * ( (g_wof->vdn_step_from_start * vdd_size) + (g_wof->vdd_step_from_start) ) + (g_wof->quad_step_from_start))))
+ g_wof->vfrt_mm_offset = g_wof->vfrt_block_size *
+ (( g_wof->active_quads_size *
+ ((g_wof->vdn_step_from_start * g_wof->vdd_size) +
+ g_wof->vdd_step_from_start) ) + g_wof->quad_step_from_start);
+ }
// Skip the wof header at the beginning of wof tables
uint32_t wof_tables_base = g_wof->vfrt_tbls_main_mem_addr + WOF_HEADER_SIZE;
@@ -833,13 +860,18 @@ void read_shared_sram( void )
g_wof->f_clip_ps = l_wofstate.fields.fclip_ps;
- // convert f_clip_ps from Pstate to frequency(mHz)
- g_wof->f_clip_freq = (proc_pstate2freq(g_wof->f_clip_ps))/1000;
-
g_wof->v_clip = l_wofstate.fields.vclip_mv;
- g_wof->v_ratio = l_wofstate.fields.vratio;
- sensor_update(AMECSENSOR_PTR(VRATIO), (uint16_t)l_wofstate.fields.vratio);
+ // Update Fclip Freq and Vratio for P9 only. P9 prime uses values updated in read_pgpe_produced_wof_values()
+ if( (!G_pgpe_shared_sram_V_I_readings) ||
+ (G_internal_flags & INT_FLAG_DISABLE_CEFF_TRACKING) )
+ {
+ g_wof->v_ratio = l_wofstate.fields.vratio;
+ sensor_update(AMECSENSOR_PTR(VRATIO), (uint16_t)l_wofstate.fields.vratio);
+
+ // convert f_clip_ps from Pstate to frequency(mHz)
+ g_wof->f_clip_freq = (proc_pstate2freq(g_wof->f_clip_ps))/1000;
+ }
g_wof->f_ratio = 1;
@@ -883,8 +915,27 @@ void read_shared_sram( void )
*/
void read_pgpe_produced_wof_values( void )
{
+ // Read in OCS bits from OCC Flag 0 register
+ uint32_t occ_flags0 = 0;
+ occ_flags0 = in32(OCB_OCCFLG);
+ g_wof->ocs_dirty = (uint8_t)(occ_flags0 & (OCS_PGPE_DIRTY_MASK | OCS_PGPE_DIRTY_TYPE_MASK));
+
+ // INC counter for value of ocs_dirty
+ if(g_wof->ocs_dirty == 0) // not dirty
+ g_wof->ocs_not_dirty_count++;
+ else if(g_wof->ocs_dirty == OCS_PGPE_DIRTY_TYPE_MASK) // not dirty, type 1. PGPE shouldn't be setting this
+ g_wof->ocs_not_dirty_type1_count++;
+ else if(g_wof->ocs_dirty == OCS_PGPE_DIRTY_MASK) // dirty type 0 (hold)
+ g_wof->ocs_dirty_type0_count++;
+ else if(g_wof->ocs_dirty == (OCS_PGPE_DIRTY_MASK | OCS_PGPE_DIRTY_TYPE_MASK)) // dirty type 1 (act)
+ g_wof->ocs_dirty_type1_count++;
+ else
+ INTR_TRAC_ERR("???????? Invalid ocs_dirty[%d]", g_wof->ocs_dirty);
+
+ // Update V/I from PGPE
uint16_t l_voltage = 0;
uint16_t l_current = 0;
+ uint32_t l_freq = 0;
pgpe_wof_values_t l_PgpeWofValues;
l_PgpeWofValues.dw0.value = in64(G_pgpe_header.pgpe_produced_wof_values_addr);
@@ -936,13 +987,26 @@ void read_pgpe_produced_wof_values( void )
update_avsbus_power_sensors(AVSBUS_VDD);
update_avsbus_power_sensors(AVSBUS_VDN);
- // save the PGPE WOF values
+ // populate values used by WOF alg
+
+ // these are only used for Ceff frequency tracking
+ if(!(G_internal_flags & INT_FLAG_DISABLE_CEFF_TRACKING))
+ {
+ // Average Frequency
+ l_freq = proc_pstate2freq((Pstate)l_PgpeWofValues.dw0.fields.average_frequency_pstate);
+ // value returned in kHz, save in MHz
+ g_wof->c_ratio_vdd_freq = (l_freq / 1000);
+ g_wof->f_clip_freq = g_wof->c_ratio_vdd_freq;
+ g_wof->v_ratio = l_PgpeWofValues.dw0.fields.vratio_avg;
+ sensor_update(AMECSENSOR_PTR(VRATIO), (uint16_t)g_wof->v_ratio);
+ }
+
+ // save the full PGPE WOF values for debug
g_wof->pgpe_wof_values_dw0 = l_PgpeWofValues.dw0.value;
g_wof->pgpe_wof_values_dw1 = l_PgpeWofValues.dw1.value;
g_wof->pgpe_wof_values_dw2 = l_PgpeWofValues.dw2.value;
g_wof->pgpe_wof_values_dw3 = l_PgpeWofValues.dw3.value;
}
-
/**
* calculate_core_voltage
*
@@ -1288,6 +1352,7 @@ void calculate_ceff_ratio_vdn( void )
void calculate_ceff_ratio_vdd( void )
{
uint32_t l_raw_ceff_ratio = 0;
+ static bool L_trace_not_tracking = true;
// If we get v_ratio of 0 from pgpe, force ceff_ratio_vdd to 0;
if( g_wof->v_ratio == 0 )
@@ -1296,37 +1361,126 @@ void calculate_ceff_ratio_vdd( void )
}
else
{
- // Read iac_tdp_vdd from OCCPstateParmBlock struct
- g_wof->iac_tdp_vdd =
- multiply_ratio( G_oppb.lac_tdp_vdd_turbo_10ma,
- g_wof->v_ratio );
+ // If not tracking ceff to frequency use turbo
+ if( (G_internal_flags & INT_FLAG_DISABLE_CEFF_TRACKING) ||
+ !(G_pgpe_shared_sram_V_I_readings) )
+ {
+ if(L_trace_not_tracking)
+ {
+ INTR_TRAC_INFO("ceff_ratio_vdd: Not tracking freq: Internal Flags[0x%08X] PGPE SRAM?[%d] F[%d]",
+ G_internal_flags,
+ G_pgpe_shared_sram_V_I_readings,
+ g_wof->c_ratio_vdd_freq);
+ L_trace_not_tracking = false;
+ }
- // Get Vturbo and convert to 100uV (mV -> 100uV) = mV*10
- // Multiply by Vratio
- g_wof->c_ratio_vdd_volt = G_oppb.operating_points[TURBO].vdd_mv * 10;
+ // Read iac_tdp_vdd from OCCPstateParmBlock struct
+ g_wof->iac_tdp_vdd = G_oppb.lac_tdp_vdd_turbo_10ma;
- // Get Fturbo and multiply by Fratio
- g_wof->c_ratio_vdd_freq =
- G_oppb.operating_points[TURBO].frequency_mhz * g_wof->f_ratio;
- /* TODO Uncomment once we use f_ratio from PGPE
- g_wof->c_ratio_vdd_freq =
- multiply_ratio( G_oppb.operating_points[TURBO].frequency_mhz,
- g_wof->f_ratio );
- */
+ // Get Vturbo and convert to 100uV (mV -> 100uV) = mV*10
+ g_wof->vdd_avg_tdp_100uv = 10 * G_oppb.operating_points[TURBO].vdd_mv;
+
+ // Use Fturbo
+ g_wof->c_ratio_vdd_freq =
+ G_oppb.operating_points[TURBO].frequency_mhz * g_wof->f_ratio;
+ }
+ else // track Ceff ratio with currrent average frequency
+ {
+ // NOTE: g_wof->c_ratio_vdd_freq == g_wof->f_clip_freq is the average frequency
+ // and were updated in read_pgpe_produced_wof_values()
+ // P9' we only have nominal and turbo Iac TDP Vdd from PGPE so only interpolate in that range
+ if(g_wof->c_ratio_vdd_freq <= G_oppb.operating_points[NOMINAL].frequency_mhz)
+ {
+ // Below nominal use nominal
+ if( (!L_trace_not_tracking) ||
+ (G_allow_trace_flags & ALLOW_CEFF_RATIO_VDD_TRACE) )
+ {
+ INTR_TRAC_INFO("ceff_ratio_vdd: Freq[%d] below nominal[%d]",
+ g_wof->c_ratio_vdd_freq,
+ G_oppb.operating_points[NOMINAL].frequency_mhz);
+ L_trace_not_tracking = true;
+ }
+
+ g_wof->iac_tdp_vdd = G_oppb.lac_tdp_vdd_nominal_10ma;
+
+ // *10 to convert mV to 100uV
+ g_wof->vdd_avg_tdp_100uv = 10 * G_oppb.operating_points[NOMINAL].vdd_mv;
+
+ g_wof->c_ratio_vdd_freq = G_oppb.operating_points[NOMINAL].frequency_mhz;
+
+ }
+ else if(g_wof->c_ratio_vdd_freq >= G_oppb.operating_points[TURBO].frequency_mhz)
+ {
+ // Above turbo use turbo
+ if( (!L_trace_not_tracking) ||
+ (G_allow_trace_flags & ALLOW_CEFF_RATIO_VDD_TRACE) )
+ {
+ INTR_TRAC_INFO("ceff_ratio_vdd: Freq[%d] above turbo[%d]",
+ g_wof->c_ratio_vdd_freq,
+ G_oppb.operating_points[TURBO].frequency_mhz);
+ L_trace_not_tracking = true;
+ }
+
+ g_wof->iac_tdp_vdd = G_oppb.lac_tdp_vdd_turbo_10ma;
+
+ // *10 to convert mV to 100uV
+ g_wof->vdd_avg_tdp_100uv = 10 * G_oppb.operating_points[TURBO].vdd_mv;
+
+ g_wof->c_ratio_vdd_freq = G_oppb.operating_points[TURBO].frequency_mhz;
+ }
+ else
+ {
+ // Frequency is between nominal and turbo do linear interpolation
+
+ // Calculate Vdd AC Current average TDP by interpolating #V current@g_wof->c_ratio_vdd_freq
+ g_wof->iac_tdp_vdd = interpolate_linear( g_wof->c_ratio_vdd_freq,
+ G_oppb.operating_points[NOMINAL].frequency_mhz,
+ G_oppb.operating_points[TURBO].frequency_mhz,
+ G_oppb.lac_tdp_vdd_nominal_10ma,
+ G_oppb.lac_tdp_vdd_turbo_10ma);
+
+ // Calculate Vdd voltage average TDP by interpolating #V voltage@g_wof->c_ratio_vdd_freq
+ // *10 to convert mV to 100uV
+ g_wof->vdd_avg_tdp_100uv = 10 * interpolate_linear( g_wof->c_ratio_vdd_freq,
+ G_oppb.operating_points[NOMINAL].frequency_mhz,
+ G_oppb.operating_points[TURBO].frequency_mhz,
+ G_oppb.operating_points[NOMINAL].vdd_mv,
+ G_oppb.operating_points[TURBO].vdd_mv);
+ if( (!L_trace_not_tracking) ||
+ (G_allow_trace_flags & ALLOW_CEFF_RATIO_VDD_TRACE) )
+ {
+ INTR_TRAC_INFO("ceff_ratio_vdd: F[%d] between nominal[%d] and turbo[%d]",
+ g_wof->c_ratio_vdd_freq,
+ G_oppb.operating_points[NOMINAL].frequency_mhz,
+ G_oppb.operating_points[TURBO].frequency_mhz);
+ INTR_TRAC_INFO("ceff_ratio_vdd: interpolated iac_tdp_vdd[%d] nominal[%d] turbo[%d]",
+ g_wof->iac_tdp_vdd,
+ G_oppb.lac_tdp_vdd_nominal_10ma,
+ G_oppb.lac_tdp_vdd_turbo_10ma);
+ INTR_TRAC_INFO("ceff_ratio_vdd: interpolated vdd_avg_tdp_100uv[%d] nominal[%d] turbo[%d]",
+ g_wof->vdd_avg_tdp_100uv,
+ G_oppb.operating_points[NOMINAL].vdd_mv * 10,
+ G_oppb.operating_points[TURBO].vdd_mv * 10);
+ L_trace_not_tracking = true;
+ }
+ }
+ } // else track to frequency
+
+ g_wof->c_ratio_vdd_volt = multiply_ratio( g_wof->vdd_avg_tdp_100uv,
+ g_wof->v_ratio );
// Calculate ceff_tdp_vdd
- // iac_tdp_vdd / ((Vturbo*Vratio)^1.3 * (Fturbo*Fratio))
+ // iac_tdp_vdd / ((V@Freq*Vratio)^1.3 * (Freq*Fratio))
+ // Freq is either Turbo (not tracking to frequency) or the average frequency from PGPE
g_wof->ceff_tdp_vdd =
calculate_effective_capacitance( g_wof->iac_tdp_vdd,
g_wof->c_ratio_vdd_volt,
g_wof->c_ratio_vdd_freq );
// Calculate ceff_vdd
- // iac_vdd / (Vclip^1.3 * Fclip)
- // NOTE: WOF Phase 1 to use VOLTVDDSENSE. Phase 2 will use v_clip
+ // iac_vdd / (V^1.3 * Freq)
g_wof->ceff_vdd =
calculate_effective_capacitance( g_wof->iac_vdd,
- //(g_wof->v_clip*10),// mV->100uV
g_wof->voltvddsense_sensor,
g_wof->f_clip_freq );
@@ -1335,13 +1489,13 @@ void calculate_ceff_ratio_vdd( void )
{
// Print debug info to help isolate offending variable
INTR_TRAC_ERR("WOF Disabled! Ceff VDD divide by 0");
- INTR_TRAC_ERR("iac_tdp_vdd = %d", G_oppb.lac_tdp_vdd_turbo_10ma );
+ INTR_TRAC_ERR("iac_tdp_vdd = %d", g_wof->iac_tdp_vdd );
INTR_TRAC_ERR("v_ratio = %d", g_wof->v_ratio );
INTR_TRAC_ERR("f_ratio = %d", g_wof->f_ratio );
- INTR_TRAC_ERR("vdd_mv = %d", G_oppb.operating_points[TURBO].vdd_mv);
- INTR_TRAC_ERR("freq_mhz = %d", G_oppb.operating_points[TURBO].frequency_mhz);
+ INTR_TRAC_ERR("c ratio vdd V = %d", g_wof->c_ratio_vdd_volt);
+ INTR_TRAC_ERR("c ratio vdd F = %d", g_wof->c_ratio_vdd_freq);
INTR_TRAC_ERR("v_clip_mv = %d", g_wof->v_clip);
- INTR_TRAC_ERR("f_clip_PS = 0x%x", g_wof->f_clip_ps);
+ INTR_TRAC_ERR("f_clip_freq = 0x%x", g_wof->f_clip_freq);
print_oppb();
// Return 0
@@ -1362,7 +1516,7 @@ void calculate_ceff_ratio_vdd( void )
// this is saved to the parameter used by the rest of the wof alg
g_wof->ceff_ratio_vdd = prevent_over_current(l_raw_ceff_ratio);
}
- }
+ } // else v_ratio != 0
}
/**
@@ -1370,7 +1524,7 @@ void calculate_ceff_ratio_vdd( void )
*
* Description: Calculate the AC currents
*/
-inline void calculate_AC_currents( void )
+void calculate_AC_currents( void )
{
g_wof->iac_vdd = g_wof->curvdd_sensor - g_wof->idc_vdd;
g_wof->iac_vdn = g_wof->curvdn_sensor - g_wof->idc_vdn;
@@ -1387,7 +1541,7 @@ inline void calculate_AC_currents( void )
*
* Return: Returns a non-zero value if the core is powered on, 0 otherwise
*/
-inline uint32_t core_powered_on(uint8_t i_core_num)
+uint32_t core_powered_on(uint8_t i_core_num)
{
return ( g_wof->core_pwr_on & (0x80000000 >> i_core_num));
}
@@ -1402,7 +1556,7 @@ inline uint32_t core_powered_on(uint8_t i_core_num)
*
* Return: Operating point * ratio
*/
-inline uint32_t multiply_ratio( uint32_t i_operating_point,
+uint32_t multiply_ratio( uint32_t i_operating_point,
uint32_t i_ratio )
{
// We get i_ratio from the PGPE ranging from 0x0000 to 0xffff
@@ -1448,13 +1602,20 @@ uint8_t num_cores_on_in_quad( uint8_t i_quad_num )
*
* Return: The result Y of the formula above
*/
-inline int32_t interpolate_linear( int32_t i_X,
- int32_t i_x1,
- int32_t i_x2,
- int32_t i_y1,
- int32_t i_y2 )
+int32_t interpolate_linear( int32_t i_X,
+ int32_t i_x1,
+ int32_t i_x2,
+ int32_t i_y1,
+ int32_t i_y2 )
{
- return ( ((i_X - i_x1)*(i_y2 - i_y1)) / (i_x2 - i_x1) ) + i_y1;
+ if( (i_x2 == i_x1) || (i_y2 == i_y1) )
+ {
+ return i_y1;
+ }
+ else
+ {
+ return ( ((i_X - i_x1)*(i_y2 - i_y1)) / (i_x2 - i_x1) ) + i_y1;
+ }
}
@@ -2288,162 +2449,191 @@ void print_data( void )
void print_oppb( void )
{
CMDH_TRAC_INFO("Printing Contents of OCCPstateParmBlock");
- CMDH_TRAC_INFO("");
int i;
for(i = 0; i < VPD_PV_POINTS; i++)
{
- CMDH_TRAC_INFO("operating_points[%d] = %d",
+ CMDH_TRAC_INFO("operating_points[%d] = Freq[%d] vdd_mv[%d] ",
i,
- G_oppb.operating_points[i] );
+ G_oppb.operating_points[i].frequency_mhz,
+ G_oppb.operating_points[i].vdd_mv );
}
- CMDH_TRAC_INFO("G_oppb.IddqTable");
- CMDH_TRAC_INFO("");
- CMDH_TRAC_INFO("iddq_version = %x", G_oppb.iddq.iddq_version);
- CMDH_TRAC_INFO("good_quads_per_sort = %d", G_oppb.iddq.good_quads_per_sort);
- CMDH_TRAC_INFO("good_normal_cores_per_sort = %d",
- G_oppb.iddq.good_normal_cores_per_sort);
- CMDH_TRAC_INFO("good_caches_per_sort = %d", G_oppb.iddq.good_caches_per_sort);
-
- for( i = 0; i < MAXIMUM_QUADS; i++)
- {
- CMDH_TRAC_INFO("good_normal_cores[%d] = %d",
- i,
- G_oppb.iddq.good_normal_cores[i] );
- }
- for( i = 0; i < MAXIMUM_QUADS; i++)
- {
- CMDH_TRAC_INFO("good_caches[%d] = %d",
- i,
- G_oppb.iddq.good_caches[i] );
- }
- CMDH_TRAC_INFO("rdp_to_tdp_scale_factor = %d", G_oppb.iddq.rdp_to_tdp_scale_factor);
- CMDH_TRAC_INFO("wof_iddq_margin_factor = %d", G_oppb.iddq.wof_iddq_margin_factor);
- CMDH_TRAC_INFO("vdd_temp_scale_factor = %d",
- G_oppb.iddq.vdd_temperature_scale_factor);
- CMDH_TRAC_INFO("vdn_temp_scale_factor = %d",
- G_oppb.iddq.vdn_temperature_scale_factor);
- for( i = 0; i < IDDQ_MEASUREMENTS; i++)
- {
- CMDH_TRAC_INFO("ivdd_all_good_cores_on_caches_on[%d] = %d",
- i,
- G_oppb.iddq.ivdd_all_good_cores_on_caches_on[i]);
- }
- for( i = 0; i < IDDQ_MEASUREMENTS; i++)
- {
- CMDH_TRAC_INFO("ivdd_all_cores_off_caches_off[%d] = %d",
- i,
- G_oppb.iddq.ivdd_all_cores_off_caches_off[i]);
- }
- for( i = 0; i < IDDQ_MEASUREMENTS; i++)
- {
- CMDH_TRAC_INFO("ivdd_all_good_cores_off_good_caches_on[%d] = %d",
- i,
- G_oppb.iddq.ivdd_all_good_cores_off_good_caches_on[i]);
- }
- int j;
- for( i = 0; i < MAXIMUM_QUADS; i++ )
- {
- for( j = 0; j < IDDQ_MEASUREMENTS; j++)
- {
- CMDH_TRAC_INFO("ivdd_quad_good_cores_on_good_caches_on[%d][%d] = %d",
- i,
- j,
- G_oppb.iddq.ivdd_quad_good_cores_on_good_caches_on[i][j]);
- }
- }
- for( i = 0; i < IDDQ_MEASUREMENTS; i++)
- {
- CMDH_TRAC_INFO("ivdn[%d] = %d",
- i,
- G_oppb.iddq.ivdn[i]);
- }
- for( i = 0; i < IDDQ_MEASUREMENTS; i++)
- {
- CMDH_TRAC_INFO("avgtemp_all_good_cores_on[%d] = %d",
- i,
- G_oppb.iddq.avgtemp_all_good_cores_on[i]);
- }
- for( i = 0; i < IDDQ_MEASUREMENTS; i++)
- {
- CMDH_TRAC_INFO("avgtemp_all_cores_off_caches_off[%d] = %d",
- i,
- G_oppb.iddq.avgtemp_all_cores_off_caches_off[i]);
- }
- for( i = 0; i < IDDQ_MEASUREMENTS; i++)
- {
- CMDH_TRAC_INFO("avgtemp_all_good_cores_off[%d] = %d",
- i,
- G_oppb.iddq.avgtemp_all_good_cores_off[i] );
- }
- for( i = 0; i < MAXIMUM_QUADS; i++ )
- {
- for( j = 0; j < IDDQ_MEASUREMENTS; j++)
- {
- CMDH_TRAC_INFO("avgtemp_quad_good_cores_on[%d][%d] = %d",
- i,
- j,
- G_oppb.iddq.avgtemp_quad_good_cores_on[i][j]);
- }
- }
- for( i = 0; i < IDDQ_MEASUREMENTS; i++)
- {
- CMDH_TRAC_INFO("avgtemp_vdn[%d] = %d",
- i,
- G_oppb.iddq.avgtemp_vdn[i]);
- }
- CMDH_TRAC_INFO("");
- CMDH_TRAC_INFO("freq_min_khz = %d", G_oppb.frequency_min_khz);
- CMDH_TRAC_INFO("freq_max_khz = %d", G_oppb.frequency_max_khz);
- CMDH_TRAC_INFO("freq_step_khz = %d", G_oppb.frequency_step_khz);
- CMDH_TRAC_INFO("pstate_min = %d", G_oppb.pstate_min);
- CMDH_TRAC_INFO("nest_freq_mhz = %d", G_oppb.nest_frequency_mhz);
- CMDH_TRAC_INFO("nest_leakage_percent = %d", G_oppb.nest_leakage_percent);
- CMDH_TRAC_INFO("ceff_tdp_vdn = %d", G_oppb.ceff_tdp_vdn);
CMDH_TRAC_INFO("lac_tdp_vdd_turbo_10ma = %d", G_oppb.lac_tdp_vdd_turbo_10ma);
CMDH_TRAC_INFO("lac_tdp_vdd_nominal_10ma = %d", G_oppb.lac_tdp_vdd_nominal_10ma);
- CMDH_TRAC_INFO("vdd_sysparm.loadline = %d", G_oppb.vdd_sysparm.loadline_uohm);
- CMDH_TRAC_INFO("vdd_sysparm.distloss = %d", G_oppb.vdd_sysparm.distloss_uohm);
- CMDH_TRAC_INFO("vdn_sysparm.loadline = %d", G_oppb.vdn_sysparm.loadline_uohm);
- CMDH_TRAC_INFO("vdn_sysparm.distloss = %d", G_oppb.vdn_sysparm.distloss_uohm);
- CMDH_TRAC_INFO("End OCCPstateParmBlock");
}
/**
* prevent_over_current
*
* Description: Determines whether ceff_ratio_vdd will cause an over-current
- * and clips it to a ratio of 1.0 if necessary.
+ * and clips it to a new ceff ratio if necessary.
*
- * Param: Calculated ceff_ratio before clipping at 1.0
+ * Param: Calculated ceff_ratio before any clipping
*
* Return: Clipped ceff_ratio
*/
uint32_t prevent_over_current( uint32_t i_ceff_ratio )
{
+ static uint8_t L_method_trace = 0; // P9 or P10 to indicate what method we are using to trace
static uint8_t L_oc_prevention_timer = 0;
+ static uint8_t L_ocs_dirty_prev = 0;
uint32_t l_clipped_ratio = i_ceff_ratio;
+ uint32_t l_new_ratio_from_measured = 0;
+ uint32_t l_new_ratio_from_prev = 0;
- if( i_ceff_ratio > MAX_CEFF_RATIO ) // 10000 = 1.0 ratio
- {
- INCREMENT_ERR_HISTORY( ERRH_CEFF_RATIO_VDD_EXCURSION );
- l_clipped_ratio = MAX_CEFF_RATIO;
+ // determine if Ceff needs to be adjusted for overcurrent
+ // different process between P9 and P10
- // If over current timer not started, start it.
- if( L_oc_prevention_timer == 0 )
- {
- L_oc_prevention_timer = 10; // 10 WOF iterations
- }
- else
- {
- L_oc_prevention_timer--;
- }
- }
- else if( L_oc_prevention_timer != 0 ) // Timer is running
+ if( (!(G_internal_flags & INT_FLAG_ENABLE_P10_OCS)) ||
+ (!G_pgpe_shared_sram_V_I_readings) )
{
- l_clipped_ratio = MAX_CEFF_RATIO;
- L_oc_prevention_timer--;
+ if(L_method_trace != 9)
+ {
+ INTR_TRAC_IMP("Using P9 Overcurrent method");
+ L_method_trace = 9;
+ }
+ if( i_ceff_ratio > MAX_CEFF_RATIO ) // 10000 = 1.0 ratio
+ {
+ INCREMENT_ERR_HISTORY( ERRH_CEFF_RATIO_VDD_EXCURSION );
+ l_clipped_ratio = MAX_CEFF_RATIO;
+
+ // If over current timer not started, start it.
+ if( L_oc_prevention_timer == 0 )
+ {
+ L_oc_prevention_timer = 10; // 10 WOF iterations
+ }
+ else
+ {
+ L_oc_prevention_timer--;
+ }
+ }
+ else if( L_oc_prevention_timer != 0 ) // Timer is running
+ {
+ l_clipped_ratio = MAX_CEFF_RATIO;
+ L_oc_prevention_timer--;
+ }
}
+ else // P10 method
+ {
+ if(L_method_trace != 10)
+ {
+ INTR_TRAC_IMP("Using P10 Overcurrent method");
+ L_method_trace = 10;
+ }
+
+ if(l_clipped_ratio > G_max_ceff_ratio)
+ l_clipped_ratio = G_max_ceff_ratio;
+
+ if((g_wof->ocs_dirty & OCS_PGPE_DIRTY_MASK) == 0)
+ {
+ // no over current condition detected on previous PGPE tick time
+ // decrease OC CeffRatio addr, stop at 0
+ if(g_wof->vdd_oc_ceff_add > g_wof->ocs_decrease_ceff)
+ {
+ g_wof->vdd_oc_ceff_add -= g_wof->ocs_decrease_ceff;
+
+ // now determine if any adjustment is needed
+ if(i_ceff_ratio < g_wof->vdd_ceff_ratio_adj_prev)
+ {
+ // new measured ratio is lower than previous add the adder but max out at previous
+ l_clipped_ratio += g_wof->vdd_oc_ceff_add;
+ if(l_clipped_ratio > g_wof->vdd_ceff_ratio_adj_prev)
+ l_clipped_ratio = g_wof->vdd_ceff_ratio_adj_prev;
+ }
+ }
+ else // no adjustment to ceff ratio
+ {
+ g_wof->vdd_oc_ceff_add = 0;
+ }
+ if( (L_ocs_dirty_prev != g_wof->ocs_dirty) &&
+ (G_allow_trace_flags & ALLOW_WOF_OCS_TRACE) )
+ {
+ INTR_TRAC_IMP("OCS NOW CLEAN: Adder[%d] Measured[%d] Previous[%d] Adjusted[%d]",
+ g_wof->vdd_oc_ceff_add,
+ i_ceff_ratio,
+ g_wof->vdd_ceff_ratio_adj_prev,
+ l_clipped_ratio);
+ }
+
+ }
+ else if(g_wof->ocs_dirty == (OCS_PGPE_DIRTY_MASK | OCS_PGPE_DIRTY_TYPE_MASK)) // dirty type 1 (act)
+ {
+ INCREMENT_ERR_HISTORY( ERRH_CEFF_RATIO_VDD_EXCURSION );
+
+ // over current condition detected on previous PGPE tick time
+ // increase OC CeffRatio addr stop at max
+ g_wof->vdd_oc_ceff_add += g_wof->ocs_increase_ceff;
+
+ if(g_wof->vdd_oc_ceff_add > G_max_ceff_ratio)
+ {
+ g_wof->vdd_oc_ceff_add = G_max_ceff_ratio;
+ }
+
+ // Calculate adjusted Ceff Ratio for new and previous
+ // Add the full accumulated adder to the new measured ceff
+ l_new_ratio_from_measured = i_ceff_ratio + g_wof->vdd_oc_ceff_add;
+
+ // only add one ceff adder to the previous
+ l_new_ratio_from_prev = g_wof->vdd_ceff_ratio_adj_prev + g_wof->ocs_increase_ceff;
+
+ // use the max for the new Ceff Ratio
+ if(l_new_ratio_from_measured > l_new_ratio_from_prev)
+ {
+ l_clipped_ratio = l_new_ratio_from_measured;
+ }
+ else
+ {
+ l_clipped_ratio = l_new_ratio_from_prev;
+ }
+
+ if(l_clipped_ratio > G_max_ceff_ratio)
+ l_clipped_ratio = G_max_ceff_ratio;
+
+ if( (L_ocs_dirty_prev != g_wof->ocs_dirty) &&
+ (G_allow_trace_flags & ALLOW_WOF_OCS_TRACE) )
+ {
+ INTR_TRAC_IMP("OCS DIRTY ACT TYPE: Measured[%d] Previous[%d] Adjusted[%d]",
+ i_ceff_ratio,
+ g_wof->vdd_ceff_ratio_adj_prev,
+ l_clipped_ratio);
+ }
+
+ }
+ else // OCS Dirty but type is 0 (block action)
+ {
+ INCREMENT_ERR_HISTORY(ERRH_OCS_DIRTY_BLOCK);
+
+ // over current condition detected on previous PGPE tick time
+ // but type is block action so no adjustment to the new measured or addr
+ // default to use max of new and previous but command allows switching to
+ // test alg always using new
+ if(g_wof->vdd_ceff_ratio_adj_prev > l_clipped_ratio)
+ {
+ l_clipped_ratio = g_wof->vdd_ceff_ratio_adj_prev;
+
+ if(l_clipped_ratio > G_max_ceff_ratio)
+ l_clipped_ratio = G_max_ceff_ratio;
+ }
+ if(G_internal_flags & INT_FLAG_ENABLE_OCS_HOLD_NEW) // debug enabled to use new?
+ l_clipped_ratio = i_ceff_ratio;
+
+ if( (L_ocs_dirty_prev != g_wof->ocs_dirty) &&
+ (G_allow_trace_flags & ALLOW_WOF_OCS_TRACE) )
+ {
+ INTR_TRAC_IMP("OCS DIRTY HOLD TYPE: Measured[%d] Previous[%d] Using[%d]",
+ i_ceff_ratio,
+ g_wof->vdd_ceff_ratio_adj_prev,
+ l_clipped_ratio);
+ }
+ }
+
+ // save to previous
+ g_wof->vdd_ceff_ratio_adj_prev = l_clipped_ratio;
+ L_ocs_dirty_prev = g_wof->ocs_dirty;
+
+ // update sensor for calculated CeffRatio addr
+ sensor_update(AMECSENSOR_PTR(OCS_ADDR), (uint16_t)g_wof->vdd_oc_ceff_add);
+ } // else P10 method
return l_clipped_ratio;
}
diff --git a/src/occ_405/wof/wof.h b/src/occ_405/wof/wof.h
index 3ebab6c..75823bd 100644
--- a/src/occ_405/wof/wof.h
+++ b/src/occ_405/wof/wof.h
@@ -48,7 +48,7 @@
#define MAX_WOF_CONTROL_CHANCES G_max_wof_control_chances
extern uint8_t G_max_vfrt_chances;
extern uint8_t G_max_wof_control_chances;
-
+extern uint32_t G_max_ceff_ratio;
#define WOF_TABLES_OFFSET 0xC0000 // Relative to PPMR_ADDRESS_HOMER
#define MAX_CEFF_RATIO 10000 // 1.0 ratio = 10000
@@ -58,6 +58,10 @@ extern uint8_t G_max_wof_control_chances;
//******************************************************************************
#define IVRM_STATE_QUAD_MASK 0x80
+#define OCS_PGPE_DIRTY_MASK 0x40
+#define OCS_PGPE_DIRTY_TYPE_MASK 0x20
+
+
//******************************************************************************
// WOF Reason Code Masks
//******************************************************************************
@@ -384,6 +388,16 @@ typedef struct __attribute__ ((packed))
uint64_t pgpe_wof_values_dw1;
uint64_t pgpe_wof_values_dw2;
uint64_t pgpe_wof_values_dw3;
+ uint8_t ocs_dirty; // Set by PGPE read from OCC Flag 0 register
+ uint16_t ocs_increase_ceff; // Fixed CeffRatio increase addr defined in attribute
+ uint16_t ocs_decrease_ceff; // Fixed CeffRatio decrease addr defined in attribute
+ uint16_t vdd_oc_ceff_add; // OCC calculated CeffRatio Addr
+ uint16_t vdd_ceff_ratio_adj_prev; // Final adjusted CeffRatio from previous tick
+ uint32_t vdd_avg_tdp_100uv;
+ uint32_t ocs_not_dirty_count; // count of number of times not dirty (type 0)
+ uint32_t ocs_not_dirty_type1_count; // count of not dirty (type 1) this counter should be 0
+ uint32_t ocs_dirty_type0_count; // count of number of times dirty with type hold (0)
+ uint32_t ocs_dirty_type1_count; // count of number of times dirty with type act (1)
} amec_wof_t;
// Structure for sensors used in g_amec for AMESTER
@@ -394,6 +408,7 @@ typedef struct __attribute__ ((packed))
sensor_t ceff_ratio_vdd_sensor;
sensor_t ceff_ratio_vdn_sensor;
sensor_t v_ratio_sensor;
+ sensor_t ocs_addr_sensor;
} amec_wof_sensors_t;
typedef struct __attribute__ ((packed))
@@ -440,17 +455,17 @@ void calculate_ceff_ratio_vdn( void );
void calculate_ceff_ratio_vdd( void );
-inline void calculate_AC_currents( void );
+void calculate_AC_currents( void );
-inline uint32_t core_powered_on( uint8_t i_core_num );
+uint32_t core_powered_on( uint8_t i_core_num );
uint8_t num_cores_on_in_quad( uint8_t i_quad_num );
-inline int32_t interpolate_linear( int32_t i_X,
- int32_t i_x1,
- int32_t i_x2,
- int32_t i_y1,
- int32_t i_y2 );
+int32_t interpolate_linear( int32_t i_X,
+ int32_t i_x1,
+ int32_t i_x2,
+ int32_t i_y1,
+ int32_t i_y2 );
void calculate_temperature_scaling_08V( void );
@@ -495,6 +510,6 @@ uint32_t prevent_over_current( uint32_t i_ceff_ratio );
void schedule_vfrt_request( void );
-inline uint32_t multiply_ratio( uint32_t i_operating_point,
+uint32_t multiply_ratio( uint32_t i_operating_point,
uint32_t i_ratio );
#endif
OpenPOWER on IntegriCloud