summaryrefslogtreecommitdiffstats
path: root/import
diff options
context:
space:
mode:
authorYue Du <daviddu@us.ibm.com>2016-12-30 01:00:27 -0600
committerhostboot <hostboot@us.ibm.com>2018-08-22 17:54:19 -0500
commitaee37bdb6f32c961a1b3ac7163615a7400efa7ef (patch)
treedd25b11b7acf05b7c2c454549a19d24796ac7f96 /import
parentadd78b915e7ee7e1ddc3139ad67c289e5725ad96 (diff)
downloadtalos-hcode-aee37bdb6f32c961a1b3ac7163615a7400efa7ef.tar.gz
talos-hcode-aee37bdb6f32c961a1b3ac7163615a7400efa7ef.zip
STOP: SGPE IPC support for WOF
Change-Id: I7b0cbe3a1fcd112bbc3a6bcd4bada77ab0efdd1d Original-Change-Id: I7b8b10def5f2480e4886a48cf0c4a321dc99c7fe Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34249 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: ADAM S. HALE <ashale@us.ibm.com> Reviewed-by: AMIT KUMAR <akumar3@us.ibm.com> Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
Diffstat (limited to 'import')
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h49
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c178
2 files changed, 216 insertions, 11 deletions
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 e9d516b9..0bb1f0fd 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
@@ -51,6 +51,10 @@ extern "C" {
#include "cppm_firmware_registers.h"
#include "qppm_firmware_registers.h"
+#include "ipc_api.h"
+#include "ipc_async_cmd.h"
+#include "ipc_messages.h"
+
#include "p9_stop_common.h"
#include "p9_pm_hcd_flags.h"
@@ -156,6 +160,22 @@ extern "C" {
hist.fields.act_write_enable = act_e; \
GPE_PUTSCOM_VAR(PPM_SSHSRC, base, id, 0, hist.value);
+enum SGPE_IPC_CONSTANTS
+{
+ ENABLE_CORE_STOP_UPDATES = 1,
+ ENABLE_QUAD_STOP_UPDATES = 2,
+ ENABLE_BOTH_STOP_UPDATES = 3,
+ DISABLE_CORE_STOP_UPDATES = 5,
+ DISABLE_QUAD_STOP_UPDATES = 6,
+ DISABLE_BOTH_STOP_UPDATES = 7,
+ SGPE_IPC_UPDATE_CORE_ENABLED = 1,
+ SGPE_IPC_UPDATE_QUAD_ENABLED = 2,
+ SGPE_IPC_UPDATE_TYPE_ENTRY = 0,
+ SGPE_IPC_UPDATE_TYPE_EXIT = 1,
+ SGPE_IPC_RETURN_CODE_NULL = 0,
+ SGPE_IPC_RETURN_CODE_ACK = 1
+};
+
enum SGPE_STOP_RETURN_CODES
{
SGPE_STOP_SUCCESS = 0
@@ -201,12 +221,20 @@ enum SGPE_STOP_PSCOM_MASK
PSCOM_MASK_EX1_L3 = BIT64(5) | BIT64(7) | BIT64(9)
};
+enum SGPE_FUNCTION_STATUS
+{
+ STATUS_RESUMING = 0,
+ STATUS_FUNCTIONAL = 1,
+ STATUS_SUSPENDING = 2,
+ STATUS_SUSPENDED = 3
+};
enum SGPE_STOP_VECTOR_INDEX
{
VECTOR_EXIT = 0,
VECTOR_ENTRY = 1,
- VECTOR_CONFIG = 2
+ VECTOR_CONFIG = 2,
+ VECTOR_ACTIVE = 3
};
typedef struct
@@ -225,14 +253,24 @@ typedef struct
typedef struct
{
- uint32_t core[3]; // 24 bits
+ uint32_t core[4]; // 24 bits
+ uint32_t quad[4]; // 6 bits
uint32_t ex_l[3]; // 6 bits
uint32_t ex_r[3]; // 6 bits
uint32_t ex_b[3]; // 12 bits
- uint32_t quad[3]; // 6 bits
uint32_t qswu[3]; // 6 bits
} sgpe_group_t;
+typedef struct
+{
+ // function status(functional, suspending, suspended, resuming)
+ uint8_t status_pstate;
+ uint8_t status_stop;
+ // sgpe-pgpe interlock status(quad/core updates enable/disable)
+ uint8_t update_pgpe;
+ ipc_msg_t* suspend_cmd;
+} sgpe_wof_t;
+
/// SGPE Stop Score Board Structure
typedef struct
{
@@ -243,6 +281,7 @@ typedef struct
sgpe_state_t state[MAX_QUADS];
// group of ex and quad entering or exiting the stop
sgpe_group_t group;
+ sgpe_wof_t wof;
PkSemaphore sem[2];
} SgpeStopRecord;
@@ -254,6 +293,9 @@ typedef struct
uint64_t data;
} SgpeScomRestore;
+/// SGPE to PGPE IPC handlers
+void p9_sgpe_ipc_pgpe_ctrl_stop_updates(ipc_msg_t* cmd, void* arg);
+void p9_sgpe_ipc_pgpe_suspend_stop(ipc_msg_t* cmd, void* arg);
/// SGPE STOP Entry and Exit Prototypes
void p9_sgpe_stop_pig_handler(void*, PkIrqId);
@@ -262,6 +304,7 @@ void p9_sgpe_stop_exit_thread(void*);
int p9_sgpe_stop_entry();
int p9_sgpe_stop_exit();
+/// Procedures shared between Istep4 and SGPE Stop
int p9_hcd_cache_scan0(uint32_t, uint64_t, uint64_t);
int p9_hcd_cache_poweron(uint32_t);
int p9_hcd_cache_chiplet_reset(uint32_t, 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 529b1b7c..8d3f9288 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
@@ -26,7 +26,16 @@
#include "p9_sgpe_stop.h"
#include "p9_sgpe_stop_enter_marks.h"
-extern SgpeStopRecord G_sgpe_stop_record;
+extern SgpeStopRecord G_sgpe_stop_record;
+
+#if !SKIP_IPC
+
+ GPE_BUFFER(ipc_async_cmd_t G_sgpe_ipccmd_to_pgpe);
+ GPE_BUFFER(ipcmsg_s2p_suspend_pstate_t G_sgpe_ipcmsg_suspend_pstate);
+ GPE_BUFFER(ipcmsg_s2p_update_active_cores_t G_sgpe_ipcmsg_update_cores);
+ GPE_BUFFER(ipcmsg_s2p_update_active_quads_t G_sgpe_ipcmsg_update_quads);
+
+#endif
#if HW386311_DD1_PBIE_RW_PTR_STOP11_FIX
@@ -76,6 +85,9 @@ p9_sgpe_stop_entry()
#if HW386311_DD1_PBIE_RW_PTR_STOP11_FIX
int spin;
#endif
+#if !SKIP_IPC
+ int rc;
+#endif
//--------------------------------------------------------------------------
PK_TRACE_INF("+++++ +++++ BEGIN OF STOP ENTRY +++++ +++++");
@@ -173,20 +185,124 @@ p9_sgpe_stop_entry()
G_sgpe_stop_record.group.ex_r[VECTOR_ENTRY],
G_sgpe_stop_record.group.quad[VECTOR_ENTRY]);
- //TODO: message pgpe to suspend Pstate only if stop level >= 8
- if (G_sgpe_stop_record.group.quad[VECTOR_ENTRY])
+
+
+#if !SKIP_IPC
+
+ // If any core entries, including stop5 to stop15
+ // sends Update Active Cores IPC to the PGPE
+ // with Update Type being Enter and the ActiveCores field
+ // indicating the resultant cores that have already been powered off.
+ // PGPE acknowledge immediately and
+ // then perform any adjustments to take advantage of the powered off cores.
+ // Upon a good response from the PGPE,
+ // the SGPE retires the operation ???
+ // Upon a bad response from the PGPE,
+ // the SGPE will halt as the SGPE and PGPE are now out of synchronization.
+ // [This is not a likely error.]
+
+ if((G_sgpe_stop_record.wof.update_pgpe & SGPE_IPC_UPDATE_CORE_ENABLED) &&
+ G_sgpe_stop_record.group.core[VECTOR_ENTRY])
+ {
+ PK_TRACE_INF("SEIPC: Update PGPE with Active Cores");
+ G_sgpe_ipcmsg_update_cores.fields.update_type = SGPE_IPC_UPDATE_TYPE_ENTRY;
+ G_sgpe_ipcmsg_update_cores.fields.return_code = SGPE_IPC_RETURN_CODE_NULL;
+ G_sgpe_ipcmsg_update_cores.fields.active_cores =
+ (G_sgpe_stop_record.group.core[VECTOR_ENTRY] >> SHIFT32(5));
+
+ G_sgpe_ipccmd_to_pgpe.cmd_data = &G_sgpe_ipcmsg_update_cores;
+ ipc_init_msg(&G_sgpe_ipccmd_to_pgpe.cmd,
+ IPC_MSGID_SGPE_PGPE_UPDATE_ACTIVE_CORES,
+ 0, 0);
+
+ rc = ipc_send_cmd(&G_sgpe_ipccmd_to_pgpe.cmd);
+
+ if (rc)
+ {
+ PK_TRACE_INF("ERROR: Entry Updates PGPE with Active Cores Failed. HALT SGPE!");
+ pk_halt();
+ }
+
+ // can poll right away since pgpe should ack right back
+ PK_TRACE_INF("SEIPC: Poll PGPE Update Active Cores Ack");
+
+ while (G_sgpe_ipcmsg_update_cores.fields.return_code == SGPE_IPC_RETURN_CODE_NULL);
+
+ if (G_sgpe_ipcmsg_update_cores.fields.return_code != SGPE_IPC_RETURN_CODE_ACK)
+ {
+ PK_TRACE_INF("ERROR: Entry Updates PGPE with Active Cores Bad RC. HALT SGPE!");
+ pk_halt();
+ }
+
+ G_sgpe_stop_record.group.core[VECTOR_ACTIVE] &=
+ ~(G_sgpe_stop_record.group.core[VECTOR_ENTRY]);
+ }
+
+ // Upon entry into STOP 11, right before stopping the clocks to the cache chiplet
+ // the SGPE must communicate to the PGPE to
+ // allow it to know which CME Quad Managers will no longer be active; and
+ // if WOF is enabled,
+ // to perform VRFT calculations to take advantage of the core/cache power.
+ // If Pstates are disabled, SGPE does nothing.
+ // If Pstates are enabled, the SGPE:
+ // 1. sends Suspend Pstates IPC to PGPE and waits for the response IPC .
+ // PGPE completes any current Pstate operations and responses to the Suspend Pstates IPC.
+ // 2. stops the clocks (and optionally finishes the entry)
+ // 3. sends Update Active Quads IPC to PGPE and waits for the response IPC.
+ // PGPE, as a side effect of processing the Update Active Quads IPC,
+ // will resume Pstate protocol operations.
+ // 4. optionally finishes the entry (if not done above)
+
+ if ((in32(OCB_OCCS2) & BIT32(PGPE_PSTATE_PROTOCOL_ACTIVE)) &&
+ G_sgpe_stop_record.group.quad[VECTOR_ENTRY]) // entry into STOP11
{
//===============================
MARK_TRAP(SE_STOP_SUSPEND_PSTATE)
//===============================
+
+ PK_TRACE_INF("SEIPC: Message PGPE to Suspend Pstate(stop11 and pstate enabled)");
+ G_sgpe_ipcmsg_suspend_pstate.fields.update_type = SGPE_IPC_UPDATE_TYPE_ENTRY;
+ G_sgpe_ipcmsg_suspend_pstate.fields.return_code = SGPE_IPC_RETURN_CODE_NULL;
+ G_sgpe_ipcmsg_suspend_pstate.fields.requested_quads =
+ (G_sgpe_stop_record.group.quad[VECTOR_ENTRY] >> SHIFT32(5));
+
+ G_sgpe_ipccmd_to_pgpe.cmd_data = &G_sgpe_ipcmsg_suspend_pstate;
+ ipc_init_msg(&G_sgpe_ipccmd_to_pgpe.cmd,
+ IPC_MSGID_SGPE_PGPE_SUSPEND_PSTATE,
+ 0, 0);
+
+ rc = ipc_send_cmd(&G_sgpe_ipccmd_to_pgpe.cmd);
+
+ if(rc)
+ {
+ PK_TRACE_INF("ERROR: Entry Suspend PGPE Pstate Function Failed. HALT SGPE!");
+ pk_halt();
+ }
+
+ /// @todo RTC166577
+ /// move poll below to before stop cache clocks when sgpe supports multicast
+ PK_TRACE_INF("SEIPC: Poll PGPE Suspend Pstate Ack");
+
+ while (G_sgpe_ipcmsg_suspend_pstate.fields.return_code == SGPE_IPC_RETURN_CODE_NULL);
+
+ if (G_sgpe_ipcmsg_suspend_pstate.fields.return_code != SGPE_IPC_RETURN_CODE_ACK)
+ {
+ PK_TRACE_INF("ERROR: Entry Suspend PGPE Pstate Function Bad RC. HALT SGPE!");
+ pk_halt();
+ }
+
+ G_sgpe_stop_record.group.quad[VECTOR_ACTIVE] &=
+ ~(G_sgpe_stop_record.group.quad[VECTOR_ENTRY]);
}
else if (!G_sgpe_stop_record.group.ex_b[VECTOR_ENTRY])
{
//============================
- MARK_TAG(SE_LESSTHAN8_WAIT, 0)
+ MARK_TAG(SE_LESSTHAN8_DONE, 0)
//============================
}
+#endif
+
// only stop 8 sets x_in
@@ -552,8 +668,6 @@ p9_sgpe_stop_entry()
if (ex & SND_EX_IN_QUAD)
GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG,
qloop, 1), 0);
-
- // TODO Notify PGPE to resume
}
}
@@ -578,6 +692,8 @@ p9_sgpe_stop_entry()
if (l3_purge_aborted)
{
PK_TRACE_INF("Abort: L3 Purge Aborted");
+ // For IPC reporting, taking aborted quad out of the list
+ G_sgpe_stop_record.group.quad[VECTOR_ENTRY] &= ~BIT32(qloop);
continue;
}
@@ -610,13 +726,14 @@ p9_sgpe_stop_entry()
MARK_TAG(SE_WAIT_PGPE_SUSPEND, (32 >> qloop))
//===========================================
- // TODO: Poll PGPE Suspend Ack
+ /// @todo RTC166577
+ /// IPC poll will move to here when multicast
//======================================
MARK_TAG(SE_QUIESCE_QUAD, (32 >> qloop))
//======================================
- // TODO halt cme here
+ /// @todo halt cme here
PK_TRACE("Assert refresh quiesce prior to L3 (refresh domain) stop clk via EX_DRAM_REF_REG[7]");
@@ -943,6 +1060,51 @@ p9_sgpe_stop_entry()
}
}
+#if !SKIP_IPC
+
+ /// @todo RTC166577
+ /// this block can be done as early as after stop cache clocks
+ /// when sgpe supports multicast
+ if((G_sgpe_stop_record.wof.update_pgpe & SGPE_IPC_UPDATE_QUAD_ENABLED) &&
+ G_sgpe_stop_record.group.quad[VECTOR_ENTRY])
+ {
+ PK_TRACE_INF("SEIPC: Send PGPE Resume with Active Quads Updated(0 if aborted)");
+ // Note: if all quads aborted on l3 purge, the list will be 0s;
+ G_sgpe_ipcmsg_update_quads.fields.requested_quads =
+ G_sgpe_stop_record.group.quad[VECTOR_ENTRY] >> SHIFT32(5);
+ }
+
+ G_sgpe_ipcmsg_update_quads.fields.update_type = SGPE_IPC_UPDATE_TYPE_ENTRY;
+ G_sgpe_ipcmsg_update_quads.fields.return_code = SGPE_IPC_RETURN_CODE_NULL;
+
+ G_sgpe_ipccmd_to_pgpe.cmd_data = &G_sgpe_ipcmsg_update_quads;
+ ipc_init_msg(&G_sgpe_ipccmd_to_pgpe.cmd,
+ IPC_MSGID_SGPE_PGPE_UPDATE_ACTIVE_QUADS,
+ 0, 0);
+
+ rc = ipc_send_cmd(&G_sgpe_ipccmd_to_pgpe.cmd);
+
+ if(rc)
+ {
+ pk_halt();
+ }
+
+ PK_TRACE_INF("SEIPC: Poll PGPE Update Active Quads Ack");
+
+ while (G_sgpe_ipcmsg_update_quads.fields.return_code == SGPE_IPC_RETURN_CODE_NULL);
+
+ if (G_sgpe_ipcmsg_update_quads.fields.return_code != SGPE_IPC_RETURN_CODE_ACK)
+ {
+ PK_TRACE_INF("ERROR: Entry Updates PGPE with Active Quads Bad RC. HALT SGPE!");
+ pk_halt();
+ }
+
+ G_sgpe_stop_record.group.quad[VECTOR_ACTIVE] &=
+ ~(G_sgpe_stop_record.group.quad[VECTOR_ENTRY]);
+
+#endif
+
+
//============================
MARK_TRAP(ENDSCOPE_STOP_ENTRY)
//============================
OpenPOWER on IntegriCloud