diff options
-rw-r--r-- | src/include/pstate_pgpe_occ_api.h | 280 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_parm.h | 4 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_parm_table.c | 4 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_sensors_power.c | 141 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_slave_smh.c | 29 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_fsp.h | 1 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c | 36 | ||||
-rwxr-xr-x | src/occ_405/main.c | 82 | ||||
-rw-r--r-- | src/occ_405/occ_service_codes.h | 2 | ||||
-rw-r--r-- | src/occ_405/pgpe/pgpe_shared.h | 8 | ||||
-rw-r--r-- | src/occ_405/wof/wof.c | 145 | ||||
-rw-r--r-- | src/occ_405/wof/wof.h | 20 |
12 files changed, 641 insertions, 111 deletions
diff --git a/src/include/pstate_pgpe_occ_api.h b/src/include/pstate_pgpe_occ_api.h index 0593b62..d6ee76c 100644 --- a/src/include/pstate_pgpe_occ_api.h +++ b/src/include/pstate_pgpe_occ_api.h @@ -1,25 +1,19 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/include/pstate_pgpe_occ_api.h $ */ +/* $Source: chips/p9/common/pmlib/include/pstate_pgpe_occ_api.h $ */ /* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2019 */ -/* [+] International Business Machines Corp. */ +/* IBM CONFIDENTIAL */ /* */ +/* EKB Project */ /* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ +/* COPYRIGHT 2015,2019 */ +/* [+] International Business Machines Corp. */ /* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ +/* 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. */ /* */ /* IBM_PROLOG_END_TAG */ /// @file p9_pstates_pgpe_occ_api.h @@ -31,7 +25,6 @@ // *HWP Level : 1 // *HWP Consumed by : PGPE:OCC - #ifndef __P9_PSTATES_PGPE_API_H__ #define __P9_PSTATES_PGPE_API_H__ @@ -53,7 +46,7 @@ enum MESSAGE_ID_IPI2HI MSGID_405_CLIPS = 2, MSGID_405_SET_PMCR = 3, MSGID_405_WOF_CONTROL = 4, - MSGID_405_WOF_VFRT = 5 + MSGID_405_WOF_VRT = 5 }; // @@ -67,9 +60,9 @@ enum MESSAGE_ID_IPI2HI // Active quad mismatch with requested active quads. PGPE did not switch // to using the new VFRT. The original VFRT is still being used. #define PGPE_WOF_RC_VFRT_QUAD_MISMATCH 0x20 -#define PGPE_RC_REQ_WHILE_PENDING_ACK 0x21 -#define PGPE_RC_NULL_VFRT_POINTER 0x22 -#define PGPE_RC_INVALID_PMCR_OWNER 0x23 +#define PGPE_RC_REQ_WHILE_PENDING_ACK 0x21 +#define PGPE_RC_NULL_VRT_POINTER 0x22 +#define PGPE_RC_INVALID_PMCR_OWNER 0x23 // // PMCR Owner @@ -142,13 +135,12 @@ typedef struct ipcmsg_wof_vfrt HomerVFRTLayout_t* homer_vfrt_ptr; } ipcmsg_wof_vfrt_t; - // ----------------------------------------------------------------------------- // Start Pstate Table #define MAX_OCC_PSTATE_TABLE_ENTRIES 256 -/// Pstate Table produce by the PGPE for consumption by OCC Firmware +/// Pstate Table produced by the PGPE for consumption by OCC Firmware /// /// This structure defines the Pstate Table content /// -- 16B structure @@ -175,6 +167,81 @@ typedef struct // End Pstate Table // ----------------------------------------------------------------------------- +// Start FFDC + +/// Scopes of the First Failure Data Capture (FFDC) registers +enum scope_type +{ + FFDC_CHIP = 0, // Address is chip scope (eg absolute) + FFDC_QUAD = 1, // Address + 0x01000000*quad for good quads from 0 to 5 + FFDC_CORE = 2, // Address + 0x01000000*core for good cores from 0 to 23 + FFDC_CME = 3 // Address if EX is even; Address + 0x400*EX for EX odd for good Exs from 0 to 11 +}; + +/// Address types of First Failure Data Capture (FFDC) register addresses +enum scope_type1 +{ + FFDC_OCI = 0, // Address is an OCI address + FFDC_SCOM = 1 // Address is a SCOM address +}; + +/// Register definition of the Hcode FFDC register list +#define MAX_FFDC_REG_LIST 12 +typedef struct +{ + uint32_t address; + /* union address_attribute + { + uint32_t value; + struct + { + uint32_t address_type : 16; + uint32_t scope : 16; + } attr; + }*/ +} Hcode_FFDC_entry_t; + +/// Hcode FFDC register list +typedef struct +{ + /// Number of FFDC address list entries + uint32_t list_entries; + + /// FFDC Address list + Hcode_FFDC_entry_t list[MAX_FFDC_REG_LIST]; +} Hcode_FFDC_list_t; + + + +/// Hcode FFDC register list +/// @todo RTC: 161183 Fill out the rest of this FFDC list +/// @note The reserved FFDC space for registers and traces set aside in the +/// OCC is 1KB. On the register side, the following list will generate +/// 12B of content (4B address, 8B data) x the good entries per scope. +/// CHIP scope are not dependent on partial good or currently active and will +/// take 12B x 8 = 96B. CME scope entries will, at maximum, generate 12B x +/// 12 CMEs x 4 SCOMs = 576B.. The overall totla for registers is 96 + 576 +/// +/*typedef struct Hcode_FFDC_list +{ + + {PERV_TP_OCC_SCOM_OCCLFIR, FFDC_SCOM, FFDC_CHIP }, // OCC LFIR + {PU_PBAFIR, FFDC_SCOM, FFDC_CHIP }, // PBA LFIR + {EX_CME_SCOM_LFIR, FFDC_SCOM, FFDC_CME }, // CME LFIR + {PU_GPE3_GPEDBG_OCI, FFDC_OCI, FFDC_CHIP }, // SGPE XSR, SPRG0 + {PU_GPE3_GPEDDR_OCI, FFDC_OCI, FFDC_CHIP }, // SGPE IR, EDR + {PU_GPE3_PPE_XIDBGPRO, FFDC_OCI, FFDC_CHIP }, // SGPE XSR, IAR + {PU_GPE2_GPEDBG_OCI, FFDC_OCI, FFDC_CHIP }, // PGPE XSR, SPRG0 + {PU_GPE2_GPEDDR_OCI, FFDC_OCI, FFDC_CHIP }, // PGPE IR, EDR + {PU_GPE2_PPE_XIDBGPRO, FFDC_OCI, FFDC_CHIP }, // PGPE XSR, IAR + {EX_PPE_XIRAMDBG, FFDC_SCOM, FFDC_CME }, // CME XSR, SPRG0 + {EX_PPE_XIRAMEDR, FFDC_SCOM, FFDC_CME }, // CME IR, EDR + {EX_PPE_XIDBGPRO, FFDC_SCOM, FFDC_CME }, // CME XSR, IAR + +};*/ + +// End FFDC +// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // Start Quad State @@ -282,6 +349,157 @@ typedef struct pgpe_error_table // End Error Log Table // ----------------------------------------------------------------------------- +typedef struct +{ + union + { + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + struct + { + uint64_t average_pstate : 8; + uint64_t average_frequency_pstate : 8; + uint64_t clip_pstate : 8; + uint64_t reserved : 8; + uint64_t vratio_inst : 16; + uint64_t vratio_avg : 16; + } fields; + } dw0; + union + { + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + struct + { + uint64_t idd_avg_ma : 16; + uint64_t ics_avg_ma : 16; + uint64_t idn_avg_ma : 16; + uint64_t iio_avg_ma : 16; + + } fields; + } dw1; + union + { + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + struct + { + uint64_t vdd_avg_mv : 16; + uint64_t vcs_avg_mv : 16; + uint64_t vdn_avg_mv : 16; + uint64_t vio_avg_mv : 16; + } fields; + } dw2; + union + { + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + struct + { + uint64_t ocs_avg_0p01pct : 16; + uint64_t reserved : 48; + } fields; + } dw3; +} pgpe_wof_values_t; + +typedef struct +{ + union + { + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + struct + { + uint64_t magic_word : 32; //ELTC + uint64_t total_log_slots : 8; + uint64_t reserved : 24; + } fields; + } dw0; + union + { + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + struct + { + uint64_t errlog_id : 8; + uint64_t errlog_src : 8; + uint64_t errlog_len : 16; + uint64_t pgpe_critical_log_address : 32; + } fields; + } dw1; + union + { + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + struct + { + uint64_t errlog_id : 8; + uint64_t errlog_src : 8; + uint64_t errlog_len : 16; + uint64_t pgpe_info_log_address : 32; + } fields; + } dw2; + union + { + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + struct + { + uint64_t errlog_id : 8; + uint64_t errlog_src : 8; + uint64_t errlog_len : 16; + uint64_t sgpe_critical_log_address : 32; + } fields; + } dw3; + union + { + uint64_t value; + struct + { + uint32_t high_order; + uint32_t low_order; + } words; + struct + { + uint64_t errlog_id : 8; + uint64_t errlog_src : 8; + uint64_t errlog_len : 16; + uint64_t sgpe_info_log_address : 32; + } fields; + } dw4; +} errlog_idx_t; typedef struct { @@ -297,21 +515,25 @@ typedef struct /// Actual Pstate 1 - Quads 4, 5 quad_state1_t quad_pstate_1; - ///PGPE WOF State + /// PGPE Produced WOF State pgpe_wof_state_t pgpe_wof_state; - ///Requested Active Quads + ///Requested Active Quads requested_active_quads_t req_active_quads; - // PGPE Produced WOF Values - uint64_t pgpe_produced_wof_values[2]; + //PGPE WOF Values + pgpe_wof_values_t pgpe_wof_values; - // Reserved - uint64_t reserved; + //Reserved + uint64_t reserved1; - // Error Log Table + /// Hcode Error Log Index + errlog_idx_t errlog_idx; pgpe_error_table_t pgpe_error_table; + //Reserved + uint64_t reserved2[24]; + /// Pstate Table OCCPstateTable_t pstate_table; @@ -321,4 +543,4 @@ typedef struct } // end extern C #endif -#endif /* __P9_PSTATES_PGPE_API_H__ */ +#endif /* __PSTATES_PGPE_OCC_API_H__ */ 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 ); |