diff options
| author | Yue Du <daviddu@us.ibm.com> | 2016-02-24 23:27:38 -0600 |
|---|---|---|
| committer | hostboot <hostboot@us.ibm.com> | 2018-08-22 17:54:04 -0500 |
| commit | bfede8ec480adca02a24fb9efe0798d61b823206 (patch) | |
| tree | 667f1043be3f2b091f3925dc8abf6507f69f98e5 | |
| parent | 5f2e6f8d81d69ae73bf922ca5dc9fd8e618df79d (diff) | |
| download | talos-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>
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 |

