summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRahul Batra <rbatra@us.ibm.com>2018-12-05 11:59:26 -0600
committerhostboot <hostboot@us.ibm.com>2019-01-25 19:24:40 -0600
commite5e276106c9e8fbb648c8f9ff4d2c7f6b82dcb97 (patch)
tree8805e50a2397a2f4b5b39933db79277a8f18dbb4
parent9b0e0c73659f729e4728a5b772bda93fb7fb7be7 (diff)
downloadtalos-hcode-e5e276106c9e8fbb648c8f9ff4d2c7f6b82dcb97.tar.gz
talos-hcode-e5e276106c9e8fbb648c8f9ff4d2c7f6b82dcb97.zip
PGPE: WOV Hcode Updates (3/3)
3rd commit in the series of 3 commits for Workload Optimized Voltage(WOV) Commit 1. Adds WOV attributes Commit 2(Hostboot). WOV HW procedures changes and global parm updates Commit 3(Hcode). PGPE Hcode changes for WOV(undervolting only) feature Key_Cronus_Test=PM_REGRESS HW-Image-Prereq: I9833e8713d362684c1537b08478a9c9934e5012e CMVC-Prereq: 1074650 Change-Id: I9833e8713d362684c1537b08478a9c9934e5012e Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/69465 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Cronus HW CI <cronushw-ci+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: RANGANATHPRASAD G. BRAHMASAMUDRA <prasadbgr@in.ibm.com> Reviewed-by: Gregory S. Still <stillgs@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c101
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c8
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h5
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c12
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c403
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h52
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c5
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c26
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pgpe_panic_codes.h8
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_common.mk4
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk4
11 files changed, 487 insertions, 141 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c
index 708b1c4a..ccb76618 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HCODE Project */
/* */
-/* COPYRIGHT 2016,2018 */
+/* COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -50,6 +50,8 @@ uint32_t G_tb_sync_count;
uint32_t G_quad_hb_value;
+uint32_t G_wov_count;
+
extern GlobalPstateParmBlock* G_gppb;
extern PgpeHeader_t* G_pgpe_header_data;
extern PgpePstateRecord G_pgpe_pstate_record;
@@ -129,7 +131,7 @@ void p9_pgpe_fit_init()
G_throttleCount = 0;
G_beacon_count = 0;
G_tb_sync_count = 0;
-
+ G_wov_count = 0;
//Set FIT handler which is called on every FIT interrupt tick
ppe42_fit_setup(p9_pgpe_fit_handler, NULL);
}
@@ -146,52 +148,55 @@ __attribute__((always_inline)) inline void handle_core_throttle()
uint32_t config = in32(G_OCB_OCCS2); //bits 16-18 in OCC Scratch Register 2
uint32_t run = (config >> 14) & 0x3; //this looks at the inject and enable bits, if either are high we run
- if(run) //Currently running
+ if (!(in32(G_OCB_OCCFLG) & BIT32(PGPE_PROLONGED_DROOP_WORKAROUND_ACTIVE)))
{
- uint32_t throttleData = G_orig_throttle;
- uint32_t inject = run & 0x1; //Inject is bit 17, if this is high we run one throttle burst then turn off
- uint32_t type = (config >> 13) & 0x1; //type is bit 18, this determines which kind of throttling we do
- uint32_t mask = type ? CORE_SLOWDOWN : CORE_IFU_THROTTLE;
- uint32_t pgpe_throttle_assert = G_pgpe_header_data->g_pgpe_core_throttle_assert_cnt;
- uint32_t pgpe_throttle_deassert = G_pgpe_header_data->g_pgpe_core_throttle_deassert_cnt;
-
- //if currently off, we don't desire always off, this is the first evaluation since become enabled, we are in always on,
- //or we (re enabled and have reached the count, then we turn throttling on (if both assert and deassert are 0 this statement fails)
- if(!G_throttleOn && pgpe_throttle_assert != 0 &&
- (G_throttleCount == 0 || pgpe_throttle_deassert == 0 || pgpe_throttle_deassert == G_throttleCount))
+ if(run) //Currently running
{
- G_throttleOn = 1;
- G_throttleCount = 0;
- throttleData |= mask; //data for start throttle
+ uint32_t throttleData = G_orig_throttle;
+ uint32_t inject = run & 0x1; //Inject is bit 17, if this is high we run one throttle burst then turn off
+ uint32_t type = (config >> 13) & 0x1; //type is bit 18, this determines which kind of throttling we do
+ uint32_t mask = type ? CORE_SLOWDOWN : CORE_IFU_THROTTLE;
+ uint32_t pgpe_throttle_assert = G_pgpe_header_data->g_pgpe_core_throttle_assert_cnt;
+ uint32_t pgpe_throttle_deassert = G_pgpe_header_data->g_pgpe_core_throttle_deassert_cnt;
+
+ //if currently off, we don't desire always off, this is the first evaluation since become enabled, we are in always on,
+ //or we (re enabled and have reached the count, then we turn throttling on (if both assert and deassert are 0 this statement fails)
+ if(!G_throttleOn && pgpe_throttle_assert != 0 &&
+ (G_throttleCount == 0 || pgpe_throttle_deassert == 0 || pgpe_throttle_deassert == G_throttleCount))
+ {
+ G_throttleOn = 1;
+ G_throttleCount = 0;
+ throttleData |= mask; //data for start throttle
- }
- //if currently on and we desire always off or we don't desire always on and have reached the count,
- //then we turn it off (if both assert and deassert are 0 this statement true)
- else if(G_throttleOn &&
- (pgpe_throttle_assert == 0 || ( pgpe_throttle_deassert != 0 && pgpe_throttle_assert == G_throttleCount)))
- {
- G_throttleOn = 0;
- G_throttleCount = 0;
- throttleData &= ~mask; //data for stop throttle
+ }
+ //if currently on and we desire always off or we don't desire always on and have reached the count,
+ //then we turn it off (if both assert and deassert are 0 this statement true)
+ else if(G_throttleOn &&
+ (pgpe_throttle_assert == 0 || ( pgpe_throttle_deassert != 0 && pgpe_throttle_assert == G_throttleCount)))
+ {
+ G_throttleOn = 0;
+ G_throttleCount = 0;
+ throttleData &= ~mask; //data for stop throttle
+
+ if(inject == 1)
+ {
+ out32(G_OCB_OCCS2, (config & 0xFFFFBFFF)); //write out to indicate inject has finished
+ }
+ }
- if(inject == 1)
+ if(G_throttleCount == 0)
{
- out32(G_OCB_OCCS2, (config & 0xFFFFBFFF)); //write out to indicate inject has finished
+ p9_pgpe_pstate_write_core_throttle(throttleData, NO_RETRY);
}
- }
- if(G_throttleCount == 0)
+ G_throttleCount++; //count always incremented, it is impossible to reach a count of 0 while enabled
+ }
+ else if(G_throttleCount != 0)
{
- p9_pgpe_pstate_write_core_throttle(throttleData, NO_RETRY);
+ G_throttleCount = 0;
+ G_throttleOn = 0;
+ p9_pgpe_pstate_write_core_throttle(G_orig_throttle, NO_RETRY);
}
-
- G_throttleCount++; //count always incremented, it is impossible to reach a count of 0 while enabled
- }
- else if(G_throttleCount != 0)
- {
- G_throttleCount = 0;
- G_throttleOn = 0;
- p9_pgpe_pstate_write_core_throttle(G_orig_throttle, NO_RETRY);
}
}
//Quads must get HB value
@@ -378,6 +383,23 @@ __attribute__((always_inline)) inline void handle_fit_timebase_sync()
}
}
+//
+// handle_undervolt
+//
+__attribute__((always_inline)) inline void handle_wov()
+{
+ if (G_pgpe_pstate_record.wov.status & WOV_UNDERVOLT_ENABLED)
+ {
+ G_wov_count++;
+
+ if (G_gppb->wov_sample_125us == G_wov_count)
+ {
+ p9_pgpe_pstate_adjust_wov();
+ G_wov_count = 0;
+ }
+ }
+}
+
// p9_pgpe_fit_handler
//
// This is a periodic FIT Handler which is called up at fixed period
@@ -392,4 +414,5 @@ void p9_pgpe_fit_handler(void* arg, PkIrqId irq)
handle_occflg_requests();
handle_aux_task();
handle_fit_timebase_sync();
+ handle_wov();
}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c
index 0864fae8..ee54b194 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HCODE Project */
/* */
-/* COPYRIGHT 2016,2018 */
+/* COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -26,6 +26,7 @@
#include "p9_pgpe_gppb.h"
#include "p9_pgpe_header.h"
#include "p9_hcode_image_defines.H"
+#include "ppehw_common.h"
typedef enum
{
@@ -301,3 +302,8 @@ uint16_t p9_pgpe_gppb_vdm_threshold_from_ps(uint32_t pstate)
return ret;
}
+
+uint32_t p9_pgpe_gppb_freq_from_ps(Pstate ps)
+{
+ return (G_gppb->reference_frequency_khz - ((ps) * G_gppb->frequency_step_khz)) / 1000;
+}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h
index bbcc2d74..685654aa 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HCODE Project */
/* */
-/* COPYRIGHT 2016,2018 */
+/* COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -72,4 +72,7 @@ uint32_t p9_pgpe_gppb_vdm_vid_cmp_from_ps(Pstate ps);
// retval - VDM Threshold(VDM_OVERVOLT:VDM_DROOP_SMALL:VDM_DROOP_LARGE:VDM_DROOP_XTREME]
uint16_t p9_pgpe_gppb_vdm_threshold_from_ps(uint32_t pstate);
+//Get Frequency for a Pstate
+uint32_t p9_pgpe_gppb_freq_from_ps(Pstate ps);
+
#endif //_P9_PGPE_GPPB_H_
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c
index d5590ac2..d1cc75e7 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HCODE Project */
/* */
-/* COPYRIGHT 2016,2018 */
+/* COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -162,7 +162,7 @@ void p9_pgpe_irq_handler_ocb_err()
G_pgpe_optrace_data.word[0] = (G_pgpe_pstate_record.activeQuads << 24) |
(G_pgpe_pstate_record.activeCores << 8);
G_pgpe_optrace_data.word[1] = (G_pgpe_pstate_record.psCurr.fields.glb << 24) |
- (G_pgpe_pstate_record.eVidCurr << 8) |
+ (G_pgpe_pstate_record.extVrmCurr << 8) |
PGPE_OP_TRACE_OCC_HB_FAULT;
p9_pgpe_optrace(SEVERE_FAULT_DETECTED);
@@ -203,7 +203,7 @@ void p9_pgpe_irq_handler_sgpe_err()
G_pgpe_optrace_data.word[0] = (G_pgpe_pstate_record.activeQuads << 24) |
(G_pgpe_pstate_record.activeCores << 8);
G_pgpe_optrace_data.word[1] = (G_pgpe_pstate_record.psCurr.fields.glb << 24) |
- (G_pgpe_pstate_record.eVidCurr << 8) |
+ (G_pgpe_pstate_record.extVrmCurr << 8) |
PGPE_OP_TRACE_SGPE_FAULT;
p9_pgpe_optrace(SEVERE_FAULT_DETECTED);
@@ -243,7 +243,7 @@ void p9_pgpe_irq_handler_pvref_err()
G_pgpe_optrace_data.word[0] = (G_pgpe_pstate_record.activeQuads << 24) |
(G_pgpe_pstate_record.activeCores << 8);
G_pgpe_optrace_data.word[1] = (G_pgpe_pstate_record.psCurr.fields.glb << 24) |
- (G_pgpe_pstate_record.eVidCurr << 8) |
+ (G_pgpe_pstate_record.extVrmCurr << 8) |
PGPE_OP_TRACE_PVREF_FAULT;
p9_pgpe_optrace(SEVERE_FAULT_DETECTED);
@@ -288,7 +288,7 @@ void p9_pgpe_irq_handler_system_xstop(void* arg, PkIrqId irq)
G_pgpe_optrace_data.word[0] = (G_pgpe_pstate_record.activeQuads << 24) |
(G_pgpe_pstate_record.activeCores << 8);
G_pgpe_optrace_data.word[1] = (G_pgpe_pstate_record.psCurr.fields.glb << 24) |
- (G_pgpe_pstate_record.eVidCurr << 8) |
+ (G_pgpe_pstate_record.extVrmCurr << 8) |
PGPE_OP_TRACE_SYS_XSTOP;
p9_pgpe_optrace(SEVERE_FAULT_DETECTED);
@@ -454,7 +454,7 @@ void p9_pgpe_irq_handler_cme_err()
G_pgpe_optrace_data.word[0] = (G_pgpe_pstate_record.activeQuads << 24) |
(G_pgpe_pstate_record.activeCores << 8);
G_pgpe_optrace_data.word[1] = (G_pgpe_pstate_record.psCurr.fields.glb << 24) |
- (G_pgpe_pstate_record.eVidCurr << 8) |
+ (G_pgpe_pstate_record.extVrmCurr << 8) |
PGPE_OP_TRACE_CME_FAULT;
p9_pgpe_optrace(SEVERE_FAULT_DETECTED);
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c
index 09d59832..f268a0d4 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HCODE Project */
/* */
-/* COPYRIGHT 2016,2018 */
+/* COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -65,6 +65,7 @@ GPE_BUFFER(ipcmsg_p2s_suspend_stop_t G_sgpe_suspend_stop);
//Local Functions
void p9_pgpe_handle_nacks(uint32_t origCoreVector, uint32_t origAckVector, uint32_t expectedAcks);
void p9_pgpe_pstate_freq_updt();
+void p9_pgpe_pstate_wov_init();
inline void p9_pgpe_droop_throttle() __attribute__((always_inline));
inline void p9_pgpe_droop_unthrottle() __attribute__((always_inline));
@@ -138,6 +139,9 @@ void p9_pgpe_pstate_init()
pk_semaphore_create(&(G_pgpe_pstate_record.sem_actuate), 0, 1);
pk_semaphore_create(&(G_pgpe_pstate_record.sem_sgpe_wait), 0, 1);
pk_semaphore_create(&(G_pgpe_pstate_record.sem_process_req), 0, 1);
+
+ //WOV init
+ p9_pgpe_pstate_wov_init();
}
//
@@ -367,7 +371,6 @@ void p9_pgpe_pstate_calc_wof()
{
G_pgpe_pstate_record.vratio = (G_pgpe_pstate_record.numActiveCores * MAX_VRATIO) / (G_pgpe_pstate_record.numSortCores);
-
// Note we separate out numActiveCores = 0 case. Otherwise, subtracting 1 will
// result in invalid vindex
if (G_pgpe_pstate_record.numActiveCores != 0)
@@ -411,7 +414,7 @@ void p9_pgpe_pstate_update_wof_state()
PK_TRACE_DBG("WFU: Updt WOF Shr Sram");
pgpe_wof_state_t* wof_state = (pgpe_wof_state_t*)G_pgpe_header_data->g_pgpe_wof_state_address;
wof_state->fields.fclip_ps = G_pgpe_pstate_record.wofClip;
- wof_state->fields.vclip_mv = G_pgpe_pstate_record.eVidCurr;
+ wof_state->fields.vclip_mv = G_pgpe_pstate_record.extVrmCurr;
wof_state->fields.fratio = G_pgpe_pstate_record.fratio;
wof_state->fields.vratio = G_pgpe_pstate_record.vratio;
PK_TRACE_INF("WFU: FClip_PS=0x%x, vindex=0x%x, vratio=0x%x", G_pgpe_pstate_record.wofClip, G_pgpe_pstate_record.vindex,
@@ -674,20 +677,8 @@ void p9_pgpe_handle_nacks(uint32_t origTargetCores, uint32_t origExpectedAckFrom
p.waitForAcks = PGPE_DB_ACK_WAIT_CME;
p.checkNACKs = PGPE_DB3_SKIP_CHECK_NACKS;
- //a. If OCC Scratch2 Core Throttle Continuous Change Enable bit is set (i.e. during Manufacturing test), halt the PGPE with a unique error code.
- //Engineering Note: characterization team is responsible to set CSAR bit "Disable CME NACK on Prolonged Droop" when doing PGPE throttle scom injection.
- if(in32(G_OCB_OCCS2) & BIT32(CORE_THROTTLE_CONTINUOUS_CHANGE_ENABLE))
- {
- PGPE_TRACE_AND_PANIC(PGPE_DROOP_AND_CORE_THROTTLE_ENABLED);
- }
-
- //b) If OCC flag PGPE Prolonged Droop Workaround Active bit is not set,
- // call droop_throttle()
-
- if (!(in32(G_OCB_OCCFLG) & BIT32(PGPE_PROLONGED_DROOP_WORKAROUND_ACTIVE)))
- {
- p9_pgpe_droop_throttle();
- }
+ G_pgpe_pstate_record.wov.target_pct = 0;
+ p9_pgpe_pstate_updt_ext_volt();
//c) Send DB3 (Replay Previous DB0 Operation) to only the CME Quad Managers, and
//their Sibling CME (if present), that responded with a NACK.
@@ -713,6 +704,14 @@ void p9_pgpe_handle_nacks(uint32_t origTargetCores, uint32_t origExpectedAckFrom
//If a NACK received was in response to the first retry (i.e. second failed attempt):
if (G_pgpe_pstate_record.cntNACKs == 2)
{
+
+ //b) If OCC flag PGPE Prolonged Droop Workaround Active bit is not set,
+ // call droop_throttle()
+ if (!(in32(G_OCB_OCCFLG) & BIT32(PGPE_PROLONGED_DROOP_WORKAROUND_ACTIVE)))
+ {
+ p9_pgpe_droop_throttle();
+ }
+
// 1 SCOM Write to OCC FIR[prolonged_droop_detected] bit. This FIR bit is set to recoverable so that it will create an informational error log.
GPE_PUTSCOM(OCB_OCCLFIR_OR, BIT64(OCCLFIR_PROLONGED_DROOP_DETECTED));
@@ -811,21 +810,26 @@ void p9_pgpe_pstate_start(uint32_t pstate_start_origin)
}
//3. Move system to SyncPState
- external_voltage_control_init(&G_pgpe_pstate_record.eVidCurr);
- G_pgpe_pstate_record.eVidNext = p9_pgpe_gppb_intp_vdd_from_ps(syncPstate, VPD_PT_SET_BIASED_SYSP);
- PK_TRACE_INF("PST: SyncPstate=0x%x eVid(Boot)=%umV,eVid(SyncPstate)=%umV", syncPstate, G_pgpe_pstate_record.eVidCurr,
- G_pgpe_pstate_record.eVidNext);
+ external_voltage_control_init(&G_pgpe_pstate_record.extVrmCurr);
+ G_pgpe_pstate_record.biasSyspExtVrmCurr = G_pgpe_pstate_record.extVrmCurr;
+ G_pgpe_pstate_record.biasSyspExtVrmNext = p9_pgpe_gppb_intp_vdd_from_ps(syncPstate, VPD_PT_SET_BIASED_SYSP);
+ PK_TRACE_INF("PST: SyncPstate=0x%x eVid(Boot)=%umV,eVid(SyncPstate)=%umV", syncPstate,
+ G_pgpe_pstate_record.biasSyspExtVrmCurr,
+ G_pgpe_pstate_record.biasSyspExtVrmNext);
dpllFreq.value = 0;
dpllFreq.fields.fmax = G_gppb->dpll_pstate0_value - syncPstate;
dpllFreq.fields.fmult = dpllFreq.fields.fmax;
dpllFreq.fields.fmin = dpllFreq.fields.fmax;
+ G_pgpe_pstate_record.psNext.fields.glb = syncPstate;
+ p9_pgpe_pstate_reset_wov();
+
//Move voltage only if raising it. Otherwise, we lower it later after
//sending Pstate Start DB0. This is to make sure VDMs are not affected in
//this window
- if(G_pgpe_pstate_record.eVidCurr < G_pgpe_pstate_record.eVidNext)
+ if(G_pgpe_pstate_record.biasSyspExtVrmCurr < G_pgpe_pstate_record.biasSyspExtVrmNext)
{
- p9_pgpe_pstate_updt_ext_volt(G_pgpe_pstate_record.eVidNext); //update voltage
+ p9_pgpe_pstate_updt_ext_volt(); //update voltage
}
for (q = 0; q < MAX_QUADS; q++)
@@ -857,6 +861,7 @@ void p9_pgpe_pstate_start(uint32_t pstate_start_origin)
p9_pgpe_pstate_do_auction();
p9_pgpe_pstate_apply_clips();
+ G_pgpe_pstate_record.psNext.value = G_pgpe_pstate_record.psTarget.value;
//5. Set up CME_SCRATCH0[Local_Pstate_Index]
for (q = 0; q < MAX_QUADS; q++)
@@ -949,9 +954,9 @@ void p9_pgpe_pstate_start(uint32_t pstate_start_origin)
out32(G_OCB_OCCFLG_CLR, BIT32(PGPE_PM_RESET_SUPPRESS));
//Lower voltage if boot voltage > syncPstate voltage
- if (G_pgpe_pstate_record.eVidCurr > G_pgpe_pstate_record.eVidNext)
+ if (G_pgpe_pstate_record.biasSyspExtVrmCurr > G_pgpe_pstate_record.biasSyspExtVrmNext)
{
- p9_pgpe_pstate_updt_ext_volt(G_pgpe_pstate_record.eVidNext); //update voltage
+ p9_pgpe_pstate_updt_ext_volt(); //update voltage
}
G_pgpe_pstate_record.psCurr.value = G_pgpe_pstate_record.psTarget.value;
@@ -966,6 +971,13 @@ void p9_pgpe_pstate_start(uint32_t pstate_start_origin)
PK_TRACE_DBG("PST: PGPE_PSTATE_PROTOCOL_ACTIVE set");
out32(G_OCB_OCCS2, occScr2);
+ //7. Enable Undervolt if needed
+ if (G_pgpe_header_data->g_pgpe_flags & PGPE_FLAG_WOV_UNDERVOLT_ENABLE)
+ {
+ G_pgpe_pstate_record.wov.status = WOV_UNDERVOLT_ENABLED;
+ PK_TRACE_INF("PST: Undervolting Enabled");
+ }
+
PK_TRACE_DBG("PST: Start Done");
}
@@ -1400,7 +1412,7 @@ void p9_pgpe_pstate_process_quad_exit_notify(uint32_t quadsRequested)
GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(QPPM_VDMCFGR, q), vdmcfg.value);
}
- vdmcfg.fields.vdm_vid_compare = (G_pgpe_pstate_record.eVidCurr - 512) >> 2;
+ vdmcfg.fields.vdm_vid_compare = (G_pgpe_pstate_record.biasSyspExtVrmCurr - 512) >> 2;
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(QPPM_VDMCFGR, q), vdmcfg.value);
}
}
@@ -1825,6 +1837,18 @@ int32_t p9_pgpe_pstate_at_target()
}
}
+int32_t p9_pgpe_pstate_at_wov_target()
+{
+ if (G_pgpe_pstate_record.wov.curr_pct ^ G_pgpe_pstate_record.wov.target_pct)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
//
// p9_pgpe_pstate_do_step
//
@@ -1836,34 +1860,35 @@ void p9_pgpe_pstate_do_step()
//Do one actuate step
PK_TRACE_DBG("STEP: Entry");
- PK_TRACE_DBG("STEP: GTgt,GCurr 0x%x, 0x%x", G_pgpe_pstate_record.psTarget.fields.glb,
+ PK_TRACE_INF("STEP: GTgt,GCurr 0x%x, 0x%x", G_pgpe_pstate_record.psTarget.fields.glb,
G_pgpe_pstate_record.psCurr.fields.glb);
- PK_TRACE_DBG("STEP: QTgt,QCurr 0x%x,0x%x 0x%x,0x%x", G_pgpe_pstate_record.psTarget.fields.quads[0],
+ PK_TRACE_INF("STEP: QTgt,QCurr 0x%x,0x%x 0x%x,0x%x", G_pgpe_pstate_record.psTarget.fields.quads[0],
G_pgpe_pstate_record.psCurr.fields.quads[0], G_pgpe_pstate_record.psTarget.fields.quads[1],
G_pgpe_pstate_record.psCurr.fields.quads[1]);
- PK_TRACE_DBG("STEP:QTgt,QCurr 0x%x,0x%x 0x%x,0x%x", G_pgpe_pstate_record.psTarget.fields.quads[2],
+ PK_TRACE_INF("STEP:QTgt,QCurr 0x%x,0x%x 0x%x,0x%x", G_pgpe_pstate_record.psTarget.fields.quads[2],
G_pgpe_pstate_record.psCurr.fields.quads[2], G_pgpe_pstate_record.psTarget.fields.quads[3],
G_pgpe_pstate_record.psCurr.fields.quads[3]);
- PK_TRACE_DBG("STEP:QTgt,QCurr 0x%x,0x%x 0x%x,0x%x", G_pgpe_pstate_record.psTarget.fields.quads[4],
+ PK_TRACE_INF("STEP:QTgt,QCurr 0x%x,0x%x 0x%x,0x%x", G_pgpe_pstate_record.psTarget.fields.quads[4],
G_pgpe_pstate_record.psCurr.fields.quads[4], G_pgpe_pstate_record.psTarget.fields.quads[5],
G_pgpe_pstate_record.psCurr.fields.quads[5]);
uint32_t q;
uint32_t targetEVid = p9_pgpe_gppb_intp_vdd_from_ps(G_pgpe_pstate_record.psTarget.fields.glb, VPD_PT_SET_BIASED_SYSP);
- PK_TRACE_DBG("STEP: eVidCurr=0x%x, eVidNext=0x%x, targetEVid=0x%x", G_pgpe_pstate_record.eVidCurr,
- G_pgpe_pstate_record.eVidNext, targetEVid);
+ PK_TRACE_INF("STEP: biasSyspExtVrmCurr=0x%x, biasSyspExtVrmNext=0x%x, targetEVid=0x%x",
+ G_pgpe_pstate_record.biasSyspExtVrmCurr,
+ G_pgpe_pstate_record.biasSyspExtVrmNext, targetEVid);
//Higher number PState
if (((int16_t)(G_pgpe_pstate_record.psTarget.fields.glb) - (int16_t)(G_pgpe_pstate_record.psCurr.fields.glb)) > 0)
{
- if ((G_pgpe_pstate_record.eVidCurr - targetEVid ) <= G_gppb->ext_vrm_step_size_mv)
+ if ((G_pgpe_pstate_record.biasSyspExtVrmCurr - targetEVid ) <= G_gppb->ext_vrm_step_size_mv)
{
- G_pgpe_pstate_record.eVidNext = targetEVid;
+ G_pgpe_pstate_record.biasSyspExtVrmNext = targetEVid;
G_pgpe_pstate_record.psNext.fields.glb = G_pgpe_pstate_record.psTarget.fields.glb;
- PK_TRACE_DBG("STEP: <= step_size");
+ PK_TRACE_INF("STEP: <= step_size");
for (q = 0; q < MAX_QUADS; q++)
{
@@ -1875,8 +1900,8 @@ void p9_pgpe_pstate_do_step()
}
else
{
- G_pgpe_pstate_record.eVidNext = G_pgpe_pstate_record.eVidCurr - G_gppb->ext_vrm_step_size_mv;
- G_pgpe_pstate_record.psNext.fields.glb = p9_pgpe_gppb_intp_ps_from_ext_vdd(G_pgpe_pstate_record.eVidNext);
+ G_pgpe_pstate_record.biasSyspExtVrmNext = G_pgpe_pstate_record.biasSyspExtVrmCurr - G_gppb->ext_vrm_step_size_mv;
+ G_pgpe_pstate_record.psNext.fields.glb = p9_pgpe_gppb_intp_ps_from_ext_vdd(G_pgpe_pstate_record.biasSyspExtVrmNext);
//It's possible that the interpolation function returns Pstate higher than
//target due to rounding errors, so we adjust back.
@@ -1886,8 +1911,8 @@ void p9_pgpe_pstate_do_step()
}
//Make sure voltage written corresponds exactly to a pstate
- G_pgpe_pstate_record.eVidNext = p9_pgpe_gppb_intp_vdd_from_ps(G_pgpe_pstate_record.psNext.fields.glb,
- VPD_PT_SET_BIASED_SYSP);
+ G_pgpe_pstate_record.biasSyspExtVrmNext = p9_pgpe_gppb_intp_vdd_from_ps(G_pgpe_pstate_record.psNext.fields.glb,
+ VPD_PT_SET_BIASED_SYSP);
for (q = 0; q < MAX_QUADS; q++)
{
@@ -1899,19 +1924,19 @@ void p9_pgpe_pstate_do_step()
}
- PK_TRACE_DBG("STEP: eVidNext=0x%x, glbPSNext=0x%x", G_pgpe_pstate_record.eVidCurr,
+ PK_TRACE_INF("STEP: biasSyspExtVrmNext=0x%x, glbPSNext=0x%x", G_pgpe_pstate_record.biasSyspExtVrmCurr,
G_pgpe_pstate_record.psNext.fields.glb);
- p9_pgpe_pstate_freq_updt();
- p9_pgpe_pstate_updt_ext_volt(targetEVid);
+ p9_pgpe_pstate_freq_updt(PGPE_FREQ_DIRECTION_DOWN);
+ p9_pgpe_pstate_updt_ext_volt();
}
//Lower number PState
else if (((int16_t)(G_pgpe_pstate_record.psTarget.fields.glb) - (int16_t)(G_pgpe_pstate_record.psCurr.fields.glb)) < 0)
{
- if ((targetEVid - G_pgpe_pstate_record.eVidCurr) <= G_gppb->ext_vrm_step_size_mv)
+ if ((targetEVid - G_pgpe_pstate_record.biasSyspExtVrmCurr) <= G_gppb->ext_vrm_step_size_mv)
{
- PK_TRACE_DBG("STEP: <= step_size");
- G_pgpe_pstate_record.eVidNext = targetEVid;
+ PK_TRACE_INF("STEP: <= step_size");
+ G_pgpe_pstate_record.biasSyspExtVrmNext = targetEVid;
G_pgpe_pstate_record.psNext.fields.glb = G_pgpe_pstate_record.psTarget.fields.glb;
for (q = 0; q < MAX_QUADS; q++)
@@ -1924,9 +1949,9 @@ void p9_pgpe_pstate_do_step()
}
else
{
- PK_TRACE_DBG("STEP: > step_size");
- G_pgpe_pstate_record.eVidNext = G_pgpe_pstate_record.eVidCurr + G_gppb->ext_vrm_step_size_mv;
- G_pgpe_pstate_record.psNext.fields.glb = p9_pgpe_gppb_intp_ps_from_ext_vdd(G_pgpe_pstate_record.eVidNext);
+ PK_TRACE_INF("STEP: > step_size");
+ G_pgpe_pstate_record.biasSyspExtVrmNext = G_pgpe_pstate_record.biasSyspExtVrmCurr + G_gppb->ext_vrm_step_size_mv;
+ G_pgpe_pstate_record.psNext.fields.glb = p9_pgpe_gppb_intp_ps_from_ext_vdd(G_pgpe_pstate_record.biasSyspExtVrmNext);
//It's possible that the interpolation function returns Pstate lower than
//target due to rounding errors, so we adjust back.
@@ -1936,8 +1961,8 @@ void p9_pgpe_pstate_do_step()
}
//Make sure voltage written corresponds exactly to a pstate
- G_pgpe_pstate_record.eVidNext = p9_pgpe_gppb_intp_vdd_from_ps(G_pgpe_pstate_record.psNext.fields.glb,
- VPD_PT_SET_BIASED_SYSP);
+ G_pgpe_pstate_record.biasSyspExtVrmNext = p9_pgpe_gppb_intp_vdd_from_ps(G_pgpe_pstate_record.psNext.fields.glb,
+ VPD_PT_SET_BIASED_SYSP);
for (q = 0; q < MAX_QUADS; q++)
{
@@ -1956,22 +1981,33 @@ void p9_pgpe_pstate_do_step()
}
}
- PK_TRACE_DBG("STEP: eVidNext=0x%x, glbPSNext=0x%x", G_pgpe_pstate_record.eVidCurr,
+ PK_TRACE_INF("STEP: biasSyspExtVrmNext=0x%x, glbPSNext=0x%x", G_pgpe_pstate_record.biasSyspExtVrmCurr,
G_pgpe_pstate_record.psNext.fields.glb);
- p9_pgpe_pstate_updt_ext_volt(targetEVid);
- p9_pgpe_pstate_freq_updt();
+ p9_pgpe_pstate_updt_ext_volt();
+ p9_pgpe_pstate_freq_updt(PGPE_FREQ_DIRECTION_UP);
}
else
{
- for (q = 0; q < MAX_QUADS; q++)
+ //Local Pstate change
+ if (p9_pgpe_pstate_at_target() == 0)
{
- if(G_pgpe_pstate_record.activeQuads & QUAD_MASK(q))
+ for (q = 0; q < MAX_QUADS; q++)
{
- G_pgpe_pstate_record.psNext.fields.quads[q] = G_pgpe_pstate_record.psTarget.fields.quads[q];
+ if(G_pgpe_pstate_record.activeQuads & QUAD_MASK(q))
+ {
+ G_pgpe_pstate_record.psNext.fields.quads[q] = G_pgpe_pstate_record.psTarget.fields.quads[q];
+ }
}
+
+ //Only local pstate change
+ p9_pgpe_pstate_freq_updt(PGPE_FREQ_DIRECTION_NO_CHANGE);
}
- p9_pgpe_pstate_freq_updt();
+ if (p9_pgpe_pstate_at_wov_target() == 0)
+ {
+ PK_TRACE_INF("WOV updt ext_volt");
+ p9_pgpe_pstate_updt_ext_volt();
+ }
}
//Update current
@@ -1987,7 +2023,7 @@ void p9_pgpe_pstate_do_step()
(G_pgpe_pstate_record.psCurr.fields.quads[5]
<< 16) |
G_pgpe_pstate_record.psCurr.fields.glb << 8 | G_pgpe_pstate_record.psTarget.fields.glb;
- G_pgpe_optrace_data.word[2] = (G_pgpe_pstate_record.eVidCurr << 16) | G_pgpe_pstate_record.eVidCurr;
+ G_pgpe_optrace_data.word[2] = (G_pgpe_pstate_record.biasSyspExtVrmCurr << 16) | G_pgpe_pstate_record.biasSyspExtVrmCurr;
p9_pgpe_optrace(ACTUATE_STEP_DONE);
PK_TRACE_DBG("STEP: Exit");
}
@@ -1997,32 +2033,41 @@ void p9_pgpe_pstate_do_step()
//
// Update External VRM to G_eVidNext
//
-void p9_pgpe_pstate_updt_ext_volt(uint32_t tgtEVid)
+void p9_pgpe_pstate_updt_ext_volt()
{
qppm_vdmcfgr_t vdmcfg;
uint32_t cmeInterppmVdataEnableSet, q;
qppm_qpmmr_t qpmmr;
+ G_pgpe_pstate_record.wov.target_mv =
+ (G_pgpe_pstate_record.biasSyspExtVrmNext * G_pgpe_pstate_record.wov.target_pct) / 1000;
+ G_pgpe_pstate_record.extVrmNext = G_pgpe_pstate_record.biasSyspExtVrmNext - G_pgpe_pstate_record.wov.target_mv;
+
+ if (G_gppb->wov_underv_vmin_mv > G_pgpe_pstate_record.extVrmNext)
+ {
+ G_pgpe_pstate_record.extVrmNext = G_gppb->wov_underv_vmin_mv;
+ }
+
#if !EPM_P9_TUNING
uint32_t delay_us = 0;
//Decreasing
- if (G_pgpe_pstate_record.eVidNext < G_pgpe_pstate_record.eVidCurr)
+ if (G_pgpe_pstate_record.extVrmNext < G_pgpe_pstate_record.extVrmCurr)
{
- delay_us = (G_pgpe_pstate_record.eVidCurr - G_pgpe_pstate_record.eVidNext) *
+ delay_us = (G_pgpe_pstate_record.extVrmCurr - G_pgpe_pstate_record.extVrmNext) *
G_ext_vrm_dec_rate_mult_usperus;
}
//Increasing
- else if(G_pgpe_pstate_record.eVidNext > G_pgpe_pstate_record.eVidCurr)
+ else if (G_pgpe_pstate_record.extVrmNext > G_pgpe_pstate_record.extVrmCurr)
{
- delay_us = (G_pgpe_pstate_record.eVidNext - G_pgpe_pstate_record.eVidCurr) *
+ delay_us = (G_pgpe_pstate_record.extVrmNext - G_pgpe_pstate_record.extVrmCurr) *
G_ext_vrm_inc_rate_mult_usperus;
}
#endif
//Update external voltage
- external_voltage_control_write(G_pgpe_pstate_record.eVidNext);
+ external_voltage_control_write(G_pgpe_pstate_record.extVrmNext);
#if !EPM_P9_TUNING
@@ -2032,20 +2077,34 @@ void p9_pgpe_pstate_updt_ext_volt(uint32_t tgtEVid)
pk_sleep(PK_MICROSECONDS((delay_us)));
}
- if(G_pgpe_pstate_record.eVidNext == tgtEVid)
+ if(G_pgpe_pstate_record.biasSyspExtVrmNext == p9_pgpe_gppb_intp_vdd_from_ps(G_pgpe_pstate_record.psNext.fields.glb,
+ VPD_PT_SET_BIASED_SYSP))
{
pk_sleep(PK_MICROSECONDS((G_gppb->ext_vrm_stabilization_time_us)));
}
#endif
- G_pgpe_pstate_record.eVidCurr = G_pgpe_pstate_record.eVidNext;
+ G_pgpe_pstate_record.biasSyspExtVrmCurr = G_pgpe_pstate_record.biasSyspExtVrmNext;
+ G_pgpe_pstate_record.extVrmCurr = G_pgpe_pstate_record.extVrmNext;
+ G_pgpe_pstate_record.wov.curr_mv = G_pgpe_pstate_record.wov.target_mv;
+ G_pgpe_pstate_record.wov.curr_pct = G_pgpe_pstate_record.wov.target_pct;
+
+ if (G_pgpe_pstate_record.wov.min_volt > G_pgpe_pstate_record.wov.curr_mv)
+ {
+ G_pgpe_pstate_record.wov.min_volt = G_pgpe_pstate_record.wov.curr_mv;
+ }
+
+ if (G_pgpe_pstate_record.wov.max_volt < G_pgpe_pstate_record.wov.curr_mv)
+ {
+ G_pgpe_pstate_record.wov.max_volt = G_pgpe_pstate_record.wov.curr_mv;
+ }
//If VDM is disabled, update VDMCFG register for every quad
if (!(G_pgpe_header_data->g_pgpe_flags & PGPE_FLAG_VDM_ENABLE))
{
vdmcfg.value = 0;
- vdmcfg.fields.vdm_vid_compare = (G_pgpe_pstate_record.eVidCurr - 512) >> 2;
+ vdmcfg.fields.vdm_vid_compare = (G_pgpe_pstate_record.biasSyspExtVrmCurr - 512) >> 2;
for (q = 0; q < MAX_QUADS; q++)
{
@@ -2074,11 +2133,13 @@ void p9_pgpe_pstate_updt_ext_volt(uint32_t tgtEVid)
//
// Frequency Update
//
-// Sends a DB0 to all active CMEs, so that Quad Managers(CMEs) update DPLL
-void p9_pgpe_pstate_freq_updt()
+//Sends a DB0 to all active CMEs, so that Quad Managers(CMEs) update DPLL
+void p9_pgpe_pstate_freq_updt(uint32_t freq_change_dir)
{
PK_TRACE_DBG("FREQ: Enter");
+ G_pgpe_pstate_record.wov.frequency_change_direction = freq_change_dir;
+ p9_pgpe_pstate_adjust_wov();
pgpe_db0_glb_bcast_t db0;
db0.value = G_pgpe_pstate_record.psNext.value;
@@ -2134,6 +2195,8 @@ void p9_pgpe_pstate_freq_updt()
p9_pgpe_optrace(ACK_ACTL_DONE);
+ G_pgpe_pstate_record.wov.frequency_change_direction = PGPE_FREQ_DIRECTION_NO_CHANGE;
+
PK_TRACE_DBG("FREQ: Exit");
}
@@ -2149,6 +2212,7 @@ void p9_pgpe_pstate_write_core_throttle(uint32_t throttleData, uint32_t enable_r
uint32_t value = mfmsr();
mtmsr(value | MSR_THROTTLE_MASK); //don't cause halt if all cores offline or address error (PC Timeout)
+
do
{
out64(THROTTLE_SCOM_MULTICAST_WRITE, ((uint64_t) throttleData << 32)); //apply new throttle SCOM setting
@@ -2175,7 +2239,7 @@ void p9_pgpe_pstate_write_core_throttle(uint32_t throttleData, uint32_t enable_r
//
inline void p9_pgpe_droop_throttle()
{
-
+ PkMachineContext ctx __attribute__((unused));
uint32_t q;
ocb_qcsr_t qcsr;
qcsr.value = in32(G_OCB_QCSR);
@@ -2230,12 +2294,14 @@ inline void p9_pgpe_droop_throttle()
}
}
- //2. Call the core_instruction_throttle() procedure to enable throttle (same as used by FIT).
- p9_pgpe_pstate_write_core_throttle(CORE_IFU_THROTTLE, RETRY);
//3. Set the OCC flag PGPE Prolonged Droop Workaround Active bit.
out32(G_OCB_OCCFLG_OR, BIT32(PGPE_PROLONGED_DROOP_WORKAROUND_ACTIVE));
+ //2. Call the core_instruction_throttle() procedure to enable throttle (same as used by FIT).
+ p9_pgpe_pstate_write_core_throttle(CORE_IFU_THROTTLE, RETRY);
+
+
//4. Clear the Prolonged Droop Global variables (Bit vector and retry counts).
G_pgpe_pstate_record.cntNACKs = 0;
@@ -2296,3 +2362,196 @@ inline void p9_pgpe_droop_unthrottle()
PK_TRACE_INF("DTH: Droop Unthrottle Done");
}
+
+
+//
+// p9_pgpe_pstate_wov_init
+//
+void p9_pgpe_pstate_wov_init()
+{
+ //G_pgpe_pstate_record.wov.freq_loss_threshold_tenths = UNDERVOLT_LOSS_THRESHOLD_TENTHS;
+ G_pgpe_pstate_record.wov.avg_freq_gt_target_freq = 0;
+ G_pgpe_pstate_record.wov.freq_loss_tenths_gt_max_droop_tenths = 0;
+ G_pgpe_pstate_record.wov.status = WOV_DISABLED;
+ G_pgpe_pstate_record.wov.info = 0xdeadbeef;
+}
+
+//
+//p9_pgpe_pstate_adjust_wov
+//
+void p9_pgpe_pstate_adjust_wov()
+{
+ uint32_t max_freq_loss_percent_tenths = 0;
+ uint32_t sample_valid = 0;
+ uint32_t q = 0;
+ uint32_t freq_loss = 0;
+ uint64_t qfmr;
+ uint32_t delta_tb, delta_cycles, new_tb, new_cycles;
+
+ PK_TRACE_INF("WOV: Adjust");
+
+ ocb_qcsr_t qcsr;
+ qcsr.value = in32(G_OCB_QCSR);
+
+ //Determine performance loss
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ //If quad not in STOP11. Active quads only has quads that are NOT in STOP11, and
+ //have been registered with PGPE. Therefore we OR in the requested_active_quads which
+ //include quads that are up, but not yet registered with PGPE
+ if (G_pgpe_pstate_record.activeQuads & QUAD_MASK(q))
+ {
+ //Sample Frequency
+ //Read from EX0(if configured). Otherwise, read from EX1
+ if (qcsr.fields.ex_config & QUAD_EX0_MASK(q))
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_QFMR, q, 0), qfmr);
+ }
+ else
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_QFMR, q, 1), qfmr);
+ }
+
+ new_tb = qfmr >> 32;
+ new_cycles = qfmr & (0xFFFFFFFF);
+
+ PK_TRACE_INF("WOV: QFMR[%d]=0x%08x %08x ", q, qfmr >> 32, qfmr);
+
+ //If freq_change_in_progress
+ if (G_pgpe_pstate_record.wov.frequency_change_direction != PGPE_FREQ_DIRECTION_NO_CHANGE)
+ {
+ G_pgpe_pstate_record.wov.freq_changed[q] = G_pgpe_pstate_record.wov.frequency_change_direction;
+ }
+ else
+ {
+ sample_valid = 1;
+ G_pgpe_pstate_record.wov.target_freq[q] = p9_pgpe_gppb_freq_from_ps(G_pgpe_pstate_record.psCurr.fields.quads[q]);
+
+ //Calculate delta timebase while accounting for rollover
+ delta_tb = new_tb - G_pgpe_pstate_record.wov.last_qfmr_tb[q];
+
+ if (delta_tb & 0x80000000)
+ {
+ delta_tb += 0xFFFFFFFF;
+ }
+
+ //Calculate delta cyles while accounting for rollover
+ delta_cycles = new_cycles - G_pgpe_pstate_record.wov.last_qfmr_cycles[q];
+
+ if (delta_cycles & 0x80000000)
+ {
+ delta_cycles += 0xFFFFFFFF;
+ }
+
+ G_pgpe_pstate_record.wov.avg_freq[q] = (delta_cycles * (G_gppb->nest_frequency_mhz >> 3)) /
+ delta_tb;
+
+
+ if (G_pgpe_pstate_record.wov.avg_freq[q] >
+ G_pgpe_pstate_record.wov.target_freq[q]) // ensure that the calculation doesn't result in negative loss
+ {
+ //\todo Understand why is happening on pstate change and Add this back
+ PK_TRACE_INF("WOV: WARNING Avg Freq sampled greater than target freq for quad[%d], avg=0x%x,tgt=0x%x", q,
+ G_pgpe_pstate_record.wov.avg_freq[q],
+ G_pgpe_pstate_record.wov.target_freq[q]);
+ G_pgpe_pstate_record.wov.avg_freq_gt_target_freq = 1;
+ // PGPE_TRACE_AND_PANIC(PGPE_UVOLT_AVG_FREQ_GREATER_THAN_TARGET);//should not happen since we interlock with Pstate change
+ }
+ else
+ {
+ freq_loss = G_pgpe_pstate_record.wov.target_freq[q] - G_pgpe_pstate_record.wov.avg_freq[q];
+ }
+
+ G_pgpe_pstate_record.wov.freq_loss_percent_tenths[q] = (freq_loss * 1000) / G_pgpe_pstate_record.wov.target_freq[q];
+
+ PK_TRACE_INF("AUV: Quad[%d] TgtFreq=0x%x Avg_Freq=0x%x FreqLossPercentTenths=0x%x", q,
+ G_pgpe_pstate_record.wov.target_freq[q], G_pgpe_pstate_record.wov.avg_freq[q],
+ G_pgpe_pstate_record.wov.freq_loss_percent_tenths[q]);
+
+ if (G_pgpe_pstate_record.wov.freq_loss_percent_tenths[q] > G_gppb->wov_max_droop_pct)
+ {
+ //\todo Understand why is happening on pstate change and Add this back
+ PK_TRACE_INF("AUV: WARNING Freq Lost Percent Tenths greater than Max Droop Percent Tenths for quad [%d], freq_loss=0x%x",
+ q, G_pgpe_pstate_record.wov.freq_loss_percent_tenths[q]);
+ G_pgpe_pstate_record.wov.freq_loss_tenths_gt_max_droop_tenths =
+ G_pgpe_pstate_record.wov.freq_loss_percent_tenths[q];
+ // PGPE_TRACE_AND_PANIC(PGPE_UVOLT_FREQ_LOSS_GREATER_THAN_MAX_DROOP); // only DPLL droop can reduce frequency if not pstate change
+ }
+
+ // remember the most freq loss seen across all quads that didnt change pstate
+ if (G_pgpe_pstate_record.wov.freq_loss_percent_tenths[q] > max_freq_loss_percent_tenths)
+ {
+ max_freq_loss_percent_tenths = G_pgpe_pstate_record.wov.freq_loss_percent_tenths[q];
+ }
+ }
+
+ G_pgpe_pstate_record.wov.last_qfmr_tb[q] = new_tb;
+ G_pgpe_pstate_record.wov.last_qfmr_cycles[q] = new_cycles;
+ }
+ }
+
+ if (sample_valid) // don't update wov parameters unless at least one quad has a valid sample
+ {
+ // WOV ALGORITHM BEGIN
+ if (max_freq_loss_percent_tenths < G_gppb->wov_underv_perf_loss_thresh_pct)
+ {
+ if (G_pgpe_pstate_record.wov.curr_pct < G_gppb->wov_underv_max_pct)
+ {
+ G_pgpe_pstate_record.wov.target_pct += G_gppb->wov_underv_step_incr_pct;
+ }
+ else
+ {
+ G_pgpe_pstate_record.wov.target_pct = G_gppb->wov_underv_max_pct;
+ }
+ }
+ else
+ {
+ if (G_pgpe_pstate_record.wov.target_pct > 0)
+ {
+ G_pgpe_pstate_record.wov.target_pct -= G_gppb->wov_underv_step_incr_pct;
+ }
+ }
+ }// WOV ALGORITHM END
+
+ PK_TRACE_INF("WOV: wov_curr_pct=%d, wov_tgt_pct=%d",
+ G_pgpe_pstate_record.wov.curr_pct,
+ G_pgpe_pstate_record.wov.target_pct);
+
+}
+
+//
+// p9_pgpe_pstate_reset_wov()
+//
+void p9_pgpe_pstate_reset_wov()
+{
+ uint64_t qfmr;
+ ocb_qcsr_t qcsr;
+ uint32_t q;
+
+ //Reset wov steps to 0
+ G_pgpe_pstate_record.wov.curr_pct = 0;
+ G_pgpe_pstate_record.wov.target_pct = 0;
+
+ //Update QFMR snapshot
+ qcsr.value = in32(G_OCB_QCSR);
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if (G_pgpe_pstate_record.activeQuads & QUAD_MASK(q))
+ {
+ //Read from EX0(if configured). Otherwise, read from EX1
+ if (qcsr.fields.ex_config & QUAD_EX0_MASK(q))
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_QFMR, q, 0), qfmr);
+ }
+ else
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_QFMR, q, 1), qfmr);
+ }
+
+ G_pgpe_pstate_record.wov.last_qfmr_tb[q] = ((qfmr >> 32) & 0xFFFFFFFF);
+ G_pgpe_pstate_record.wov.last_qfmr_cycles[q] = qfmr & 0xFFFFFFFF;
+ }
+ }
+
+}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h
index 4c0860a9..9ccb5d03 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HCODE Project */
/* */
-/* COPYRIGHT 2016,2018 */
+/* COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -33,7 +33,6 @@
#include "p9_pgpe_header.h"
#include "p9_stop_recovery_trigger.h"
-
enum IPC_PEND_TBL
{
IPC_PEND_PSTATE_START_STOP = 0,
@@ -77,6 +76,13 @@ enum WOF_STATUS
WOF_ENABLED = 2 //Pstates are active
};
+enum WOV_STATUS
+{
+ WOV_DISABLED = 0x0, //WOV Disabled
+ WOV_UNDERVOLT_ENABLED = 0x1, //WOV Undervolt Enabled
+ WOV_OVERVOLT_ENABLED = 0x2, //WOV Overvolt Enabled
+};
+
enum SAFE_MODE_FAULT_INDEX
{
SAFE_MODE_FAULT_OCC = 0,
@@ -108,7 +114,7 @@ enum PGPE_CORE_THROTTLE
// Include core offline, address error, and timeout. The timeout is
// included to avoid an extra mtmsr in the event we need to cleanup
// from SW407201
- MSR_THROTTLE_MASK = 0x39000000,
+ MSR_THROTTLE_MASK = 0x29000000,
WORKAROUND_SCOM_MULTICAST_WRITE = 0x69010800,
THROTTLE_SCOM_MULTICAST_WRITE = 0x69010A9E,
CORE_IFU_THROTTLE = 0x80000000,
@@ -130,6 +136,13 @@ enum ACTIVE_CORE_UPDATE_ACTION
ACTIVE_CORE_UPDATE_ACTION_ACK_ONLY = 0x2
};
+enum PGPE_FREQ_DIRECTION
+{
+ PGPE_FREQ_DIRECTION_NO_CHANGE = 0,
+ PGPE_FREQ_DIRECTION_DOWN = -1,
+ PGPE_FREQ_DIRECTION_UP = 1
+};
+
//Task list entry
typedef struct ipc_req
{
@@ -152,6 +165,27 @@ typedef union sys_ps
} sys_ps_t;
//
+// Struct for WOV(Workload Optimized Voltage) data
+//
+typedef struct wov
+{
+ uint32_t curr_pct, target_pct;
+ uint32_t curr_mv, target_mv;
+ uint32_t status;
+ uint32_t info;
+ uint32_t min_volt, max_volt;
+ uint32_t avg_freq_gt_target_freq;
+ uint32_t freq_loss_tenths_gt_max_droop_tenths;
+ uint32_t avg_freq[MAX_QUADS];
+ uint32_t target_freq[MAX_QUADS];
+ uint32_t freq_loss_percent_tenths[MAX_QUADS];
+ uint32_t frequency_change_direction; //Indicates frequency change direction
+ uint32_t freq_changed[MAX_QUADS];
+ uint32_t last_qfmr_tb[MAX_QUADS]; //CME_QFMR timebase field
+ uint32_t last_qfmr_cycles[MAX_QUADS]; //CME_QFMR cycles field
+} wov_t;
+
+//
// PGPE PState
//
// Structure for storing internal PGPE state
@@ -170,7 +204,7 @@ typedef struct
sys_ps_t psTarget; //56
sys_ps_t psCurr; //64
sys_ps_t psNext; //72
- uint32_t eVidCurr, eVidNext; //84
+ uint32_t extVrmCurr, extVrmNext;//84
ipc_req_t ipcPendTbl[MAX_IPC_PEND_TBL_ENTRIES]; //156(9entries*8bytes)
HomerVFRTLayout_t* pVFRT; //160
quad_state0_t* pQuadState0; //164
@@ -191,6 +225,8 @@ typedef struct
uint8_t severeFault[4];
uint32_t pendingActiveQuadUpdtDone;
uint32_t activeCoreUpdtAction;
+ uint32_t biasSyspExtVrmCurr, biasSyspExtVrmNext;
+ wov_t wov;
} PgpePstateRecord __attribute__ ((aligned (8)));
@@ -264,7 +300,13 @@ void p9_pgpe_pstate_handle_pending_sgpe_ack_on_fault();
//Actuation
int32_t p9_pgpe_pstate_at_target();
+int32_t p9_pgpe_pstate_at_wov_target();
void p9_pgpe_pstate_do_step();
-void p9_pgpe_pstate_updt_ext_volt(uint32_t tgtEVid);
+void p9_pgpe_pstate_updt_ext_volt();
void p9_pgpe_pstate_write_core_throttle(uint32_t throttleData, uint32_t enable_retry);
+
+//Wov
+void p9_pgpe_pstate_adjust_wov();
+void p9_pgpe_pstate_reset_wov();
+
#endif //
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c
index 24f352b6..d01a7d86 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HCODE Project */
/* */
-/* COPYRIGHT 2016,2018 */
+/* COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -130,7 +130,8 @@ void p9_pgpe_thread_actuate_pstates(void* arg)
}
//Actuate step(if needed)
- if(p9_pgpe_pstate_at_target() == 0)
+ if ((p9_pgpe_pstate_at_target() == 0) ||
+ (p9_pgpe_pstate_at_wov_target() == 0))
{
pk_irq_sub_critical_enter(&ctx);
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c
index 41d974cd..c9f8d0f5 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HCODE Project */
/* */
-/* COPYRIGHT 2016,2018 */
+/* COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -1210,18 +1210,32 @@ inline void p9_pgpe_process_registration()
VPD_PT_SET_BIASED_SYSP);
//Move voltage by voltage step-size
- while(G_pgpe_pstate_record.eVidCurr != targetEVid)
+ while(G_pgpe_pstate_record.biasSyspExtVrmCurr != targetEVid)
{
- if ((targetEVid - G_pgpe_pstate_record.eVidCurr) <= G_gppb->ext_vrm_step_size_mv)
+ if ((targetEVid - G_pgpe_pstate_record.biasSyspExtVrmCurr) <= G_gppb->ext_vrm_step_size_mv)
{
- G_pgpe_pstate_record.eVidNext = targetEVid;
+ G_pgpe_pstate_record.biasSyspExtVrmNext = targetEVid;
+ G_pgpe_pstate_record.psNext.fields.glb = G_pgpe_pstate_record.psTarget.fields.glb;
}
else
{
- G_pgpe_pstate_record.eVidNext = G_pgpe_pstate_record.eVidCurr + G_gppb->ext_vrm_step_size_mv;
+ G_pgpe_pstate_record.biasSyspExtVrmNext = G_pgpe_pstate_record.biasSyspExtVrmCurr + G_gppb->ext_vrm_step_size_mv;
+ G_pgpe_pstate_record.psNext.fields.glb = p9_pgpe_gppb_intp_ps_from_ext_vdd(G_pgpe_pstate_record.biasSyspExtVrmNext);
+
+ //It's possible that the interpolation function returns Pstate higher than
+ //target due to rounding errors, so we adjust back.
+ if (G_pgpe_pstate_record.psNext.fields.glb > G_pgpe_pstate_record.psTarget.fields.glb)
+ {
+ G_pgpe_pstate_record.psNext.fields.glb = G_pgpe_pstate_record.psTarget.fields.glb;
+ }
+
+ //Make sure voltage written corresponds exactly to a pstate
+ G_pgpe_pstate_record.biasSyspExtVrmNext = p9_pgpe_gppb_intp_vdd_from_ps(G_pgpe_pstate_record.psNext.fields.glb,
+ VPD_PT_SET_BIASED_SYSP);
+
}
- p9_pgpe_pstate_updt_ext_volt(targetEVid);
+ p9_pgpe_pstate_updt_ext_volt();
}
//Set GlobalPSCurr and Next
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pgpe_panic_codes.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pgpe_panic_codes.h
index 6955845a..7703cd35 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pgpe_panic_codes.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pgpe_panic_codes.h
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HCODE Project */
/* */
-/* COPYRIGHT 2016,2018 */
+/* COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -86,10 +86,8 @@ PGPE_SET_PMCR_TRAP_INJECT = 0x1e05,
PGPE_DROOP_AND_CORE_THROTTLE_ENABLED = 0x1e06,
PGPE_INVALID_FREQ_UPDT = 0x1e07,
PGPE_PMAX_RCV_GREATER_THAN_PSAFE = 0x1e08,
-//_UNUSED_1e07 = 0x1e07,
-//_UNUSED_1e08 = 0x1e08,
-//_UNUSED_1e09 = 0x1e09,
-//_UNUSED_1e0a = 0x1e0a,
+PGPE_UVOLT_FREQ_LOSS_GREATER_THAN_MAX_DROOP = 0x1e09,
+PGPE_UVOLT_AVG_FREQ_GREATER_THAN_TARGET = 0x1e0a,
//_UNUSED_1e0d = 0x1e0d,
//_UNUSED_1e1c = 0x1e1c,
//_UNUSED_1e1d = 0x1e1d,
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_common.mk b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_common.mk
index 6e8376bf..04c17452 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_common.mk
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_common.mk
@@ -5,7 +5,7 @@
#
# OpenPOWER HCODE Project
#
-# COPYRIGHT 2017,2018
+# COPYRIGHT 2017,2019
# [+] International Business Machines Corp.
#
#
@@ -91,7 +91,7 @@ PSTATE_COMMONFLAGS+= -DPK_TRACE_SUPPORT=1
PSTATE_COMMONFLAGS+= -DUSE_PK_APP_CFG_H=1
PSTATE_COMMONFLAGS+= -D__PPE_PLAT
PSTATE_COMMONFLAGS+= -D__PK__=1
-PSTATE_COMMONFLAGS+= -DPK_TRACE_SZ=1024
+PSTATE_COMMONFLAGS+= -DPK_TRACE_SZ=2048
PSTATE_COMMONFLAGS+= -DPSTATE_GPE
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk
index f7965d8f..c516d6bf 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk
@@ -5,7 +5,7 @@
#
# OpenPOWER HCODE Project
#
-# COPYRIGHT 2016,2018
+# COPYRIGHT 2016,2019
# [+] International Business Machines Corp.
#
#
@@ -94,7 +94,7 @@ $(IMAGE)_COMMONFLAGS+= -DUSE_PK_APP_CFG_H=1
$(IMAGE)_COMMONFLAGS+= -D__PPE_PLAT
$(IMAGE)_COMMONFLAGS+= -D__PK__=1
#$(IMAGE)_COMMONFLAGS+= -fstack-usage
-$(IMAGE)_COMMONFLAGS+= -DPK_TRACE_SZ=1024
+$(IMAGE)_COMMONFLAGS+= -DPK_TRACE_SZ=2048
# add include paths
$(call ADD_PPEIMAGE_INCDIR,$(IMAGE),\
OpenPOWER on IntegriCloud