summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYue Du <daviddu@us.ibm.com>2016-02-24 23:27:38 -0600
committerhostboot <hostboot@us.ibm.com>2018-08-22 17:54:04 -0500
commitbfede8ec480adca02a24fb9efe0798d61b823206 (patch)
tree667f1043be3f2b091f3925dc8abf6507f69f98e5
parent5f2e6f8d81d69ae73bf922ca5dc9fd8e618df79d (diff)
downloadtalos-hcode-bfede8ec480adca02a24fb9efe0798d61b823206.tar.gz
talos-hcode-bfede8ec480adca02a24fb9efe0798d61b823206.zip
Combined Stop/PState Cme Image + unified interrupt handler
Change-Id: I2e9299665f7cb49884991e04ac067eb34652bcda Original-Change-Id: Ie954197008f1a35bd8336c9d921f55165ec52207 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/20857 Tested-by: Jenkins Server Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
-rwxr-xr-ximport/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c453
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h112
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c586
3 files changed, 607 insertions, 544 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c
index b3b55b7d..91d91fdf 100755
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c
@@ -53,16 +53,19 @@ p9_cme_stop_entry()
{
int rc = 0;
- uint8_t core_aborted = 0;
- uint8_t core_catchup = 0;
- uint8_t catchup_ongoing = 0;
- uint8_t entry_ongoing = 1;
+ int catchup_ongoing = 0;
+ int entry_ongoing = 1;
uint8_t target_level;
uint8_t deeper_level = 0;
+ uint8_t origin_level = 0;
+ uint32_t origin_core = 0;
uint32_t deeper_core = 0;
+ uint32_t core_aborted = 0;
+ uint32_t core_catchup = 0;
uint32_t core;
uint32_t loop;
uint32_t pm_states;
+ uint32_t lclr_data;
uint64_t scom_data;
ppm_sshsrc_t hist;
ppm_pig_t pig;
@@ -77,15 +80,19 @@ p9_cme_stop_entry()
// CME will do Daul-cast to both cores at the same time in entry flow.
core = (in32(CME_LCL_EISR) & BITS32(20, 2)) >> SHIFT32(21);
- // override with partial good core mask
- core = core & G_cme_stop_record.cme_flags & CME_MASK_BC;
+ // filter with partial good and running core mask
+ // core cannot enter stop if core is already stopped
+ core = core & G_cme_stop_record.core_enabled &
+ G_cme_stop_record.core_running;
- PK_TRACE("SE0: Core Select[%d]", core);
+ PK_TRACE("SE0: Core Select[%d] Enabled[%d] Running[%d]",
+ core, G_cme_stop_record.core_enabled,
+ G_cme_stop_record.core_running);
// Return error if None of both fired
if (!core)
{
- return CME_STOP_ENTRY_PM_NOT_ACTIVE;
+ pk_halt();
}
//===================================
@@ -95,57 +102,64 @@ p9_cme_stop_entry()
do // while(0) loop for stop flow control
{
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 1 (should be done by hardware)
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// Read SISR for pm_state_cX
pm_states = in32_sh(CME_LCL_SISR);
- G_cme_stop_record.req_stop_c0 = (pm_states & BITS32(4, 4)) >> SHIFT32(7);
- G_cme_stop_record.req_stop_c1 = (pm_states & BITS32(8, 4)) >> SHIFT32(11);
-
- // pm_active AND waken_up : pm_state = sisr (new state)
- // pm_active AND !waken_up : pm_state = sisr (only with auto promote)
- // !pm_active AND waken_up : pm_state = 0 (out dated state)
- // !pm_active AND !waken_up : pm_state = sisr (current state)
- if (~core & G_cme_stop_record.active_core & CME_MASK_C0)
+
+ // entry: req_level = target stop level
+ // act_level = current stop level
+ // running = FALSE, TRUE if aborted
+ // stopped: req_level = act_level = target and current stop level
+ // (if<=5)
+ // running = FALSE
+ // exit/abort: req_level = requested stop level
+ // act_level = latest stop level
+ // running = FALSE
+ // running: req_level = act_level = 0
+ // running = TRUE
+ // pm_active AND running : req_level = New requested stop level
+ // pm_active AND !running : req_level = Not possible,
+ // ignore false re-entry
+ // !pm_active AND running : req_level = 0 by exit,
+ // not changing req_level
+ // !pm_active AND !running : req_level = Current req_level
+ if (core & CME_MASK_C0)
{
- G_cme_stop_record.req_stop_c0 = 0;
+ G_cme_stop_record.req_level_c0 =
+ (pm_states & BITS32(4, 4)) >> SHIFT32(7);
}
- if (~core & G_cme_stop_record.active_core & CME_MASK_C1)
+ if (core & CME_MASK_C1)
{
- G_cme_stop_record.req_stop_c1 = 0;
+ G_cme_stop_record.req_level_c1 =
+ (pm_states & BITS32(8, 4)) >> SHIFT32(11);
}
- G_cme_stop_record.active_core &= ~core;
+ G_cme_stop_record.core_running &= ~core;
+ out32(CME_LCL_LMCR_OR, (core << SHIFT32(15)));
PK_TRACE("SE1: Request Stop Levels[%d %d]",
- G_cme_stop_record.req_stop_c0, G_cme_stop_record.req_stop_c1);
+ G_cme_stop_record.req_level_c0,
+ G_cme_stop_record.req_level_c1);
// Return error if target STOP level == 1(Nap)
- if((core == CME_MASK_C0 && G_cme_stop_record.req_stop_c0 <= STOP_LEVEL_1) ||
- (core == CME_MASK_C1 && G_cme_stop_record.req_stop_c1 <= STOP_LEVEL_1) ||
- (core == CME_MASK_BC && (G_cme_stop_record.req_stop_c0 <= STOP_LEVEL_1 ||
- G_cme_stop_record.req_stop_c1 <= STOP_LEVEL_1)))
+ if((core == CME_MASK_C0 &&
+ G_cme_stop_record.req_level_c0 <= STOP_LEVEL_1) ||
+ (core == CME_MASK_C1 &&
+ G_cme_stop_record.req_level_c1 <= STOP_LEVEL_1) ||
+ (core == CME_MASK_BC &&
+ (G_cme_stop_record.req_level_c0 <= STOP_LEVEL_1 ||
+ G_cme_stop_record.req_level_c1 <= STOP_LEVEL_1)))
{
- return CME_STOP_ENTRY_STOP1_SENT_IRQ;
+ pk_halt();
}
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 2
- //--------------------------------------------------------------------------
-
- PK_TRACE("SE2.a");
- // Disable fired Stop and corresponding Wakeup interrupts
- out32(CME_LCL_EIMR_OR, (CME_MASK_BC << SHIFT32(21)) |
- (core << SHIFT32(13)) |
- (core << SHIFT32(15)) |
- (core << SHIFT32(17)));
-
- PK_TRACE("SE2.b");
- // Also clear the status of the currently fired STOP interrupt(s)
- out32(CME_LCL_EISR_CLR, core << SHIFT32(21));
+ //----------------------------------------------------------------------
PK_TRACE("SE2.c");
// Request PCB Mux
@@ -156,29 +170,29 @@ p9_cme_stop_entry()
CME_PUTSCOM(CPPM_CPMMR_OR, core, BIT64(0));
// set target_level from pm_state for both cores or just one core
- target_level = (core == CME_MASK_C0) ? G_cme_stop_record.req_stop_c0 :
- G_cme_stop_record.req_stop_c1;
+ target_level = (core == CME_MASK_C0) ? G_cme_stop_record.req_level_c0 :
+ G_cme_stop_record.req_level_c1;
// If both cores are going into STOP but targeting different levels,
if ((core == CME_MASK_BC) &&
- (G_cme_stop_record.req_stop_c0 != G_cme_stop_record.req_stop_c1))
+ (G_cme_stop_record.req_level_c0 != G_cme_stop_record.req_level_c1))
{
// set target_level to the lighter level targeted by one core
// set deeper_level to the deeper level targeted by deeper core
- deeper_level = G_cme_stop_record.req_stop_c0;
+ deeper_level = G_cme_stop_record.req_level_c0;
deeper_core = CME_MASK_C0;
- if (G_cme_stop_record.req_stop_c0 < G_cme_stop_record.req_stop_c1)
+ if (G_cme_stop_record.req_level_c0 < G_cme_stop_record.req_level_c1)
{
- target_level = G_cme_stop_record.req_stop_c0;
- deeper_level = G_cme_stop_record.req_stop_c1;
+ target_level = G_cme_stop_record.req_level_c0;
+ deeper_level = G_cme_stop_record.req_level_c1;
deeper_core = CME_MASK_C1;
}
}
PK_TRACE("SE2.e");
// Update STOP History: In Transition of Entry
- // Set req_stop_level to target_level of either both or just one core
+ // Set req_level_level to target_level of either both or just one core
CME_STOP_UPDATE_HISTORY(core,
STOP_CORE_READY_RUN,
STOP_TRANS_ENTRY,
@@ -187,7 +201,7 @@ p9_cme_stop_entry()
STOP_REQ_ENABLE,
STOP_ACT_DISABLE);
- // Set req_stop_level to deeper_level for deeper core
+ // Set req_level_level to deeper_level for deeper core
if (deeper_core)
{
CME_STOP_UPDATE_HISTORY(deeper_core,
@@ -214,27 +228,39 @@ p9_cme_stop_entry()
PK_TRACE("SE2: PCB Mux Granted");
- //==========================
- MARK_TRAP(SE_STOP_CORE_CLKS)
- //==========================
+ //=============================
+ MARK_TRAP(SE_QUIESCE_CORE_INTF)
+ //=============================
PK_TRACE("SE2.g");
// Acknowledge the STOP Entry to PC with a pulse
- out32(CME_LCL_SICR_OR, core << SHIFT32(1));
+ out32(CME_LCL_SICR_OR, core << SHIFT32(1));
out32(CME_LCL_SICR_CLR, core << SHIFT32(1));
+ /// @todo Set LMCR bits 14 and/or 15 (override disables)
+
PK_TRACE("SE2.h");
// Raise Core-L2 + Core-CC Quiesces
out32(CME_LCL_SICR_OR, (core << SHIFT32(7)) | (core << SHIFT32(9)));
PK_TRACE("SE2.i");
+
+ do
+ {
+ lclr_data = in32(CME_LCL_SISR);
+ }
+ while((lclr_data & core) != core);
+
// Waits quiesce done for at least 512 core cycles
// MF: verify generate FCB otherwise math is wrong.
PPE_WAIT_CORE_CYCLES(loop, 512)
+ //==========================
+ MARK_TRAP(SE_STOP_CORE_CLKS)
+ //==========================
+
PK_TRACE("SE2.j");
// Raise Core Chiplet Fence
- CME_PUTSCOM(C_CPLT_CTRL0_OR, core, BIT64(2));
CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(18));
PK_TRACE("SE2.k");
@@ -243,7 +269,7 @@ p9_cme_stop_entry()
PK_TRACE("SE2.l");
// Stop Core Clocks
- CME_PUTSCOM(C_CLK_REGION, core, 0x9FFC00000000E000);
+ CME_PUTSCOM(C_CLK_REGION, core, 0x8FFC00000000E000);
PK_TRACE("SE2.m");
@@ -259,15 +285,14 @@ p9_cme_stop_entry()
PK_TRACE("SE2: Core Clock Stopped");
- //=========================
- MARK_TRAP(SE_DROP_CLK_SYNC)
- //=========================
+ //==============================
+ MARK_TRAP(SE_STOP_CORE_GRID)
+ //==============================
PK_TRACE("SE2.n");
// Drop clock sync enable before switch to refclk
CME_PUTSCOM(CPPM_CACCR_CLR, core, BIT64(15));
-#if !EPM_P9_TUNING
PK_TRACE("SE2.o");
// Poll for clock sync done to drop
@@ -277,24 +302,43 @@ p9_cme_stop_entry()
}
while(scom_data & BIT64(13));
-#endif
-
PK_TRACE("SE2.p");
// Switch glsmux to refclk to save clock grid power
CME_PUTSCOM(C_PPM_CGCR, core, 0);
- // Assert PCB Fence
- //CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(25));
// Assert Vital Fence
CME_PUTSCOM(C_CPLT_CTRL1_OR, core, BIT64(3));
// Assert Regional Fences
CME_PUTSCOM(C_CPLT_CTRL1_OR, core, 0xFFFF700000000000);
+ PK_TRACE("SE2: Clock Sync Dropped");
+
+ // Copy PECE CME sample to PPM Shadow
+ if (core & CME_MASK_C0)
+ {
+ scom_data = in64(CME_LCL_PECESR0);
+ CME_PUTSCOM(CPPM_PECES, core, scom_data);
+ G_cme_stop_record.act_level_c0 = STOP_LEVEL_2;
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ scom_data = in64(CME_LCL_PECESR1);
+ CME_PUTSCOM(CPPM_PECES, core, scom_data);
+ G_cme_stop_record.act_level_c1 = STOP_LEVEL_2;
+ }
+
+ //===========================
+ MARK_TAG(SE_STOP2_DONE, core)
+ //===========================
+
PK_TRACE("SE2.q");
// Update Stop History: In Core Stop Level 2
// Check if STOP level 2 reaches the target for both or one core
entry_ongoing =
- target_level == STOP_LEVEL_2 ? STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
+ target_level == STOP_LEVEL_2 ?
+ STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
+
CME_STOP_UPDATE_HISTORY(core,
STOP_CORE_IS_GATED,
entry_ongoing,
@@ -323,27 +367,11 @@ p9_cme_stop_entry()
entry_ongoing = 1;
}
- if (core & CME_MASK_C0)
- {
- G_cme_stop_record.act_stop_c0 = STOP_LEVEL_2;
- }
-
- if (core & CME_MASK_C1)
- {
- G_cme_stop_record.act_stop_c1 = STOP_LEVEL_2;
- }
-
- PK_TRACE("SE2: Clock Sync Dropped");
-
- //===========================
- MARK_TAG(SE_STOP2_DONE, core)
- //===========================
-
//===========================
MARK_TRAP(SE_IS0_BEGIN)
//===========================
#if !SKIP_ABORT
- out32(CME_LCL_EIMR_CLR, /*TODO(core << SHIFT32(13)) |*/
+ out32(CME_LCL_EIMR_CLR, (core << SHIFT32(13)) |
(core << SHIFT32(15)) |
(core << SHIFT32(17)));
sync();
@@ -355,36 +383,19 @@ p9_cme_stop_entry()
MARK_TRAP(SE_IS0_END)
//===================
- core_aborted = 0;
+ core_aborted = core & G_cme_stop_record.core_running;
- if ((core & CME_MASK_C0) &&
- G_cme_stop_record.act_stop_c0 == STOP_LEVEL_0 &&
- G_cme_stop_record.req_stop_c0 != STOP_LEVEL_0)
+ if (core_aborted && deeper_core)
{
- core_aborted |= CME_MASK_C0;
- core -= CME_MASK_C0;
- deeper_core = 0;
-
- if (deeper_core == CME_MASK_C1)
+ if (core_aborted != deeper_core)
{
target_level = deeper_level;
}
+ deeper_core = 0;
}
- if ((core & CME_MASK_C1) &&
- G_cme_stop_record.act_stop_c1 == STOP_LEVEL_0 &&
- G_cme_stop_record.req_stop_c1 != STOP_LEVEL_0)
- {
- core_aborted |= CME_MASK_C1;
- core -= CME_MASK_C1;
- deeper_core = 0;
-
- if (deeper_core == CME_MASK_C0)
- {
- target_level = deeper_level;
- }
- }
+ core = core & ~G_cme_stop_record.core_running;
if (!core)
{
@@ -393,22 +404,68 @@ p9_cme_stop_entry()
break;
}
+#if !SKIP_ENTRY_CATCHUP
+
if (catchup_ongoing)
{
- core = CME_MASK_BC;
+ // Y = 2 eo = 0 same if X = 2
+ // Y > 2 eo = 1 c=c t=t same if X = 2
+ // if X > 2 eo = 1
+ // if Y = 2 c=o t=o
+ // else (Y > 2) c=2
+ // if X != Y (X = Y: dl=0 dc=0 t=t)
+ // dl=o dc=o (X > Y)
+ // if X < Y
+ // dl=t dc=c t=o
+ if (origin_level > STOP_LEVEL_2)
+ {
+ if (target_level == STOP_LEVEL_2)
+ {
+ core = origin_core;
+ target_level = origin_level;
+ }
+ else
+ {
+ if (origin_level != target_level)
+ {
+ deeper_core = origin_core;
+ deeper_level = origin_level;
+
+ if (origin_level < target_level)
+ {
+ deeper_core = core;
+ deeper_level = target_level;
+ target_level = origin_level;
+ }
+ }
+
+ core = CME_MASK_BC;
+ }
+
+ entry_ongoing = 1;
+ }
+
break;
}
-#if !SKIP_CATCHUP
core_catchup = (in32(CME_LCL_EISR) & BITS32(20, 2)) >> SHIFT32(21);
-#endif
+ core_catchup = core_catchup & G_cme_stop_record.core_enabled &
+ G_cme_stop_record.core_running;
- if (core_catchup > core)
+ if (core_catchup)
{
- core = core_catchup - core;
+ origin_core = core;
+ origin_level = target_level;
+ core = core_catchup;
catchup_ongoing = 1;
+
+ //========================
+ MARK_TAG(SE_CATCHUP, core)
+ //========================
}
+#endif
+
}
while(catchup_ongoing);
@@ -425,9 +482,9 @@ p9_cme_stop_entry()
target_level[%d],deeper_level[%d]",
core, deeper_core, target_level, deeper_level);
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 3
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
if (target_level == 3)
{
@@ -442,6 +499,20 @@ p9_cme_stop_entry()
PK_TRACE("SE3.b");
// Drop to Vmin
+ if(core & CME_MASK_C0)
+ {
+ G_cme_stop_record.act_level_c0 = STOP_LEVEL_3;
+ }
+
+ if(core & CME_MASK_C1)
+ {
+ G_cme_stop_record.act_level_c1 = STOP_LEVEL_3;
+ }
+
+ //===========================
+ MARK_TAG(SE_STOP3_DONE, core)
+ //===========================
+
PK_TRACE("SE3.c");
// Update Stop History: In Core Stop Level 3
CME_STOP_UPDATE_HISTORY(core,
@@ -476,20 +547,6 @@ p9_cme_stop_entry()
entry_ongoing = 0;
}
- if(core & CME_MASK_C0)
- {
- G_cme_stop_record.act_stop_c0 = STOP_LEVEL_3;
- }
-
- if(core & CME_MASK_C1)
- {
- G_cme_stop_record.act_stop_c1 = STOP_LEVEL_3;
- }
-
- //===========================
- MARK_TAG(SE_STOP3_DONE, core)
- //===========================
-
// If we are done at STOP level 3
if (!entry_ongoing)
{
@@ -497,9 +554,9 @@ p9_cme_stop_entry()
}
}
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 4
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
//===============================
MARK_TAG(SE_POWER_OFF_CORE, core)
@@ -512,18 +569,6 @@ p9_cme_stop_entry()
CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(16));
#if !STOP_PRIME
-#if !EPM_P9_TUNING
- // Make sure we are not forcing PFET for VDD off
- // vdd_pfet_force_state == 00 (Nop)
- PK_TRACE("SE4.b");
- CME_GETSCOM(PPM_PFCS, core, CME_SCOM_AND, scom_data);
-
- if (scom_data & BITS64(0, 2))
- {
- return CME_STOP_ENTRY_VDD_PFET_NOT_IDLE;
- }
-
-#endif
// Prepare PFET Controls
// vdd_pfet_val/sel_override = 0 (disbaled)
@@ -545,23 +590,29 @@ p9_cme_stop_entry()
}
while(!(scom_data & BIT64(42)));
-#if !EPM_P9_TUNING
- // Optional: Poll for vdd_pg_sel being: 0x8
- PK_TRACE("SE4.f");
-
- do
- {
- CME_GETSCOM(PPM_PFCS, core, CME_SCOM_AND, scom_data);
- }
- while(!(scom_data & BIT64(46)));
-
-#endif
// Turn Off Force Voff
// vdd_pfet_force_state = 00 (Nop)
PK_TRACE("SE4.g");
CME_PUTSCOM(PPM_PFCS_CLR, core, BITS64(0, 2));
+
#endif
+ PK_TRACE("SE4: Core Powered Off");
+
+ if (core & CME_MASK_C0)
+ {
+ G_cme_stop_record.act_level_c0 = STOP_LEVEL_4;
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ G_cme_stop_record.act_level_c1 = STOP_LEVEL_4;
+ }
+
+ //===========================
+ MARK_TAG(SE_STOP4_DONE, core)
+ //===========================
+
PK_TRACE("SE4.h");
// Update Stop History: In Core Stop Level 4
// Check if STOP level 4 reaches the target for both or one core
@@ -596,27 +647,11 @@ p9_cme_stop_entry()
entry_ongoing = 1;
}
- if (core & CME_MASK_C0)
- {
- G_cme_stop_record.act_stop_c0 = STOP_LEVEL_4;
- }
-
- if (core & CME_MASK_C1)
- {
- G_cme_stop_record.act_stop_c1 = STOP_LEVEL_4;
- }
-
- PK_TRACE("SE4: Core Powered Off");
-
- //===========================
- MARK_TAG(SE_STOP4_DONE, core)
- //===========================
-
//===========================
MARK_TRAP(SE_IS1_BEGIN)
//===========================
#if !SKIP_ABORT
- out32(CME_LCL_EIMR_CLR, /*TODO(core << SHIFT32(13)) |*/
+ out32(CME_LCL_EIMR_CLR, (core << SHIFT32(13)) |
(core << SHIFT32(15)) |
(core << SHIFT32(17)));
sync();
@@ -628,39 +663,25 @@ p9_cme_stop_entry()
MARK_TRAP(SE_IS1_END)
//===================
- if ((core & CME_MASK_C0) &&
- G_cme_stop_record.act_stop_c0 == STOP_LEVEL_0 &&
- G_cme_stop_record.req_stop_c0 != STOP_LEVEL_0)
- {
- core_aborted |= CME_MASK_C0;
- core -= CME_MASK_C0;
- deeper_core = 0;
+ core_aborted = core & G_cme_stop_record.core_running;
- if (deeper_core == CME_MASK_C1)
+ if (core_aborted && deeper_core)
+ {
+ if (core_aborted != deeper_core)
{
target_level = deeper_level;
}
+ deeper_core = 0;
}
- if ((core & CME_MASK_C1) &&
- G_cme_stop_record.act_stop_c1 == STOP_LEVEL_0 &&
- G_cme_stop_record.req_stop_c1 != STOP_LEVEL_0)
- {
- core_aborted |= CME_MASK_C1;
- core -= CME_MASK_C1;
- deeper_core = 0;
-
- if (deeper_core == CME_MASK_C0)
- {
- target_level = deeper_level;
- }
- }
+ core = core & ~G_cme_stop_record.core_running;
if (!core)
{
core |= core_aborted;
entry_ongoing = 0;
+ break;
}
// If we are done at STOP level 4 or aborted
@@ -673,16 +694,16 @@ p9_cme_stop_entry()
target_level[%d],deeper_level[%d]",
core, deeper_core, target_level, deeper_level);
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 5 (preparsion of STOP LEVEL 8 and above)
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// block all wake up before purge L2,
// this is last chance either core can exit
- out32(CME_LCL_EIMR_OR, BITS32(12, 6));
+ //out32(CME_LCL_EIMR_OR, BITS32(12, 6));
- if ((G_cme_stop_record.req_stop_c0 >= STOP_LEVEL_8) &&
- (G_cme_stop_record.req_stop_c1 >= STOP_LEVEL_8))
+ if ((G_cme_stop_record.req_level_c0 >= STOP_LEVEL_8) &&
+ (G_cme_stop_record.req_level_c1 >= STOP_LEVEL_8))
{
//=========================
@@ -698,16 +719,21 @@ p9_cme_stop_entry()
// Poll for Purged Done
PK_TRACE("SE5.1b");
+
//===========================
MARK_TRAP(SE_IS2_BEGIN)
-
//===========================
+
do
{
#if !SKIP_L2_PURGE_ABORT
if(in32(CME_LCL_EINR) & BITS32(12, 6))
{
+
+ //===============================
+ MARK_TAG(SE_PURGE_L2_ABORT, core)
+ //===============================
// abort L2+NCU purges
out32(CME_LCL_SICR_OR, BIT32(19) | BIT32(23));
}
@@ -726,9 +752,9 @@ p9_cme_stop_entry()
PK_TRACE("SE5.1: L2/NCU/CHTM Purged");
- //=========================
- MARK_TRAP(SE_L2_PURGE_DONE)
- //=========================
+ //==============================
+ MARK_TAG(SE_PURGE_L2_DONE, core)
+ //==============================
}
//=============================
@@ -745,30 +771,24 @@ p9_cme_stop_entry()
STOP_REQ_DISABLE,
STOP_ACT_ENABLE);
- if (core & CME_MASK_C0)
- {
- G_cme_stop_record.act_stop_c0 = STOP_LEVEL_5;
- }
-
- if (core & CME_MASK_C1)
- {
- G_cme_stop_record.act_stop_c1 = STOP_LEVEL_5;
- }
-
// Send PCB Interrupt per core
PK_TRACE("SE5.2b");
pig.fields.req_intr_type = 2; //0b010: STOP State Change
if (core & CME_MASK_C0)
{
- pig.fields.req_intr_payload = G_cme_stop_record.req_stop_c0;
+ pig.fields.req_intr_payload = G_cme_stop_record.req_level_c0;
CME_PUTSCOM(PPM_PIG, CME_MASK_C0, pig.value);
+ G_cme_stop_record.core_stopgpe |= core;
+ G_cme_stop_record.act_level_c0 = STOP_LEVEL_5;
}
if (core & CME_MASK_C1)
{
- pig.fields.req_intr_payload = G_cme_stop_record.req_stop_c1;
+ pig.fields.req_intr_payload = G_cme_stop_record.req_level_c1;
CME_PUTSCOM(PPM_PIG, CME_MASK_C1, pig.value);
+ G_cme_stop_record.core_stopgpe |= core;
+ G_cme_stop_record.act_level_c1 = STOP_LEVEL_5;
}
// Change PPM Wakeup to STOPGPE
@@ -787,21 +807,6 @@ p9_cme_stop_entry()
// Release PPM Write Protection
CME_PUTSCOM(CPPM_CPMMR_CLR, core, BIT64(0));
- // Enable Wakeup Interrupts of this entry core if no handoff to SGPE
- // Otherwise enable Doorbell interrupts of this entry core
- out32(CME_LCL_EIMR_CLR,
- ((~core & G_cme_stop_record.active_core & CME_MASK_BC) << SHIFT32(21)));
-
- if (!entry_ongoing)
- out32(CME_LCL_EIMR_CLR,
- /*TODO((core & ~core_aborted & CME_MASK_BC) << SHIFT32(13)) |*/
- ((core & ~core_aborted & CME_MASK_BC) << SHIFT32(15)) |
- ((core & ~core_aborted & CME_MASK_BC) << SHIFT32(17)));
- else
- {
- out32_sh(CME_LCL_EIMR_CLR, (core << SHIFT32((41 - 32))));
- }
-
//============================
MARK_TRAP(ENDSCOPE_STOP_ENTRY)
//============================
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
index 499e7b4d..5553907a 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
@@ -81,6 +81,7 @@
#define EQ_QPPM_QCCR_WCLEAR 0x100F01BE
#define EQ_QPPM_QCCR_WOR 0x100F01BF
+#define EX_NCU_STATUS_REG 0x1001100F
#define EX_DRAM_REF_REG 0x1001180F
#define EX_PM_PURGE_REG 0x10011813
#define EX_PM_LCO_DIS_REG 0x10011816
@@ -99,18 +100,15 @@
hist.fields.act_write_enable = act_e; \
GPE_PUTSCOM_VAR(PPM_SSHSRC, base, id, 0, hist.value);
-
enum SGPE_STOP_RETURN_CODES
{
- SGPE_STOP_SUCCESS = 0,
- SGPE_STOP_RECEIVE_WRONG_PM_STATE = 0x00747301,
- SGPE_STOP_ENTRY_VDD_PFET_NOT_IDLE = 0x00747302
+ SGPE_STOP_SUCCESS = 0
};
enum SGPE_STOP_IRQ_SHORT_NAMES
{
IRQ_STOP_TYPE2 = OCCHW_IRQ_PMC_PCB_INTR_TYPE2_PENDING,
- IRQ_STOP_TYPE5 = OCCHW_IRQ_PMC_PCB_INTR_TYPE5_PENDING,
+ IRQ_STOP_TYPE3 = OCCHW_IRQ_PMC_PCB_INTR_TYPE3_PENDING,
IRQ_STOP_TYPE6 = OCCHW_IRQ_PMC_PCB_INTR_TYPE6_PENDING
};
@@ -132,64 +130,50 @@ enum SGPE_STOP_EVENT_FLAGS
SGPE_EXIT_FLAG = 1
};
-typedef union sgpe_level
-{
- uint16_t qlevel;
- struct
- {
- uint8_t x0lv : 8;
- uint8_t x1lv : 8;
- } xlevel;
- struct
- {
- uint8_t c0lv : 4;
- uint8_t c1lv : 4;
- uint8_t c2lv : 4;
- uint8_t c3lv : 4;
- } clevel;
-} sgpe_level_t;
-
-typedef union sgpe_state
+typedef struct
{
- uint32_t status;
- struct
- {
- uint8_t spare0 : 4;
- uint8_t q_req : 4;
- uint8_t x0req : 4;
- uint8_t x1req : 4;
- uint8_t spare1 : 4;
- uint8_t q_act : 4;
- uint8_t x0act : 4;
- uint8_t x1act : 4;
- } detail;
+ // requested stop state calculated from core stop levels
+ uint8_t req_state_x0;
+ uint8_t req_state_x1;
+ uint8_t req_state_q;
+ // actual stop state
+ uint8_t act_state_x0;
+ uint8_t act_state_x1;
+ uint8_t act_state_q;
} sgpe_state_t;
-typedef union sgpe_group
+typedef struct
{
- uint64_t vector[2];
- struct
- {
- uint32_t c_out;
- uint16_t x_out;
- uint16_t q_out;
- uint32_t c_in;
- uint16_t x_in;
- uint16_t q_in;
- } member;
+ uint32_t entry_x0;
+ uint32_t entry_x1;
+ uint32_t entry_x;
+ uint32_t entry_q;
+ uint32_t entry_c;
+ uint32_t exit_x0;
+ uint32_t exit_x1;
+ uint32_t exit_x;
+ uint32_t exit_q;
+ uint32_t exit_c;
+ uint32_t good_x0;
+ uint32_t good_x1;
+ uint32_t good_x;
+ uint32_t good_q;
+ uint32_t good_c;
} sgpe_group_t;
-
/// SGPE Stop Score Board Structure
typedef struct
{
- sgpe_group_t group;
+ // requested stop level for all cores in all quads
+ // needs to be global variable for ex/quad stop evaluation
+ uint8_t level[MAX_QUADS][CORES_PER_QUAD];
+ // requested and actual state of quad stop
sgpe_state_t state[MAX_QUADS];
- sgpe_level_t level[MAX_QUADS];
+ // group of ex and quad entering or exiting the stop
+ sgpe_group_t group;
PkSemaphore sem[2];
} SgpeStopRecord;
-
/// SGPE STOP Entry and Exit Prototypes
void p9_sgpe_stop_pig_type2_handler(void*, PkIrqId);
void p9_sgpe_stop_enter_thread(void*);
@@ -197,17 +181,17 @@ void p9_sgpe_stop_exit_thread(void*);
int p9_sgpe_stop_entry();
int p9_sgpe_stop_exit();
-int p9_hcd_cache_poweron(uint8_t);
-int p9_hcd_cache_chiplet_reset(uint8_t);
-int p9_hcd_cache_gptr_time_initf(uint8_t);
-int p9_hcd_cache_dpll_setup(uint8_t);
-int p9_hcd_cache_chiplet_init(uint8_t);
-int p9_hcd_cache_repair_initf(uint8_t);
-int p9_hcd_cache_arrayinit(uint8_t);
-int p9_hcd_cache_initf(uint8_t);
-int p9_hcd_cache_startclocks(uint8_t);
-int p9_hcd_cache_l2_startclocks(uint8_t, uint8_t);
-int p9_hcd_cache_scominit(uint8_t);
-int p9_hcd_cache_scomcust(uint8_t);
-int p9_hcd_cache_ras_runtime_scom(uint8_t);
-int p9_hcd_cache_occ_runtime_scom(uint8_t);
+int p9_hcd_cache_poweron(uint32_t);
+int p9_hcd_cache_chiplet_reset(uint32_t);
+int p9_hcd_cache_gptr_time_initf(uint32_t);
+int p9_hcd_cache_dpll_setup(uint32_t);
+int p9_hcd_cache_chiplet_init(uint32_t);
+int p9_hcd_cache_repair_initf(uint32_t);
+int p9_hcd_cache_arrayinit(uint32_t);
+int p9_hcd_cache_initf(uint32_t);
+int p9_hcd_cache_startclocks(uint32_t, uint32_t);
+int p9_hcd_cache_l2_startclocks(uint32_t, uint32_t);
+int p9_hcd_cache_scominit(uint32_t);
+int p9_hcd_cache_scomcust(uint32_t);
+int p9_hcd_cache_ras_runtime_scom(uint32_t);
+int p9_hcd_cache_occ_runtime_scom(uint32_t);
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c
index fce32aff..09e471bc 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c
@@ -31,234 +31,253 @@ extern SgpeStopRecord G_sgpe_stop_record;
int
p9_sgpe_stop_entry()
{
- int rc;
- uint8_t ex;
- uint8_t qloop;
- uint8_t cloop;
- uint8_t climit;
- uint16_t qentry;
- uint16_t xentry;
- uint8_t entry_ongoing[2] = {0, 0};
- uint8_t l3_purge_aborted = 0;
+ int entry_ongoing[2] = {0, 0};
+ int l3_purge_aborted = 0;
+ int rc = 0;
+ uint32_t ex = 0;
+ uint32_t qloop;
+ uint32_t cloop;
+ uint32_t climit;
+ uint32_t xentry;
+ uint32_t qentry;
uint32_t loop;
uint64_t scom_data;
ppm_sshsrc_t hist;
- //===================================================================
- MARK_TAG(BEGINSCOPE_STOP_ENTRY, (G_sgpe_stop_record.group.member.q_in >> 10))
- //===================================================================
+ //================================
+ MARK_TAG(BEGINSCOPE_STOP_ENTRY, 0)
+ //================================
- if (G_sgpe_stop_record.group.member.q_in)
+ if (G_sgpe_stop_record.group.entry_q)
+ {
MARK_TRAP(SE_STOP_SUSPEND_PSTATE)
+ }
- //TODO: message pgpe to suspend Pstate
-
- // ------------------------------------------------------------------------
- // EX STOP ENTRY
- // ------------------------------------------------------------------------
+ //TODO: message pgpe to suspend Pstate only if stop level >= 8
- for(xentry = G_sgpe_stop_record.group.member.x_in, qloop = 0;
- xentry > 0;
- xentry = xentry << 2, qloop++)
+ // ------------------------------------------------------------------------
+ // EX STOP ENTRY [LEVEL 8-10]
+ // ------------------------------------------------------------------------
+ // only stop 8 sets x_in
+ for(xentry = G_sgpe_stop_record.group.entry_x, qloop = 0;
+ xentry > 0;
+ xentry = xentry << 2, qloop++)
+ {
+ // if this ex is not up to entry, skip
+ if (!(ex = ((xentry & BITS32(0, 2)) >> SHIFT32(1))))
{
- // if this ex is not up to entry, skip
- if (!(ex = ((xentry & BITS16(0, 2)) >> SHIFT16(1))))
- {
- continue;
- }
+ continue;
+ }
- PK_TRACE("q[%d]exmask[%d] starts entry", qloop, ex);
+ PK_TRACE("q[%d]exmask[%d] starts entry", qloop, ex);
- //-------------------------------------------------------------------------
- // STOP LEVEL 8
- //-------------------------------------------------------------------------
+ // Update QSSR: stop_entry_ongoing
+ out32(OCB_QSSR_OR, BIT32(qloop + 20));
- // Update QSSR: stop_entry_ongoing
- out32(OCB_QSSR_OR, BIT32(qloop + 20));
+ // Update History for ongoing stop 8 entry
+ cloop = (ex & FST_EX_IN_QUAD) ? 0 : CORES_PER_EX;
+ climit = (ex & SND_EX_IN_QUAD) ? CORES_PER_QUAD : CORES_PER_EX;
+
+ for(; cloop < climit; cloop++)
+ {
+ SGPE_STOP_UPDATE_HISTORY(((qloop << 2) + cloop),
+ CORE_ADDR_BASE,
+ STOP_CORE_IS_GATED,
+ STOP_TRANS_ENTRY,
+ STOP_LEVEL_8,
+ STOP_LEVEL_8,
+ STOP_REQ_DISABLE,
+ STOP_ACT_DISABLE);
+ }
- // Update History for ongoing stop 8 entry
- cloop = (ex & FST_EX_IN_QUAD) ? 0 : CORES_PER_EX;
- climit = (ex & SND_EX_IN_QUAD) ? CORES_PER_QUAD : CORES_PER_EX;
+ //====================================================
+ MARK_TAG(SE_STOP_L2_CLKS, ((ex << 6) | (32 >> qloop)))
+ //====================================================
- for(; cloop < climit; cloop++)
- {
- SGPE_STOP_UPDATE_HISTORY(((qloop << 2) + cloop),
- CORE_ADDR_BASE,
- STOP_CORE_IS_GATED,
- STOP_TRANS_ENTRY,
- STOP_LEVEL_8,
- STOP_LEVEL_8,
- STOP_REQ_DISABLE,
- STOP_ACT_DISABLE);
- }
+ PK_TRACE("SE8.a");
- //========================
- MARK_TRAP(SE_STOP_L2_CLKS)
- //========================
+ // Disable L2 Snoop(quiesce L2-L3 interface, what about NCU?)
+ if (ex & FST_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_L2_RCMD_DIS_REG, qloop, 0),
+ BIT64(0));
- PK_TRACE("SE8.a");
- // Assert L2 Regional Fences
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL1_OR, qloop),
- ((uint64_t)ex << SHIFT64(9)));
- // Disable L2 Snoop(quiesce L2-L3 interface, what about NCU?)
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_L2_RCMD_DIS_REG, qloop, ex), BIT64(0));
- PPE_WAIT_CORE_CYCLES(loop, 256)
+ if (ex & SND_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_L2_RCMD_DIS_REG, qloop, 1),
+ BIT64(0));
- PK_TRACE("SE8.b");
- // Set all bits to zero prior stop core clocks
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SCAN_REGION_TYPE, qloop), 0);
+ PPE_WAIT_CORE_CYCLES(loop, 256)
- PK_TRACE("SE8.c");
- // Stop L2 Clocks
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop),
- (0x900000000000E000 | ((uint64_t)ex << SHIFT64(9))));
+ PK_TRACE("SE8.b");
+ // Set all bits to zero prior stop cache clocks
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SCAN_REGION_TYPE, qloop), 0);
- PK_TRACE("SE8.d");
+ PK_TRACE("SE8.c");
+ // Stop L2 Clocks
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop),
+ (0x800000000000E000 | ((uint64_t)ex << SHIFT64(9))));
- // Poll for L2 clocks stopped
- do
- {
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, qloop), scom_data);
- }
- while(((scom_data >> SHIFT64(9)) & ex) != ex);
+ PK_TRACE("SE8.d");
- // MF: verify compiler generate single rlwmni
- // MF: delay may be needed for stage latch to propagate thold
+ // Poll for L2 clocks stopped
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, qloop), scom_data);
+ }
+ while(((scom_data >> SHIFT64(9)) & ex) != ex);
- PK_TRACE("SE8: L2 Clock Stopped");
+ // MF: verify compiler generate single rlwmni
+ // MF: delay may be needed for stage latch to propagate thold
- //========================
- MARK_TRAP(SE_STOP_L2_GRID)
- //========================
+ PK_TRACE("SE8: L2 Clock Stopped");
- PK_TRACE("SE8.e");
- // Drop clock sync enable before switch to refclk
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_CLR, qloop),
- (ex << SHIFT64(37)));
+ //========================
+ MARK_TRAP(SE_STOP_L2_GRID)
+ //========================
-#if !EPM_P9_TUNING
- PK_TRACE("SE8.f");
+ PK_TRACE("SE8.e");
+ // Drop clock sync enable before switch to refclk
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_CLR, qloop),
+ ((uint64_t)ex << SHIFT64(37)));
- // Poll for clock sync done to drop
- do
- {
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(QPPM_QACSR, qloop), scom_data);
- }
- while((~scom_data >> SHIFT64(37)) & ex != ex);
+ PK_TRACE("SE8.f");
-#endif
+ // Poll for clock sync done to drop
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(QPPM_QACSR, qloop), scom_data);
+ }
+ while(((~scom_data >> SHIFT64(37)) & ex) != ex);
- PK_TRACE("SE8.g");
- // Switch glsmux to refclk to save clock grid power
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_CLR, qloop),
- (ex << SHIFT64(35)));
+ PK_TRACE("SE8.g");
+ // Switch glsmux to refclk to save clock grid power
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_CLR, qloop),
+ ((uint64_t)ex << SHIFT64(35)));
- PK_TRACE("SE8.h");
+ PK_TRACE("SE8.h");
- if (ex & FST_EX_IN_QUAD)
- {
- cloop = 0;
- G_sgpe_stop_record.state[qloop].detail.x0act = STOP_LEVEL_8;
- entry_ongoing[0] =
- G_sgpe_stop_record.state[qloop].detail.x0req == STOP_LEVEL_8 ?
- STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
- }
- else
- {
- cloop = CORES_PER_EX;
- }
+ if (ex & FST_EX_IN_QUAD)
+ {
+ cloop = 0;
+ G_sgpe_stop_record.state[qloop].act_state_x0 = STOP_LEVEL_8;
+ entry_ongoing[0] =
+ G_sgpe_stop_record.state[qloop].req_state_x0 == STOP_LEVEL_8 ?
+ STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
+ }
+ else
+ {
+ cloop = CORES_PER_EX;
+ }
- if (ex & SND_EX_IN_QUAD)
- {
- climit = CORES_PER_QUAD;
- G_sgpe_stop_record.state[qloop].detail.x1act = STOP_LEVEL_8;
- entry_ongoing[1] =
- G_sgpe_stop_record.state[qloop].detail.x0req == STOP_LEVEL_8 ?
- STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
- }
- else
- {
- climit = CORES_PER_EX;
- }
+ if (ex & SND_EX_IN_QUAD)
+ {
+ climit = CORES_PER_QUAD;
+ G_sgpe_stop_record.state[qloop].act_state_x1 = STOP_LEVEL_8;
+ entry_ongoing[1] =
+ G_sgpe_stop_record.state[qloop].req_state_x0 == STOP_LEVEL_8 ?
+ STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
+ }
+ else
+ {
+ climit = CORES_PER_EX;
+ }
- for(; cloop < climit; cloop++)
- {
- SGPE_STOP_UPDATE_HISTORY(((qloop << 2) + cloop),
- CORE_ADDR_BASE,
- STOP_CORE_IS_GATED,
- entry_ongoing[cloop >> 1],
- STOP_LEVEL_8,
- STOP_LEVEL_8,
- STOP_REQ_DISABLE,
- STOP_ACT_ENABLE);
- }
+ for(; cloop < climit; cloop++)
+ {
+ // request levle already set by CME
+ // shift by 2 == times 4, which is cores per quad
+ SGPE_STOP_UPDATE_HISTORY(((qloop << 2) + cloop),
+ CORE_ADDR_BASE,
+ STOP_CORE_IS_GATED,
+ entry_ongoing[cloop >> 1],
+ STOP_LEVEL_8,
+ STOP_LEVEL_8,
+ STOP_REQ_DISABLE,
+ STOP_ACT_ENABLE);
+ }
- // Update QSSR: l2_stopped, drop stop_entry_ongoing
- out32(OCB_QSSR_OR, (ex << SHIFT32((qloop << 1) + 1)) | BIT32(qloop + 20));
+ // Update QSSR: l2_stopped, entry_ongoing = 0
+ out32(OCB_QSSR_CLR, BIT32(qloop + 20));
+ out32(OCB_QSSR_OR, (ex << SHIFT32((qloop << 1) + 1)));
- //=================================================
- MARK_TAG(SE_STOP8_DONE, ((ex << 6) | (32 >> qloop)))
- //=================================================
+ //==================================================
+ MARK_TAG(SE_STOP8_DONE, ((ex << 6) | (32 >> qloop)))
+ //==================================================
- };
+ };
// ------------------------------------------------------------------------
- // QUAD STOP ENTRY
+ // QUAD STOP ENTRY [LEVEL 11-15]
// ------------------------------------------------------------------------
- for(qentry = G_sgpe_stop_record.group.member.q_in, qloop = 0;
+ for(qentry = G_sgpe_stop_record.group.entry_q, qloop = 0;
qentry > 0;
qentry = qentry << 1, qloop++)
{
- PK_TRACE("q[%x] starts entry", qentry);
-
// if this quad is not up to entry, skip
- if (!(qentry & BIT16(0)))
+ if (!(qentry & BIT32(0)))
{
continue;
}
- PK_TRACE("q[%d] starts entry", qloop);
+ if (G_sgpe_stop_record.group.good_x0 & BIT32(qloop))
+ {
+ ex |= FST_EX_IN_QUAD;
+ }
+
+ if (G_sgpe_stop_record.group.good_x1 & BIT32(qloop))
+ {
+ ex |= SND_EX_IN_QUAD;
+ }
+
+ PK_TRACE("q[%d]x[%d] starts quad entry", qloop, ex);
// Update QSSR: stop_entry_ongoing
out32(OCB_QSSR_OR, BIT32(qloop + 20));
- // Update STOP History
+ // Update Quad STOP History
SGPE_STOP_UPDATE_HISTORY(qloop,
QUAD_ADDR_BASE,
STOP_CORE_IS_GATED,
STOP_TRANS_ENTRY,
- G_sgpe_stop_record.state[qloop].detail.q_req,
+ G_sgpe_stop_record.state[qloop].req_state_q,
STOP_LEVEL_11,
STOP_REQ_ENABLE,
STOP_ACT_DISABLE);
- // ------------------------------------------------------------------------
- // STOP LEVEL 11.A
- //-------------------------------------------------------------------------
-
- //=================================
+ //==================================
MARK_TAG(SE_PURGE_L3, (32 >> qloop))
- //=================================
-
- ex = 2;
+ //==================================
PK_TRACE("SE11.a");
+
// Disable LCO prior to purge
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG, qloop, ex), BIT64(0));
+ if(ex & FST_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG, qloop, 0),
+ BIT64(0));
+ }
+
+ if(ex & SND_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG, qloop, 1),
+ BIT64(0));
+ }
#if !SKIP_L3_PURGE
PK_TRACE("SE11.b");
+
// Assert Purge L3
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, ex), BIT64(0));
+ if(ex & FST_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, 0), BIT64(0));
+ }
+
+ if(ex & SND_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, 1), BIT64(0));
+ }
- // PK_TRACE("SE11.c");
- // No need: Assert chtm purges
// todo: stop debug trace, attribute may be needed
- //GPE_PUTSCOM(CME_SCOM_SICR_OR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX0,
- // qloop, BIT64(24)|BIT64(25));
- //GPE_PUTSCOM(CME_SCOM_SICR_OR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX1,
- // qloop, BIT64(24)|BIT64(25));
PK_TRACE("SE11.d");
@@ -273,27 +292,62 @@ p9_sgpe_stop_entry()
{
for(cloop = 0; cloop < CORES_PER_QUAD; cloop++)
{
+ // todo type3
if (in32(OCB_OPIT2CN(((qloop << 2) + cloop))) &
TYPE2_PAYLOAD_STOP_EVENT)
{
- MARK_TRAP(SE_PURGE_L3_ABORT)
+
+ //========================================
+ MARK_TAG(SE_PURGE_L3_ABORT, (32 >> qloop))
+ //========================================
+
// Assert Purge L3 Abort
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG,
- qloop, ex), BIT64(2));
+ if (ex & FST_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG,
+ qloop, 0),
+ BIT64(2));
+
+ if (ex & SND_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG,
+ qloop, 1),
+ BIT64(2));
// Poll for Abort Done
- do
+ if(ex & FST_EX_IN_QUAD)
{
- GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG,
- qloop, ex), scom_data);
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(
+ EX_PM_PURGE_REG,
+ qloop, 0), scom_data);
+ }
+ while(scom_data & (BIT64(0) | BIT64(2)));
}
- while(scom_data & (BIT64(0) | BIT64(2)));
- MARK_TRAP(SE_PURGE_L3_ABORT_DONE)
+ if(ex & SND_EX_IN_QUAD)
+ {
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(
+ EX_PM_PURGE_REG,
+ qloop, 1), scom_data);
+ }
+ while(scom_data & (BIT64(0) | BIT64(2)));
+ }
+
+ //=============================================
+ MARK_TAG(SE_PURGE_L3_ABORT_DONE, (32 >> qloop))
+ //=============================================
// Deassert LCO Disable
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG,
- qloop, ex), 0);
+ if(ex & FST_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG,
+ qloop, 0), 0);
+
+ if(ex & SND_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG,
+ qloop, 1), 0);
+
// Notify PGPE to resume
l3_purge_aborted = 1;
break;
@@ -303,7 +357,14 @@ p9_sgpe_stop_entry()
}
#endif
- GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, ex), scom_data);
+
+ if (ex & FST_EX_IN_QUAD)
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, 0),
+ scom_data);
+
+ if (ex & SND_EX_IN_QUAD)
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, 1),
+ scom_data);
}
while(scom_data & BIT64(0));
@@ -314,30 +375,9 @@ p9_sgpe_stop_entry()
#endif
- //====================
- MARK_TRAP(SE_PURGE_PB)
- //====================
-
-#if EPM_P9_TUNING
- // PK_TRACE("SE11.e");
- // No need: Poll for chtm purge done
- // do {
- // GPE_GETSCOM(CME_SCOM_EISR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX0,
- // qloop, scom_data);
- // } while((scom_data & BITS64(24,2)) != BITS64(22,2));
- // do {
- // GPE_GETSCOM(CME_SCOM_EISR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX1,
- // qloop, scom_data);
- // } while((scom_data & BITS64(24,2)) != BITS64(22,2));
- // cme scom eisr is read-only, cannot clear the eisr here, clear in cme
-#endif
-
- // PK_TRACE("SE11.f");
- // No need: Deassert chtm purges
- //GPE_PUTSCOM(CME_SCOM_SICR_CLR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX0,
- // qloop, BIT64(24)|BIT64(25));
- //GPE_PUTSCOM(CME_SCOM_SICR_CLR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX1,
- // qloop, BIT64(24)|BIT64(25));
+ //==================================
+ MARK_TAG(SE_PURGE_PB, (32 >> qloop))
+ //==================================
PK_TRACE("SE11.g");
// Assert PowerBus purge
@@ -354,29 +394,63 @@ p9_sgpe_stop_entry()
PK_TRACE("SE11.i");
// Deassert PowerBus purge
+ // todo may need to move this to wakeup
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(30));
- //==========================================
+ //===========================================
MARK_TAG(SE_WAIT_PGPE_SUSPEND, (32 >> qloop))
- //==========================================
+ //===========================================
// TODO: Poll PGPE Suspend Ack
- //=====================================
- MARK_TAG(SE_STOP_CACHE_CLKS, (32 >> qloop))
- //=====================================
+ //======================================
+ MARK_TAG(SE_QUIESCE_QUAD, (32 >> qloop))
+ //======================================
+ // todo halt cme here
PK_TRACE("SE11.j");
+
// Assert refresh quiesce prior to L3 (refresh domain) stop clk
// Edram quiesce is asserted by hardware when l3 thold is asserted in cc
- GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, ex), scom_data);
- scom_data |= BIT64(7);
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, ex), scom_data);
+ if (ex & FST_EX_IN_QUAD)
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, 0), scom_data);
+ scom_data |= BIT64(7);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, 0), scom_data);
+ }
- // todo: check NCU_SATUS_REG[0:3] for all zeros
+ if (ex & SND_EX_IN_QUAD)
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, 1), scom_data);
+ scom_data |= BIT64(7);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, 1), scom_data);
+ }
+
+ // Check NCU_SATUS_REG[0:3] for all zeros
+ if (ex & FST_EX_IN_QUAD)
+ {
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_NCU_STATUS_REG, qloop, 0),
+ scom_data);
+ }
+ while((~scom_data & BITS64(0, 4)) != BITS64(0 , 4));
+ }
+
+ if (ex & SND_EX_IN_QUAD)
+ {
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_NCU_STATUS_REG, qloop, 1),
+ scom_data);
+ }
+ while((~scom_data & BITS64(0, 4)) != BITS64(0 , 4));
+ }
+
+ //===========================
+ MARK_TRAP(SE_STOP_CACHE_CLKS)
+ //===========================
PK_TRACE("SE11.k");
- // Assert flush_inhibit
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL0_OR, qloop), BIT64(2));
// Raise Cache Logical fence
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, qloop), BIT64(18));
@@ -387,8 +461,8 @@ p9_sgpe_stop_entry()
PK_TRACE("SE11.m");
// Stop Cache Clocks
- //GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop), 0x9F3E00000000E000);
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop), 0x9E3E00000000E000);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop),
+ 0x8C3E00000000E000 | ((uint64_t)ex << SHIFT64(7)));
PK_TRACE("SE11.n");
@@ -397,9 +471,9 @@ p9_sgpe_stop_entry()
{
GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, qloop), scom_data);
}
-
- //while((scom_data & (BITS64(4, 4) | BITS64(10, 4))) != (BITS64(4, 4) | BITS64(10, 4)));
- while((scom_data & (BITS64(4, 3) | BITS64(10, 5))) != (BITS64(4, 3) | BITS64(10, 5)));
+ while((scom_data &
+ (BITS64(4, 2) | ((uint64_t)ex << SHIFT64(7)) | BITS64(10, 5))) !=
+ (BITS64(4, 2) | ((uint64_t)ex << SHIFT64(7)) | BITS64(10, 5)));
// MF: verify compiler generate single rlwmni
// MF: delay may be needed for stage latch to propagate thold
@@ -418,17 +492,9 @@ p9_sgpe_stop_entry()
// Update QSSR: quad_stopped
out32(OCB_QSSR_OR, BIT32(qloop + 14));
- //===================================
- MARK_TAG(SE_STOP_CACHE_CLKS_DONE, (32 >> qloop))
- //===================================
-
- //-------------------------------------------------------------------------
- // STOP LEVEL 11.B
- //-------------------------------------------------------------------------
-
- //========================================
+ //=========================================
MARK_TAG(SE_POWER_OFF_CACHE, (32 >> qloop))
- //========================================
+ //=========================================
// DD: Assert Cache Vital Thold/PCB Fence/Electrical Fence
PK_TRACE("SE11.q");
@@ -437,45 +503,49 @@ p9_sgpe_stop_entry()
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, qloop), BIT64(16));
// L3 edram shutdown
+ // todo: not EPM flag for delay
PK_TRACE("SE11.r");
- /*
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(7));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(6));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(5));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(4));
- */
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(3));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(2));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(1));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(0));
-#if !STOP_PRIME
-#if !EPM_P9_TUNING
- // Make sure we are not forcing PFET for VDD or VCS off
- // vdd_pfet_force_state == 00 (Nop)
- // vcs_pfet_force_state == 00 (Nop)
- PK_TRACE("SE11.s");
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, qloop), scom_data);
-
- if (scom_data & BITS64(0, 4))
+ if (ex & SND_EX_IN_QUAD)
{
- return SGPE_STOP_ENTRY_VDD_PFET_NOT_IDLE;
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(7));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(6));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(5));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(4));
}
-#endif
+ if (ex & FST_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(3));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(2));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(1));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(0));
+ }
+#if !STOP_PRIME
+ // todo needed?
// Prepare PFET Controls
// vdd_pfet_val/sel_override = 0 (disbaled)
// vcs_pfet_val/sel_override = 0 (disbaled)
// vdd_pfet_regulation_finger_en = 0 (controled by FSM)
PK_TRACE("SE11.t");
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_CLR, qloop), BITS64(4, 4) | BIT64(8));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_CLR, qloop),
+ BITS64(4, 4) | BIT64(8));
- // Power Off Cache VDD/VDS
- // vdd_pfet_force_state = 01 (Force Voff)
+ // Power Off Cache VDS then VDD
// vcs_pfet_force_state = 01 (Force Voff)
PK_TRACE("SE11.u");
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_OR, qloop), BIT64(1) | BIT64(3));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_OR, qloop), BIT64(3));
+
+ // todo: poll the sense line instead
// Poll for power gate sequencer state: 0x8 (FSM Idle)
PK_TRACE("SE11.v");
@@ -483,28 +553,32 @@ p9_sgpe_stop_entry()
{
GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, qloop), scom_data);
}
- while(!(scom_data & (BIT64(42) | BIT64(50))));
+ while(!(scom_data & BIT64(50)));
-#if !EPM_P9_TUNING
- // Optional: Poll for vdd_pg_sel/vcs_pg_sel being: 0x8
- PK_TRACE("SE11.w");
+ // vdd_pfet_force_state = 01 (Force Voff)
+ PK_TRACE("SE11.u");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_OR, qloop), BIT64(1));
+
+ // todo: poll the sense line instead
+ // Poll for power gate sequencer state: 0x8 (FSM Idle)
+ PK_TRACE("SE11.v");
do
{
- CME_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, qloop), scom_data);
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, qloop), scom_data);
}
- while(!(scom_data & BIT64(46) | BIT64(54)));
-
-#endif
+ while(!(scom_data & BIT64(42)));
// Turn Off Force Voff
// vdd_pfet_force_state = 00 (Nop)
+ // vcs_pfet_force_state = 00 (Nop)
PK_TRACE("SE11.x");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_CLR, qloop), BITS64(0, 4));
+
#endif
PK_TRACE("SE11.y");
- G_sgpe_stop_record.state[qloop].detail.q_act = STOP_LEVEL_11;
+ G_sgpe_stop_record.state[qloop].act_state_q = STOP_LEVEL_11;
for(cloop = 0; cloop < CORES_PER_QUAD; cloop++)
{
@@ -530,9 +604,9 @@ p9_sgpe_stop_entry()
// Update QSSR: drop stop_entry_ongoing
out32(OCB_QSSR_CLR, BIT32(qloop + 20));
- //====================================
+ //=====================================
MARK_TAG(SE_STOP11_DONE, (32 >> qloop))
- //====================================
+ //=====================================
}
// Enable Type2 Interrupt
OpenPOWER on IntegriCloud