summaryrefslogtreecommitdiffstats
path: root/src/occ_405
diff options
context:
space:
mode:
authormbroyles <mbroyles@us.ibm.com>2019-01-18 10:49:04 -0600
committerChristopher J. Cain <cjcain@us.ibm.com>2019-02-15 13:11:48 -0600
commitc77b16ee36a3e8d89db142baca74387548e8773a (patch)
tree29d517ec5a0bc7ac1a3ae6d9c6714798fb83adcc /src/occ_405
parentf7b1e2a3bcae240b8a9d47b7997f82367c11e1bd (diff)
downloadtalos-occ-c77b16ee36a3e8d89db142baca74387548e8773a.tar.gz
talos-occ-c77b16ee36a3e8d89db142baca74387548e8773a.zip
Run WOF every tick
Change-Id: I3e493e10202172bd019a168c6f6e39c57c0f75e3 RTC: 200408 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/70638 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: William A. Bryan <wilbryan@us.ibm.com> Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com>
Diffstat (limited to 'src/occ_405')
-rwxr-xr-xsrc/occ_405/amec/amec_parm.h4
-rwxr-xr-xsrc/occ_405/amec/amec_parm_table.c4
-rwxr-xr-xsrc/occ_405/amec/amec_sensors_power.c141
-rwxr-xr-xsrc/occ_405/amec/amec_slave_smh.c29
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp.h1
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c36
-rwxr-xr-xsrc/occ_405/main.c82
-rw-r--r--src/occ_405/occ_service_codes.h2
-rw-r--r--src/occ_405/pgpe/pgpe_shared.h8
-rw-r--r--src/occ_405/wof/wof.c145
-rw-r--r--src/occ_405/wof/wof.h20
11 files changed, 390 insertions, 82 deletions
diff --git a/src/occ_405/amec/amec_parm.h b/src/occ_405/amec/amec_parm.h
index 71f1841..d978065 100755
--- a/src/occ_405/amec/amec_parm.h
+++ b/src/occ_405/amec/amec_parm.h
@@ -187,6 +187,10 @@ typedef enum
PARM_QUAD_ALL_ON_5_T,
PARM_QUAD_ALL_ON_6_T,
PARM_AVGTEMP_VDN,
+ PARM_PGPE_WOF_DW0,
+ PARM_PGPE_WOF_DW1,
+ PARM_PGPE_WOF_DW2,
+ PARM_PGPE_WOF_DW3,
// End WOF Parameters
AMEC_PARM_NUMBER_OF_PARAMETERS
diff --git a/src/occ_405/amec/amec_parm_table.c b/src/occ_405/amec/amec_parm_table.c
index 6e63e6b..b5ce5af 100755
--- a/src/occ_405/amec/amec_parm_table.c
+++ b/src/occ_405/amec/amec_parm_table.c
@@ -261,6 +261,10 @@ amec_parm_t g_amec_parm_list[] = {
AMEC_PARM_UINT8_ARRAY(PARM_QUAD_ALL_ON_5_T, "q5CorsCachesOnT", &g_amec_sys.wof.quad5CoresCachesOnT, MAXIMUM_QUADS),
AMEC_PARM_UINT8_ARRAY(PARM_QUAD_ALL_ON_6_T, "q6CorsCachesOnT", &g_amec_sys.wof.quad6CoresCachesOnT, MAXIMUM_QUADS),
AMEC_PARM_UINT8_ARRAY(PARM_AVGTEMP_VDN, "avgtemp_vdn", &g_amec_sys.wof.avgtemp_vdn, MAXIMUM_QUADS),
+ AMEC_PARM_UINT64(PARM_PGPE_WOF_DW0, "PGPE_WOF_dw0", &g_amec_sys.wof.pgpe_wof_values_dw0 ),
+ 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 ),
// End WOF parameters
};
diff --git a/src/occ_405/amec/amec_sensors_power.c b/src/occ_405/amec/amec_sensors_power.c
index 6ad3406..7f1d038 100755
--- a/src/occ_405/amec/amec_sensors_power.c
+++ b/src/occ_405/amec/amec_sensors_power.c
@@ -47,6 +47,7 @@
#include "amec_oversub.h"
#include "avsbus.h"
#include <p9_pstates_occ.h>
+#include <wof.h>
/******************************************************************************/
/* Globals */
/******************************************************************************/
@@ -84,6 +85,8 @@ extern task_t G_task_table[TASK_END];
extern uint16_t G_configured_mbas;
extern uint8_t G_injected_epow_asserted;
+extern bool G_pgpe_shared_sram_V_I_readings;
+
extern uint8_t G_gpu_volt_type[MAX_GPU_DOMAINS][MAX_NUM_GPU_PER_DOMAIN];
#define GPU0_USING_VOLT2(proc, channel) ((channel == G_sysConfigData.apss_adc_map.gpu[proc][0]) && (G_gpu_volt_type[proc][0] == 2))
@@ -695,6 +698,7 @@ void update_avsbus_power_sensors(const avsbus_type_e i_type)
// Name: amec_update_avsbus_sensors
//
// Description: Read AVS Bus data and update sensors (called every tick)
+// If reading V/I from AVSbus
// Tick 0: start read current (for Vdd/Vdn)
// Tick 1: process current, start voltage read (Vdd/Vdn)
// Tick 2: process voltage, start Vdd temp read
@@ -707,6 +711,16 @@ void update_avsbus_power_sensors(const avsbus_type_e i_type)
// Vdd/Vdn current and voltage are read every 3 ticks
// Vdd temperature and status is read every 6 ticks
//
+// If reading V/I from OCC-PGPE Shared SRAM
+// Tick 0: start read current (for Vdd)
+// Tick 1: process current, start status read (Vdd)
+// Tick 2: process status, start Vdd temp read
+// Tick 3: process Vdd temp, start current read (Vdd)
+// (back to tick 1)
+//
+// Vdd current is read every 3 ticks
+// Vdd temperature and status is read every 3 ticks
+//
// Thread: RealTime Loop
//
// End Function Specification
@@ -733,53 +747,103 @@ void amec_update_avsbus_sensors(void)
switch (L_avsbus_state)
{
case AVSBUS_STATE_INITIATE_READ:
- // Start reading from AVS bus, what we start with depends on the amec slave state
- // with goal of processing status on the same tick that WOF runs (amec slave state 4)
- // Want processing of Temperature on state 1, voltage on 2, current on 3, to give status on 4
- // can only start with temperature or voltage, since the status must be last and requires
- // voltage and current to have been read in order to update the power sensor
- switch ( G_amec_slv_state.state )
+ // Start reading from AVS bus
+ if(!G_pgpe_shared_sram_V_I_readings)
{
- case 0:
- case 4:
+ // Start reading from AVS bus, what we start with depends on the amec slave state
+ // with goal of processing status on the same tick that WOF runs (amec slave state 4)
+ // Want processing of Temperature on state 1, voltage on 2, current on 3, to give status on 4
+ // can only start with temperature or voltage, since the status must be last and requires
+ // voltage and current to have been read in order to update the power sensor
+ switch ( G_amec_slv_state.state )
+ {
+ case 0:
+ case 4:
+ // Initiate AVS Bus read for Vdd temperature
+ // temperature will be processed on next tick (state 1/5)
+ TRAC_IMP("amec_update_avsbus_sensors: Starting with temperature in slave state %d", G_amec_slv_state.state);
+ avsbus_read_start(AVSBUS_VDD, AVSBUS_TEMPERATURE);
+ L_avsbus_state = AVSBUS_STATE_PROCESS_TEMPERATURE;
+ break;
+ case 1:
+ case 5:
+ // Initiate read of voltages
+ // voltages will be processed on next tick (state 2/6)
+ TRAC_IMP("amec_update_avsbus_sensors: Starting with voltage in slave state %d", G_amec_slv_state.state);
+ initiate_avsbus_reads(AVSBUS_VOLTAGE);
+ L_avsbus_state = AVSBUS_STATE_PROCESS_VOLTAGE;
+ break;
+ case 2:
+ case 3:
+ case 6:
+ case 7:
+ // Need to wait another tick, can only start with temperature or voltage readings
+ break;
+ default:
+ // this should never happen, this would mean the whole state machine is broken!
+ // just start reading with temperature
+ TRAC_ERR("amec_update_avsbus_sensors: INVALID AMEC SLAVE STATE 0x%02X", G_amec_slv_state.state);
+ avsbus_read_start(AVSBUS_VDD, AVSBUS_TEMPERATURE);
+ L_avsbus_state = AVSBUS_STATE_PROCESS_TEMPERATURE;
+ break;
+ } // switch G_amec_slv_state.state
+
+ } // if reading V/I from AVSbus
+ else
+ {
+ // we are reading V/I from PGPE except if internal flag got set for OCC
+ // to read Vdd Current in order to handle rollover detection
+ if(G_internal_flags & INT_FLAG_ENABLE_VDD_CURRENT_READ)
+ {
+ // Vdd current enabled, start with initiate read of Vdd current
+ // Before starting the Current read clear the Vdd OCW bit if it is being used for rollover detection
+ if (G_sysConfigData.vdd_current_rollover_10mA != 0xFFFF)
+ {
+ clear_status_errors(G_sysConfigData.avsbus_vdd.bus, AVSBUS_STATUS_OVER_CURRENT_MASK);
+ }
+ initiate_avsbus_reads(AVSBUS_CURRENT);
+ L_avsbus_state = AVSBUS_STATE_PROCESS_CURRENT;
+ }
+ else
+ {
// Initiate AVS Bus read for Vdd temperature
- // temperature will be processed on next tick (state 1/5)
- TRAC_IMP("amec_update_avsbus_sensors: Starting with temperature in slave state %d", G_amec_slv_state.state);
- avsbus_read_start(AVSBUS_VDD, AVSBUS_TEMPERATURE);
- L_avsbus_state = AVSBUS_STATE_PROCESS_TEMPERATURE;
- break;
- case 1:
- case 5:
- // Initiate read of voltages
- // voltages will be processed on next tick (state 2/6)
- TRAC_IMP("amec_update_avsbus_sensors: Starting with voltage in slave state %d", G_amec_slv_state.state);
- initiate_avsbus_reads(AVSBUS_VOLTAGE);
- L_avsbus_state = AVSBUS_STATE_PROCESS_VOLTAGE;
- break;
- case 2:
- case 3:
- case 6:
- case 7:
- // Need to wait another tick, can only start with temperature or voltage readings
- break;
- default:
- // this should never happen, this would mean the whole state machine is broken!
- // just start reading with temperature
- TRAC_ERR("amec_update_avsbus_sensors: INVALID AMEC SLAVE STATE 0x%02X", G_amec_slv_state.state);
avsbus_read_start(AVSBUS_VDD, AVSBUS_TEMPERATURE);
L_avsbus_state = AVSBUS_STATE_PROCESS_TEMPERATURE;
- break;
- }
+ }
+ } // else reading V/I from PGPE Shared SRAM
break; // case AVSBUS_STATE_INITIATE_READ
case AVSBUS_STATE_PROCESS_TEMPERATURE:
- // Read and process Vdd temperature
- avsbus_read(AVSBUS_VDD, AVSBUS_TEMPERATURE);
+ // Read and process Vdd temperature
+ avsbus_read(AVSBUS_VDD, AVSBUS_TEMPERATURE);
+ // determine what to read next
+ if(!G_pgpe_shared_sram_V_I_readings)
+ {
// Initiate read of voltages
initiate_avsbus_reads(AVSBUS_VOLTAGE);
L_avsbus_state = AVSBUS_STATE_PROCESS_VOLTAGE;
+ }
+ else if(G_internal_flags & INT_FLAG_ENABLE_VDD_CURRENT_READ)
+ {
+ // Initiate read of Vdd current
+ // this will only read Vdd since Vdn monitoring was turned off due to G_pgpe_shared_sram_V_I_readings
+ // in data_store_avsbus_config()
+ // Before starting the Current read clear the Vdd OCW bit if it is being used for rollover detection
+ if (G_sysConfigData.vdd_current_rollover_10mA != 0xFFFF)
+ {
+ clear_status_errors(G_sysConfigData.avsbus_vdd.bus, AVSBUS_STATUS_OVER_CURRENT_MASK);
+ }
+ initiate_avsbus_reads(AVSBUS_CURRENT);
+ L_avsbus_state = AVSBUS_STATE_PROCESS_CURRENT;
+ }
+ else
+ {
+ // Initiate read of status
+ initiate_avsbus_read_status();
+ L_avsbus_state = AVSBUS_STATE_PROCESS_STATUS;
+ }
break;
case AVSBUS_STATE_PROCESS_VOLTAGE:
@@ -825,6 +889,13 @@ void amec_update_avsbus_sensors(void)
break;
}
+ // if we are using V/I readings from PGPE Shared memory, read and update the sensors now
+ // this will also save the data for WOF to use on this tick
+ if(G_pgpe_shared_sram_V_I_readings)
+ {
+ read_pgpe_produced_wof_values();
+ }
+
} // end amec_update_avsbus_sensors()
// Function Specification
diff --git a/src/occ_405/amec/amec_slave_smh.c b/src/occ_405/amec/amec_slave_smh.c
index 0772fd7..f60eba9 100755
--- a/src/occ_405/amec/amec_slave_smh.c
+++ b/src/occ_405/amec/amec_slave_smh.c
@@ -71,6 +71,7 @@ extern dcom_slv_inbox_t G_dcom_slv_inbox_rx;
extern opal_proc_voting_reason_t G_amec_opal_proc_throt_reason;
extern uint16_t G_proc_fmax_mhz;
extern GpeRequest G_wof_vfrt_req;
+extern bool G_pgpe_shared_sram_V_I_readings;
//*************************************************************************
// Macros
@@ -446,12 +447,21 @@ void amec_slv_common_tasks_post(void)
// Call the OCC slave's performance check
amec_slv_check_perf();
- // Call the every tick trace recording if it has been configured via Amester.
- // If not configured, this call will return immediately.
- amec_tb_record(AMEC_TB_EVERY_TICK);
+ //-------------------------------------------------------
+ // Run WOF Algorithm if we are getting readings from PGPE
+ // Else WOF will run in slave state 4
+ //-------------------------------------------------------
+ if(G_pgpe_shared_sram_V_I_readings)
+ {
+ call_wof_main();
+ }
// Check to see if a VFRT IPC request needs to be sent to the PGPE
schedule_vfrt_request();
+
+ // Call the every tick trace recording if it has been configured via Amester.
+ // If not configured, this call will return immediately.
+ amec_tb_record(AMEC_TB_EVERY_TICK);
}
else
{
@@ -601,10 +611,15 @@ void amec_slv_state_4(void)
if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
amec_update_centaur_sensors(CENTAUR_4);
- //-------------------------------------------------------
- // Run WOF Algorithm
- //-------------------------------------------------------
- call_wof_main();
+ //-------------------------------------------------------
+ // Run WOF Algorithm if we are NOT getting readings from PGPE
+ // Else WOF will run every tick with new PGPE readings
+ //-------------------------------------------------------
+ if(!G_pgpe_shared_sram_V_I_readings)
+ {
+ call_wof_main();
+ }
+
}
diff --git a/src/occ_405/cmdh/cmdh_fsp.h b/src/occ_405/cmdh/cmdh_fsp.h
index 4570f58..6a59367 100755
--- a/src/occ_405/cmdh/cmdh_fsp.h
+++ b/src/occ_405/cmdh/cmdh_fsp.h
@@ -314,6 +314,7 @@ 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
void notifyCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond);
void clearCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond);
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
index 23f9b29..a51080c 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
@@ -84,6 +84,7 @@ extern uint32_t G_curr_proc_gpu_config;
extern bool G_gpu_config_done;
extern bool G_gpu_monitoring_allowed;
extern task_t G_task_table[TASK_END];
+extern bool G_pgpe_shared_sram_V_I_readings;
typedef struct data_req_table
{
@@ -1343,6 +1344,8 @@ errlHndl_t data_store_avsbus_config(const cmdh_fsp_cmd_t * i_cmd_ptr,
{
if ((l_cmd_ptr->vdd_rail >= 0) && (l_cmd_ptr->vdd_rail <= 15))
{
+ // may be getting Vdd from PGPE but this could be enabled with internal flag
+ // for OCC to handle overflow, that checking will be done in amec_update_avsbus_sensors()
G_avsbus_vdd_monitoring = TRUE;
G_sysConfigData.avsbus_vdd.bus = l_cmd_ptr->vdd_bus;
G_sysConfigData.avsbus_vdd.rail = l_cmd_ptr->vdd_rail;
@@ -1376,17 +1379,27 @@ errlHndl_t data_store_avsbus_config(const cmdh_fsp_cmd_t * i_cmd_ptr,
{
if ((l_cmd_ptr->vdn_rail >= 0) && (l_cmd_ptr->vdn_rail <= 15))
{
- G_avsbus_vdn_monitoring = TRUE;
- G_sysConfigData.avsbus_vdn.bus = l_cmd_ptr->vdn_bus;
- G_sysConfigData.avsbus_vdn.rail = l_cmd_ptr->vdn_rail;
- CNFG_DBG("data_store_avsbus_config: Vdn bus[%d] rail[%d]",
- G_sysConfigData.avsbus_vdn.bus, G_sysConfigData.avsbus_vdn.rail);
-
- if (G_avsbus_vdd_monitoring &&
- (G_sysConfigData.avsbus_vdd.bus == G_sysConfigData.avsbus_vdn.bus))
+ if(G_pgpe_shared_sram_V_I_readings)
{
- CMDH_TRAC_ERR("data_store_avsbus_config: Vdd and Vdn can not use the same AVS bus");
- l_invalid_data = TRUE;
+ // going to be getting Vdn from PGPE and no way to enable from AVSbus
+ CMDH_TRAC_INFO("Reading Vdn from PGPE turning off Vdn monitoring");
+ G_avsbus_vdn_monitoring = FALSE;
+ }
+
+ else
+ {
+ G_avsbus_vdn_monitoring = TRUE;
+ G_sysConfigData.avsbus_vdn.bus = l_cmd_ptr->vdn_bus;
+ G_sysConfigData.avsbus_vdn.rail = l_cmd_ptr->vdn_rail;
+ CNFG_DBG("data_store_avsbus_config: Vdn bus[%d] rail[%d]",
+ G_sysConfigData.avsbus_vdn.bus, G_sysConfigData.avsbus_vdn.rail);
+
+ if (G_avsbus_vdd_monitoring &&
+ (G_sysConfigData.avsbus_vdd.bus == G_sysConfigData.avsbus_vdn.bus))
+ {
+ CMDH_TRAC_ERR("data_store_avsbus_config: Vdd and Vdn can not use the same AVS bus");
+ l_invalid_data = TRUE;
+ }
}
}
else
@@ -1418,7 +1431,8 @@ errlHndl_t data_store_avsbus_config(const cmdh_fsp_cmd_t * i_cmd_ptr,
l_invalid_data = TRUE;
}
- if (l_invalid_data || !G_avsbus_vdd_monitoring || !G_avsbus_vdn_monitoring)
+ if( (l_invalid_data) ||
+ ( !G_pgpe_shared_sram_V_I_readings && (!G_avsbus_vdd_monitoring || !G_avsbus_vdn_monitoring) ) )
{
cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
G_avsbus_vdd_monitoring = FALSE;
diff --git a/src/occ_405/main.c b/src/occ_405/main.c
index 5e4a0c8..7f609d9 100755
--- a/src/occ_405/main.c
+++ b/src/occ_405/main.c
@@ -69,6 +69,19 @@
// in SRAM
bool G_ipl_time = false;
+// Defaults for Reading V/I from OCC-PGPE Shared SRAM
+// if reading from shared SRAM is supported we will read every tick and
+// run WOF every tick. All defaults will assume not supported.
+
+// indication on where OCC is getting voltage/current readings from
+// PGPE shared SRAM or reading directly from AVSbus
+bool G_pgpe_shared_sram_V_I_readings = false;
+
+// timeout, as number of WOF ticks, for PGPE VFRT command
+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;
+
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;
@@ -501,6 +514,7 @@ bool read_pgpe_header(void)
uint32_t userdata1 = 0;
uint32_t userdata2 = 0;
uint64_t magic_number = 0;
+ uint32_t pgpe_shared_magic_number = 0;
MAIN_TRAC_INFO("read_pgpe_header(0x%08X)", PGPE_HEADER_ADDR);
do
@@ -521,6 +535,7 @@ bool read_pgpe_header(void)
G_pgpe_header.requested_active_quad_sram_addr = in32(PGPE_HEADER_ADDR + PGPE_REQUESTED_ACTIVE_QUAD_ADDR_OFFSET);
G_pgpe_header.wof_tables_addr = in32(PGPE_HEADER_ADDR + PGPE_WOF_TBLS_ADDR_OFFSET);
G_pgpe_header.wof_tables_length = in32(PGPE_HEADER_ADDR + PGPE_WOF_TBLS_LEN_OFFSET);
+ G_pgpe_header.pgpe_produced_wof_values_addr = in32(PGPE_HEADER_ADDR + PGPE_PRODUCED_WOF_VALUES_ADDR_OFFSET);
const uint32_t hcode_elog_table_addr = G_pgpe_header.shared_sram_addr + HCODE_ELOG_TABLE_SRAM_OFFSET;
if (HCODE_ELOG_TABLE_MAGIC_NUMBER == in32(hcode_elog_table_addr))
@@ -561,6 +576,73 @@ bool read_pgpe_header(void)
userdata2 = WORD_LOW(G_pgpe_header.shared_sram_addr);
break;
}
+ // verify what version of OCC-PGPE shared SRAM we have so we know how we are reading
+ // voltage and current
+ pgpe_shared_magic_number = in32(G_pgpe_header.shared_sram_addr);
+ // older PGPE P9 code didn't fill in the magic number, if 0 assume P9
+ if( (pgpe_shared_magic_number == 0) ||
+ (pgpe_shared_magic_number == OPS_MAGIC_NUMBER_P9) )
+ {
+ // no support for reading voltage/current from PGPE, OCC reads via AVS bus
+ G_pgpe_shared_sram_V_I_readings = false;
+ MAIN_TRAC_IMP("Reading V/I from AVSbus for PGPE shared SRAM magic number[0x%08x]",
+ pgpe_shared_magic_number);
+ }
+ else if(pgpe_shared_magic_number == OPS_MAGIC_NUMBER_P9_PRIME)
+ {
+ if (G_pgpe_header.pgpe_produced_wof_values_addr == 0)
+ {
+ // don't have a valid address
+ MAIN_TRAC_ERR("read_pgpe_header: PGPE Produced WOF Values Address is 0! 0 Address read from [0x%08X]",
+ WORD_LOW(PGPE_HEADER_ADDR + PGPE_PRODUCED_WOF_VALUES_ADDR_OFFSET));
+ /*
+ * @errortype
+ * @moduleid READ_PGPE_HEADER
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 lower word of PGPE Produced WOF values sram address
+ * @userdata2 lower word of SRAM address PGPE Produced WOF values SRAM addr was read from
+ * @userdata4 ERC_PGPE_WOF_VALUES_INVALID_ADDRESS
+ * @devdesc Invalid sram address for PGPE Produced WOF values from PGPE header
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_PGPE_WOF_VALUES_INVALID_ADDRESS;
+ userdata1 = WORD_LOW(G_pgpe_header.pgpe_produced_wof_values_addr);
+ userdata2 = WORD_LOW(PGPE_HEADER_ADDR + PGPE_PRODUCED_WOF_VALUES_ADDR_OFFSET);
+ break;
+ }
+ else
+ {
+ // read voltage/current from OCC-PGPE shared SRAM
+ MAIN_TRAC_IMP("Reading V/I from PGPE Shared SRAM addr[0x%08X] for Magic Number[0x%08X]",
+ G_pgpe_header.pgpe_produced_wof_values_addr, pgpe_shared_magic_number);
+ G_pgpe_shared_sram_V_I_readings = true;
+
+ // this also means we will be running WOF every tick, update WOF timeouts
+ // for runnning every tick to keep same timeout
+ G_max_vfrt_chances = MAX_VFRT_CHANCES_EVERY_TICK;
+ G_max_wof_control_chances = MAX_WOF_CONTROL_CHANCES_EVERY_TICK;
+ }
+ }
+ else
+ {
+ // magic number not supported
+ MAIN_TRAC_ERR("read_pgpe_header: Invalid PGPE Shared SRAM Magic number. Addr[0x%08X], Magic Number[0x%08X]",
+ G_pgpe_header.shared_sram_addr, pgpe_shared_magic_number);
+ /* @
+ * @errortype
+ * @moduleid READ_PGPE_HEADER
+ * @reasoncode INVALID_MAGIC_NUMBER
+ * @userdata1 OCC PGPE Shared SRAM magic number
+ * @userdata2 0
+ * @userdata4 ERC_OPS_INVALID_MAGIC_NUMBER
+ * @devdesc Invalid magic number in OCC PGPE Shared SRAM
+ */
+ l_reasonCode = INVALID_MAGIC_NUMBER;
+ l_extReasonCode = ERC_OPS_INVALID_MAGIC_NUMBER;
+ userdata1 = pgpe_shared_magic_number;
+ userdata2 = 0;
+ break;
+ }
}
else
{
diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h
index d54244e..4ef537d 100644
--- a/src/occ_405/occ_service_codes.h
+++ b/src/occ_405/occ_service_codes.h
@@ -264,6 +264,8 @@ enum occExtReasonCode
ERC_PGPE_ACTIVE_TO_OBSERVATION_TIMEOUT = 0x00B9,
ERC_PGPE_TASK_TIMEOUT = 0x00BA,
ERC_PGPE_INVALID_ADDRESS = 0x00BB,
+ ERC_OPS_INVALID_MAGIC_NUMBER = 0x00BC,
+ ERC_PGPE_WOF_VALUES_INVALID_ADDRESS = 0x00BD,
ERC_WOF_QUAD_COUNT_FAILURE = 0x00C0,
ERC_WOF_CONTROL_ERROR = 0x00C1,
diff --git a/src/occ_405/pgpe/pgpe_shared.h b/src/occ_405/pgpe/pgpe_shared.h
index e9b958f..0c23392 100644
--- a/src/occ_405/pgpe/pgpe_shared.h
+++ b/src/occ_405/pgpe/pgpe_shared.h
@@ -29,6 +29,12 @@
#define OPPB_MAGIC_NUMBER_10 0x4F43435050423030ull // "OCCPPB00"
#define PGPE_MAGIC_NUMBER_10 0x504750455F312E30ull // "PGPE_1.0"
+// magic number for OCC-PGPE Shared Sram
+#define OPS_MAGIC_NUMBER_P9 0x4F505330ull // "OPS0"
+#define OPS_MAGIC_NUMBER_P9_PRIME 0x4F505331ull // "OPS1"
+#define OPS_MAGIC_NUMBER_P10 0x4F505332ull // "OPS2"
+
+
// Address and offset to find PGPE PK trace
#define PGPE_DEBUG_PTRS_ADDR 0xFFF20200 // 0xfff20000 + 0x200
#define PGPE_DEBUG_TRACE_ADDR_OFFSET 0x04
@@ -47,6 +53,7 @@
#define PGPE_REQUESTED_ACTIVE_QUAD_ADDR_OFFSET 0x54
#define PGPE_WOF_TBLS_ADDR_OFFSET 0x58
#define PGPE_WOF_TBLS_LEN_OFFSET 0x5C
+#define PGPE_PRODUCED_WOF_VALUES_ADDR_OFFSET 0x78
// This size must be a multiple of 128
typedef struct __attribute__ ((packed))
@@ -87,6 +94,7 @@ typedef struct __attribute__ ((packed))
uint32_t requested_active_quad_sram_addr;
uint32_t wof_tables_addr;
uint32_t wof_tables_length;
+ uint32_t pgpe_produced_wof_values_addr;
} pgpe_header_data_t;
extern pgpe_header_data_t G_pgpe_header;
diff --git a/src/occ_405/wof/wof.c b/src/occ_405/wof/wof.c
index 0a5bff3..f1e0967 100644
--- a/src/occ_405/wof/wof.c
+++ b/src/occ_405/wof/wof.c
@@ -36,6 +36,7 @@
#include <wof.h>
#include <amec_freq.h>
#include <pgpe_interface.h>
+#include <avsbus.h>
#include "common.h" // For ignore_pgpe_error()
//******************************************************************************
// External Globals
@@ -49,6 +50,8 @@ extern GpeRequest G_wof_control_req;
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;
+
//******************************************************************************
// Globals
//******************************************************************************
@@ -117,25 +120,22 @@ int16_t G_wof_iddq_mult_table[][2] = {
* such that the WOF algorithm can run. This includes making
* sure the PGPE is ready to perform WOF calculations and enforcing
* when WOF should wait a tick to perform a calc or disable wof
- * entirely. Called from amec_slave_smh.c::amec_slv_state_4.
- * This should run every 4ms, if HW_MICS_PER_TICK changes adjust calls
- * to this function (use amec substates) to keep this called every 4ms
+ * entirely. Called from amec_slave_smh.c::amec_slv_common_tasks_post.
* Param: None
*
* Return: None
*/
void call_wof_main( void )
{
- // Variable to ensure we do not keep trying to send vfrt GpeRequest
- // more than 1 extra time.
- static uint8_t L_vfrt_last_chance = MAX_VFRT_CHANCES;
+ // Timeout for VFRT to complete
+ static uint8_t L_vfrt_last_chance = MAX_VFRT_CHANCES_EVERY_TICK;
- // Variable to ensure we do not keep trying to send the wof control
- static bool L_wof_control_last_chance = false;
+ // Timeout for WOF Control to complete
+ static uint8_t L_wof_control_last_chance = MAX_WOF_CONTROL_CHANCES_EVERY_TICK;
// Variable to keep track of logging timeouts being ignored
- // Since WOF runs every 4ms we have already waited more than the required 1ms for PGPE
- // to set the bit to give ignore indication so no additional timer needed before checking
+ // WOF runs every 500us all timeouts must be at least 1ms for PGPE
+ // to have time to set the bit to give ignore indication
static bool L_current_timeout_recorded = false;
// Variable to keep track of PState enablement to prevent setting/clearing
@@ -231,6 +231,10 @@ void call_wof_main( void )
// For each possible initialization state,
// do the appropriate action
case WOF_DISABLED:
+ // Reset timeouts for VFRT response and WOF control
+ L_vfrt_last_chance = MAX_VFRT_CHANCES;
+ L_wof_control_last_chance = MAX_WOF_CONTROL_CHANCES;
+
// calculate initial vfrt, send gpeRequest
// Initial vfrt is the last vfrt in Main memory
send_initial_vfrt_to_pgpe();
@@ -252,9 +256,11 @@ void call_wof_main( void )
}
else if(L_vfrt_last_chance != 0)
{
- INTR_TRAC_INFO("initial VFRT NOT idle."
- " %d more chance(s)",
- L_vfrt_last_chance );
+ if( L_vfrt_last_chance == 1 )
+ {
+ INTR_TRAC_INFO("initial VFRT NOT idle. Last chance out of %d chances",
+ MAX_VFRT_CHANCES);
+ }
L_vfrt_last_chance--;
}
else
@@ -280,18 +286,21 @@ void call_wof_main( void )
if( !enable_success )
{
// Treat as an error only if not currently ignoring PGPE failures
- if( L_wof_control_last_chance && (!ignore_pgpe_error()) )
+ if( (L_wof_control_last_chance == 0) && (!ignore_pgpe_error()) )
{
INTR_TRAC_ERR("WOF Disabled! Control req timeout(1)");
set_clear_wof_disabled(SET,
WOF_RC_CONTROL_REQ_TIMEOUT,
ERC_WOF_CONTROL_REQ_TIMEOUT);
}
- else if(!L_wof_control_last_chance)
+ else if(L_wof_control_last_chance != 0)
{
- INTR_TRAC_ERR("One more chance for WOF "
- "control request(1)");
- L_wof_control_last_chance = true;
+ if(L_wof_control_last_chance == 1 )
+ {
+ INTR_TRAC_ERR("Last chance for WOF control request(1) out of %d chances ",
+ MAX_WOF_CONTROL_CHANCES);
+ }
+ L_wof_control_last_chance--;
}
else
{
@@ -308,7 +317,7 @@ void call_wof_main( void )
{
// Reset the last chance variable
// Init state updated in enable_wof
- L_wof_control_last_chance = false;
+ L_wof_control_last_chance = MAX_WOF_CONTROL_CHANCES;
L_current_timeout_recorded = FALSE;
}
@@ -319,18 +328,21 @@ void call_wof_main( void )
if( !async_request_is_idle(&G_wof_control_req.request) )
{
// Treat as an error only if not currently ignoring PGPE failures
- if( L_wof_control_last_chance && (!ignore_pgpe_error()) )
+ if( (L_wof_control_last_chance == 0) && (!ignore_pgpe_error()) )
{
INTR_TRAC_ERR("WOF Disabled! Control req timeout(2)");
set_clear_wof_disabled(SET,
WOF_RC_CONTROL_REQ_TIMEOUT,
ERC_WOF_CONTROL_REQ_TIMEOUT );
}
- else if(!L_wof_control_last_chance)
+ else if(L_wof_control_last_chance != 0)
{
- INTR_TRAC_ERR("One more chance for WOF "
- "control request(2)");
- L_wof_control_last_chance = true;
+ if(L_wof_control_last_chance == 1 )
+ {
+ INTR_TRAC_ERR("Last chance for WOF control request(2) out of %d chances ",
+ MAX_WOF_CONTROL_CHANCES);
+ }
+ L_wof_control_last_chance--;
}
else
{
@@ -388,8 +400,11 @@ void call_wof_main( void )
}
else
{
- INTR_TRAC_INFO("VFRT NOT idle. %d more chance(s)",
- L_vfrt_last_chance);
+ if( L_vfrt_last_chance == 1 )
+ {
+ INTR_TRAC_INFO("VFRT NOT idle. Last chance out of %d chances",
+ MAX_VFRT_CHANCES);
+ }
L_vfrt_last_chance--;
}
}
@@ -430,12 +445,13 @@ void call_wof_main( void )
*/
void wof_main( void )
{
+ // Some sensors may be updated from PGPE data so we must read PGPE data before reading sensors
+ // Read out PGPE data from shared SRAM
+ read_shared_sram();
// Read out the sensor data needed for calculations
read_sensor_data();
- // Read out PGPE data from shared SRAM
- read_shared_sram();
// Calculate the core voltage per quad
calculate_core_voltage();
@@ -782,6 +798,11 @@ void read_shared_sram( void )
sensor_update(AMECSENSOR_PTR(VRATIO), (uint16_t)l_wofstate.fields.vratio);
g_wof->f_ratio = 1;
+
+ // the PGPE produced WOF values were already read in this tick from amec_update_avsbus_sensors()
+ // required to read them in every tick regardless of WOF running so voltage and current sensors
+ // are updated even when WOF isn't running
+
// Get the requested active quad update
read_req_active_quads();
@@ -811,6 +832,74 @@ void read_shared_sram( void )
}
/**
+ * read_pgpe_produced_wof_values
+ *
+ * Description: Read the PGPE Produced WOF values from OCC-PGPE shared SRAM and
+ * update sensors
+ */
+void read_pgpe_produced_wof_values( void )
+{
+ uint16_t l_voltage = 0;
+ uint16_t l_current = 0;
+
+ pgpe_wof_values_t l_PgpeWofValues;
+ l_PgpeWofValues.dw0.value = in64(G_pgpe_header.pgpe_produced_wof_values_addr);
+ l_PgpeWofValues.dw1.value = in64(G_pgpe_header.pgpe_produced_wof_values_addr + 0x08);
+ l_PgpeWofValues.dw2.value = in64(G_pgpe_header.pgpe_produced_wof_values_addr + 0x10);
+ l_PgpeWofValues.dw3.value = in64(G_pgpe_header.pgpe_produced_wof_values_addr + 0x18);
+
+ // save Vdd voltage to sensor
+ l_voltage = (uint16_t)l_PgpeWofValues.dw2.fields.vdd_avg_mv;
+ if (l_voltage != 0)
+ {
+ // Voltage value stored in the sensor should be in 100uV (mV scale -1)
+ l_voltage *= 10;
+ sensor_update(AMECSENSOR_PTR(VOLTVDD), l_voltage);
+ }
+
+ // save Vdn voltage to sensor
+ l_voltage = (uint16_t)l_PgpeWofValues.dw2.fields.vdn_avg_mv;
+ if (l_voltage != 0)
+ {
+ // Voltage value stored in the sensor should be in 100uV (mV scale -1)
+ l_voltage *= 10;
+ sensor_update(AMECSENSOR_PTR(VOLTVDN), l_voltage);
+ }
+
+ // don't use Vdd current from PGPE if it was enabled for OCC to read from AVSbus
+ if(!(G_internal_flags & INT_FLAG_ENABLE_VDD_CURRENT_READ))
+ {
+ // Save Vdd current to sensor
+ l_current = (uint16_t)l_PgpeWofValues.dw1.fields.idd_avg_ma;
+ if (l_current != 0)
+ {
+ // Current value stored in the sensor should be in 10mA (A scale -2)
+ // Reading from SRAM is already in 10mA
+ sensor_update(AMECSENSOR_PTR(CURVDD), l_current);
+ }
+ }
+
+ // Save Vdn current to sensor
+ l_current = (uint16_t)l_PgpeWofValues.dw1.fields.idn_avg_ma;
+ if (l_current != 0)
+ {
+ // Current value stored in the sensor should be in 10mA (A scale -2)
+ // Reading from SRAM is already in 10mA
+ sensor_update(AMECSENSOR_PTR(CURVDN), l_current);
+ }
+
+ // Update the chip voltage and power sensors
+ update_avsbus_power_sensors(AVSBUS_VDD);
+ update_avsbus_power_sensors(AVSBUS_VDN);
+
+ // save the PGPE WOF values
+ 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
*
* Description: Calculate the core voltage based on Pstate and IVRM state.
diff --git a/src/occ_405/wof/wof.h b/src/occ_405/wof/wof.h
index 69f5412..e63fa67 100644
--- a/src/occ_405/wof/wof.h
+++ b/src/occ_405/wof/wof.h
@@ -37,7 +37,19 @@
#define PGPE_WOF_OFF 0
#define PGPE_WOF_ON 1
#define NUM_CORES_PER_QUAD 4
-#define MAX_VFRT_CHANCES 2
+
+// default number of chances for WOF running every 8th tick, actual timeout
+// used will be adjusted if WOF runs every tick
+#define MAX_VFRT_CHANCES_EVERY_8TH_TICK 2 // 8ms = 4ms * 2
+#define MAX_VFRT_CHANCES_EVERY_TICK 16 // 8ms = 500us * 16
+#define MAX_VFRT_CHANCES G_max_vfrt_chances
+#define MAX_WOF_CONTROL_CHANCES_EVERY_8TH_TICK 2 // 8ms = 4ms * 2
+#define MAX_WOF_CONTROL_CHANCES_EVERY_TICK 16 // 8ms = 500us * 16
+#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;
+
+
#define WOF_TABLES_OFFSET 0xC0000 // Relative to PPMR_ADDRESS_HOMER
#define MAX_CEFF_RATIO 10000 // 1.0 ratio = 10000
// (scaled to avoid floating point)
@@ -367,6 +379,10 @@ typedef struct __attribute__ ((packed))
uint8_t quad5CoresCachesOnT[CORE_IDDQ_MEASUREMENTS];
uint8_t quad6CoresCachesOnT[CORE_IDDQ_MEASUREMENTS];
uint8_t avgtemp_vdn[CORE_IDDQ_MEASUREMENTS];
+ uint64_t pgpe_wof_values_dw0;
+ uint64_t pgpe_wof_values_dw1;
+ uint64_t pgpe_wof_values_dw2;
+ uint64_t pgpe_wof_values_dw3;
} amec_wof_t;
// Structure for sensors used in g_amec for AMESTER
@@ -411,6 +427,8 @@ void send_vfrt_to_pgpe( uint32_t i_vfrt_address );
void read_shared_sram( void );
+void read_pgpe_produced_wof_values( void );
+
void calculate_core_voltage( void );
void calculate_core_leakage( void );
OpenPOWER on IntegriCloud