diff options
author | mbroyles <mbroyles@us.ibm.com> | 2019-03-26 13:14:53 -0500 |
---|---|---|
committer | Martha Broyles <mbroyles@us.ibm.com> | 2019-04-23 13:45:01 -0500 |
commit | cf4c143eb571de19c03d1c66e963feb6bed4f190 (patch) | |
tree | faebe0e25f483ecb30c0d98517c3ec1e5c71d52a /src/occ_405 | |
parent | 91d3487ed586ba53e6bc34111c374a581aa52060 (diff) | |
download | talos-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-x | src/occ_405/amec/amec_parm.h | 9 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_parm_table.c | 9 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_dbug_cmd.c | 75 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_dbug_cmd.h | 24 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_fsp.h | 10 | ||||
-rw-r--r-- | src/occ_405/common.h | 2 | ||||
-rwxr-xr-x | src/occ_405/errl/errl.h | 4 | ||||
-rwxr-xr-x | src/occ_405/main.c | 10 | ||||
-rwxr-xr-x | src/occ_405/sensor/sensor_enum.h | 1 | ||||
-rwxr-xr-x | src/occ_405/sensor/sensor_info.c | 1 | ||||
-rwxr-xr-x | src/occ_405/sensor/sensor_table.c | 3 | ||||
-rw-r--r-- | src/occ_405/wof/wof.c | 544 | ||||
-rw-r--r-- | src/occ_405/wof/wof.h | 33 |
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 |