summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRahul Batra <rbatra@us.ibm.com>2016-11-18 17:10:30 -0600
committerJoshua Hunsberger <jahunsbe@us.ibm.com>2017-10-23 17:01:28 -0500
commit3ca9f1f8636f794d287e2cfef135f0a1bf31e55d (patch)
treee6aa15d99a6ed3194bea5220c0f8b9bccf57e5a2
parent7c134a664ecd90f6c5bb7353df5cf853ed27c925 (diff)
downloadtalos-hcode-3ca9f1f8636f794d287e2cfef135f0a1bf31e55d.tar.gz
talos-hcode-3ca9f1f8636f794d287e2cfef135f0a1bf31e55d.zip
WOF Enablement in PGPE
-Full functionality for OCC Start/Stop, Set PMCR, Clip Updt -New code structure for PGPE(actuate/process thread, etc) -Update CME code as per the new Doorbell0 -Added place holders for SGPE-PGPE IPCs -Place holders for Error Interrupts like OCB_Error, XSTOP -Added code to correctly account for VRM transition delays Change-Id: I301b14304677e2ed0130f1c3479d523dcb931293 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34156 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: ASHISH A. MORE <ashish.more@in.ibm.com> Reviewed-by: Gregory S. Still <stillgs@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
-rw-r--r--import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h153
-rw-r--r--import/chips/p9/common/pmlib/include/pstate_pgpe_occ_api.h31
-rw-r--r--import/chips/p9/common/pmlib/occlib/ipc_core.c2
-rw-r--r--import/chips/p9/procedures/hwp/lib/p9_pstates_pgpe.h22
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_intercme.c99
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.c406
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.h35
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c528
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_pmcr.c131
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/topfiles.mk10
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe.h18
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_boot_temp.c14
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c13
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h1
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.c3
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h2
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.c413
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.h51
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.c156
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.h36
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c147
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_main.c55
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c544
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h74
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c783
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c574
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pk_app_cfg.h30
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk5
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/topfiles.mk8
29 files changed, 3400 insertions, 944 deletions
diff --git a/import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h b/import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h
new file mode 100644
index 00000000..e3ab881d
--- /dev/null
+++ b/import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h
@@ -0,0 +1,153 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/common/pmlib/include/pstate_pgpe_cme_api.h $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PSTATE_PGPE_CME_API_H__
+#define __PSTATE_PGPE_CME_API_H__
+
+#define DPLL_REFCLK_DIVIDER 16667
+#define PIG_PAYLOAD_PS_PHASE1_MASK 0x03FF000000000000
+#define PIG_PAYLOAD_PS_PHASE2_MASK 0x000003FF00000000
+#define PIG_PAYLOAD_MASK 0x0fff000000000000
+#define PIG_INTR_FIELD_MASK 0x7000000000000000
+#define PIG_INTR_GRANTED_MASK 0x0000000080000000
+
+// Type1 specific defines
+#define PIG_PAYLOAD_PSTATE_MASK 0x03ff000000000000
+#define PIG_PAYLOAD_PSTATE_SEQ_INCR 0x0400000000000000 // Seq increment value
+
+// PIR defines
+#define PIR_INSTANCE_EVEN_ODD_MASK (uint32_t)(0x00000001)
+#define PIR_INSTANCE_NUM_MASK (uint32_t)(0x0000000F)
+
+//Bit0 WR: 0
+//Bit1 Multicast: 1
+//Bit 2:4 Multicast Type: 101
+//Bit 5:7 Mutlicast Grp: 001
+#define PCB_MUTLICAST_GRP1 0x69000000
+
+#define QUAD_FROM_CORE(c) \
+ ((c&0x1C) >> 2)
+
+#define QUAD_FROM_CME_INSTANCE_NUM(num) \
+ ((num&0xE) >> 1)
+
+//
+// CME<->PGPE API
+//
+enum MESSAGE_ID_DB0
+{
+ MSGID_DB0_INVALID = 0,
+ MSGID_DB0_RESERVED = 1,
+ MSGID_DB0_GLOBAL_ACTUAL_BROADCAST = 2,
+ MSGID_DB0_START_PSTATE_BROADCAST = 3,
+ MSGID_DB0_STOP_PSTATE_BROADCAST = 4
+};
+
+enum MESSAGEID_PCB_TYPE4_ACK_TYPES
+{
+ MSGID_PCB_TYPE4_ACK_ERROR = 0,
+ MSGID_PCB_TYPE4_ACK_PSTATE_PROTO_ACK = 1,
+ MSGID_PCB_TYPE4_ACK_PSTATE_SUSPENDED = 2,
+};
+
+
+//
+//PGPE-CME Doorbell0(Global Actual Broadcast)
+//
+typedef union pgpe_db0_glb_bcast_t
+{
+ uint64_t value;
+ struct
+ {
+#ifdef _BIG_ENDIAN
+ uint64_t msg_id : 8;
+ uint64_t global_actual : 8;
+ uint64_t quad0_ps: 8;
+ uint64_t quad1_ps: 8;
+ uint64_t quad2_ps: 8;
+ uint64_t quad3_ps: 8;
+ uint64_t quad4_ps: 8;
+ uint64_t quad5_ps: 8;
+#else
+ uint64_t quad5_ps: 8;
+ uint64_t quad4_ps: 8;
+ uint64_t quad3_ps: 8;
+ uint64_t quad2_ps: 8;
+ uint64_t quad1_ps: 8;
+ uint64_t quad0_ps: 8;
+ uint64_t global_actual : 8;
+ uint64_t msg_id : 8;
+#endif
+ } fields;
+} pgpe_db0_glb_bcast_t;
+
+//
+//PGPE-CME Doorbell0(Start Pstate Broaadcast)
+//
+typedef union pgpe_db0_start_ps_bcast
+{
+ uint64_t value;
+ struct
+ {
+#ifdef _BIG_ENDIAN
+ uint64_t msg_id : 8;
+ uint64_t global_actual : 8;
+ uint64_t quad0_ps : 8;
+ uint64_t quad1_ps : 8;
+ uint64_t quad2_ps : 8;
+ uint64_t quad3_ps : 8;
+ uint64_t quad4_ps : 8;
+ uint64_t quad5_ps : 8;
+#else
+ uint64_t quad5_ps : 8;
+ uint64_t quad4_ps : 8;
+ uint64_t quad3_ps : 8;
+ uint64_t quad2_ps : 8;
+ uint64_t quad1_ps : 8;
+ uint64_t quad0_ps : 8;
+ uint64_t global_actual : 8;
+ uint64_t msg_id : 8;
+#endif
+ } fields;
+} pgpe_db0_start_ps_bcast_t;
+
+//
+//PGPE-CME Doorbell0(Pstate Stop Broaadcast)
+//
+typedef union pgpe_db0_stop_ps_bcast
+{
+ uint64_t value;
+ struct
+ {
+#ifdef _BIG_ENDIAN
+ uint64_t msg_id : 8;
+ uint64_t reserved : 56;
+#else
+ uint64_t reserved : 56;
+ uint64_t msg_id : 8;
+#endif
+ } fields;
+} pgpe_db0_stop_ps_bcast_t;
+
+#endif //__PSTATE_PGPE_CME_API_H__
diff --git a/import/chips/p9/common/pmlib/include/pstate_pgpe_occ_api.h b/import/chips/p9/common/pmlib/include/pstate_pgpe_occ_api.h
index 32f10398..08850fed 100644
--- a/import/chips/p9/common/pmlib/include/pstate_pgpe_occ_api.h
+++ b/import/chips/p9/common/pmlib/include/pstate_pgpe_occ_api.h
@@ -41,9 +41,6 @@
extern "C" {
#endif
-// Maximum Number of Quads supported
-#define MAX_QUADS 6
-
//---------------
// IPC from 405
@@ -62,11 +59,19 @@ enum MESSAGE_ID_IPI2HI
//
// Return Codes
//
-#define PGPE_RC_SUCCESS 0x01
-#define PGPE_WOF_RC_NOT_ENABLED 0x10
+//\todo
+//Get feedback from Martha and Greg on these return codes
+//
+#define PGPE_RC_SUCCESS 0x01
+#define PGPE_WOF_RC_NOT_ENABLED 0x10
+#define PGPE_RC_PSTATES_DISABLED 0x11
+#define PGPE_RC_REQ_PSTATE_ALREADY_STARTED 0x12
+#define PGPE_RC_REQ_PSTATE_ALREADY_SUSPENDED 0x13
+#define PGPE_RC_OCC_NOT_PMCR_OWNER 0x14
// Active quad mismatch with requested active quads. PGPE did not switch
// to using the new VFRT. The original VFRT is still being used.
#define PGPE_WOF_RC_VFRT_QUAD_MISMATCH 0x20
+#define PGPE_RC_REQ_WHILE_PENDING_ACK 0x21
//
// PMCR Owner
@@ -74,7 +79,8 @@ enum MESSAGE_ID_IPI2HI
typedef enum
{
PMCR_OWNER_HOST = 0,
- PMCR_OWNER_OCC = 1
+ PMCR_OWNER_OCC = 1,
+ PMCR_OWNER_CHAR = 2
} PMCR_OWNER;
@@ -88,14 +94,14 @@ typedef struct ipcmsg_base
// Start Suspend Actions
//
#define PGPE_ACTION_PSTATE_START 0
-#define PGPE_ACTION_PSTATE_SUSPEND 1
+#define PGPE_ACTION_PSTATE_STOP 1
-typedef struct ipcmsg_start_suspend
+typedef struct ipcmsg_start_stop
{
ipcmsg_base_t msg_cb;
uint8_t action;
PMCR_OWNER pmcr_owner;
-} ipcmsg_start_suspend_t;
+} ipcmsg_start_stop_t;
typedef struct ipcmsg_clip_update
@@ -269,9 +275,9 @@ typedef union quad_state0
uint64_t quad1_pstate : 8; // Pstate of Quad 1; 0xFF indicates EQ is off
uint64_t quad2_pstate : 8; // Pstate of Quad 2; 0xFF indicates EQ is off
uint64_t quad3_pstate : 8; // Pstate of Quad 3; 0xFF indicates EQ is off
+ uint64_t core_poweron_state : 16; // bit vector: 0:core0, 1:core1, ..., 15:core15
uint64_t ivrm_state : 4; // ivrm state: bit vector 0:quad0, 1:quad1, 2:quad2, 3;quad3
uint64_t ivrm_state_rsvd : 4;
- uint64_t core_poweron_state : 16; // bit vector: 0:core0, 1:core1, ..., 15:core15
uint64_t external_vrm_setpoint : 8; // set point in mV
} fields;
} quad_state0_t;
@@ -288,12 +294,11 @@ typedef union quad_state1
{
uint64_t quad4_pstate : 8; // Pstate of Quad 4; 0xFF indicates EQ is off
uint64_t quad5_pstate : 8; // Pstate of Quad 5; 0xFF indicates EQ is off
- uint64_t requested_active_quad : 6; // Pstate of Quad 5; 0xFF indicates EQ is off
- uint64_t quad_pstate_rsvd : 10;
+ uint64_t reserved : 16;
uint64_t ivrm_state : 2; // ivrm state: bit vector 0:quad4, 1:quad5
uint64_t ivrm_state_rsvd : 6;
uint64_t core_poweron_state : 8; // bit vector: 0:core16, 1:core17, ..., 7:core23
- uint64_t core_poweron_state_rsvd : 8;
+ uint64_t requested_active_quad : 8;
uint64_t external_vrm_setpoint : 8; // set point in mV
} fields;
} quad_state1_t;
diff --git a/import/chips/p9/common/pmlib/occlib/ipc_core.c b/import/chips/p9/common/pmlib/occlib/ipc_core.c
index e6096932..65a8625a 100644
--- a/import/chips/p9/common/pmlib/occlib/ipc_core.c
+++ b/import/chips/p9/common/pmlib/occlib/ipc_core.c
@@ -355,8 +355,10 @@ void ipc_process_cbuf(uint32_t sender_id)
ipc_process_cbuf(sender_id);
}
+#ifndef UNIFIED_IRQ_HANDLER_GPE
// Unmask the irq before returning
KERN_IRQ_ENABLE(IPC_GET_IRQ(OCCHW_INST_ID_SELF));
+#endif
}
diff --git a/import/chips/p9/procedures/hwp/lib/p9_pstates_pgpe.h b/import/chips/p9/procedures/hwp/lib/p9_pstates_pgpe.h
index ea7fd0d1..789cdd17 100644
--- a/import/chips/p9/procedures/hwp/lib/p9_pstates_pgpe.h
+++ b/import/chips/p9/procedures/hwp/lib/p9_pstates_pgpe.h
@@ -218,13 +218,31 @@ typedef struct
/// Resonant Clock Grid Management Setup
ResonantClockingSetup resclk;
- //Voltage change step size
- uint32_t ext_vdd_step_size_mv;
+ //Time b/w ext VRM detects write voltage cmd and when voltage begins to move
+ uint32_t ext_vrm_transition_start_ns;
+ //Transition rate for an increasing VDD voltage excursion
+ uint32_t ext_vrm_transition_rate_inc_uv_per_us;
+
+ //Transition rate for an decreasing VDD voltage excursion
+ uint32_t ext_vrm_transition_rate_dec_uv_per_us;
+
+ //Delay to account for VDD rail setting
+ uint32_t ext_vrm_stabilization_time_us;
+
+ //External VRM transition step size
+ uint32_t ext_vrm_step_size_mv;
+
+ //Nest frequency in Mhz. This is used by FIT interrupt
uint32_t nest_frequency_mhz;
+ //Precalculated Pstate-Voltage Slopes
uint16_t PsVSlopes[VPD_NUM_SLOPES_SET][VPD_NUM_SLOPES_REGION];
+
+ //Precalculated Voltage-Pstates Slopes
uint16_t VPsSlopes[VPD_NUM_SLOPES_SET][VPD_NUM_SLOPES_REGION];
+
+
// @todo DPLL Droop Settings. These need communication to SGPE for STOP
} GlobalPstateParmBlock;
diff --git a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_intercme.c b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_intercme.c
new file mode 100644
index 00000000..45860434
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_intercme.c
@@ -0,0 +1,99 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_intercme.c $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "pk.h"
+#include "ppe42_scom.h"
+#include "cppm_register_addresses.h"
+#include "cppm_firmware_registers.h"
+#include "cme_register_addresses.h"
+#include "cmehw_common.h"
+#include "ppehw_common.h"
+
+#include "p9_cme_irq.h"
+#include "p9_cme_flags.h"
+#include "p9_cme_pstate.h"
+#include "pstate_pgpe_cme_api.h"
+#include "p9_pstate_vpd.h"
+#include "ppe42_cache.h"
+
+//
+//Globals
+//
+extern CmePstateRecord G_cme_pstate_record;
+
+//
+//InterCME_IN0 handler
+//
+void p9_cme_pstate_intercme_in0_handler(void* arg, PkIrqId irq)
+{
+ cppm_cmedb0_t dbData;
+ dbData.value = 0;
+ uint32_t localPS = 0;
+ uint32_t cme_flags = in32(CME_LCL_FLAGS);
+ uint64_t pmsrData = 0;
+ int32_t c = 0;
+ PkMachineContext ctx;
+
+ PK_TRACE("INTERCME_IN0: Enter\n");
+
+ for (c = 0; c < CORES_PER_EX; c++ )
+ {
+ if (cme_flags & (CME_FLAGS_CORE0_GOOD >> c))
+ {
+ if(dbData.fields.cme_message_number0 == MSGID_DB0_START_PSTATE_BROADCAST)
+ {
+ PK_TRACE("INTERCME_IN0: DB0 Start\n");
+ //Clear any pending PMCR interrupts
+ out32_sh(CME_LCL_EISR_CLR, BIT32(2) >> c);
+ out32_sh(CME_LCL_EIMR_CLR, BIT32(2) >> c);//Enable PMCR0/1
+ }
+ else if(dbData.fields.cme_message_number0 == MSGID_DB0_GLOBAL_ACTUAL_BROADCAST)
+ {
+ PK_TRACE("INTERCME_IN0: DB0 GlbBcast\n");
+ localPS = (dbData.value >>
+ ((MAX_QUADS - G_cme_pstate_record.quadNum - 1) << 8)) & 0xFF;
+ pmsrData = (dbData.value << 8) & 0xFF00000000000000;
+ pmsrData |= ((uint64_t)localPS << 48) & 0x00FF000000000000;
+ out64((CME_LCL_PMSRS0 + (c << 5)), pmsrData);
+ out32_sh(CME_LCL_EISR_CLR, BIT32(4) >> c);//Clear DB0_C0
+ }
+ else if(dbData.fields.cme_message_number0 == MSGID_DB0_STOP_PSTATE_BROADCAST)
+ {
+ PK_TRACE("INTERCME_IN0: DB0 Stop\n");
+ out32_sh(CME_LCL_EIMR_OR, BIT32(2) >> c);//Enable PMCR0/1
+ }
+ else
+ {
+ pk_halt();
+ }
+ }
+ }
+
+ out32(CME_LCL_ICCR_OR, BIT32(5));//Send Direct InterCME_IN0(Ack to QM-CME)
+ out32(CME_LCL_ICCR_CLR, BIT32(5));//Clear Ack
+ out32(CME_LCL_EISR_CLR, BIT32(7));//Clear InterCME_IN0
+
+ pk_irq_vec_restore(&ctx);
+ PK_TRACE("INTERCME_IN0: Exit\n");
+}
diff --git a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.c b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.c
index e963814c..e96fcb89 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.c
@@ -49,418 +49,12 @@
#include "ppehw_common.h"
#include "cmehw_common.h"
#include "cmehw_interrupts.h"
-
-#include "p9_cme_irq.h"
-#include "p9_cme_flags.h"
#include "p9_cme_pstate.h"
-#include "p9_pstate_common.h"
-#include "p9_pstate_vpd.h"
-#include "ppe42_cache.h"
//
//Globals
//
-extern CmePstateRecord G_cme_pstate_record;
-cme_pstate_db_data_t G_db_thread_data;
-cme_pstate_pmcr_data_t G_pmcr_thread_data;
-
-//\todo Use PState Parameter Block structures. RTC
-extern global_pstate_table_t G_gpst;
-extern freq_2_idx_entry_t G_freq2idx[NUM_FREQ_REGIONS];
-extern uint16_t G_cgm_table[CGM_TRANSITIONS];
-extern uint8_t G_resclkEnabled;
-
-//
-//Function Prototypes
-//
-void freq_update(uint64_t dbData);
-void resclk_update();
-int send_pig_packet(uint64_t data, uint32_t coreMask);
-
-//
-//PMCR Interrupt Handler
-//
-void p9_cme_pstate_pmcr_handler(void* arg, PkIrqId irq)
-{
- pk_semaphore_post((PkSemaphore*)arg);
-}
-
-//
-//Doorbell0 interrupt handler
-//
-//Only enabled on QuadManager-CME
-void p9_cme_pstate_db_handler(void* arg, PkIrqId irq)
-{
- pk_semaphore_post((PkSemaphore*)arg);
-}
-
-//
-//InterCME_IN0 handler
-//
-void p9_cme_pstate_intercme_in0_handler(void* arg, PkIrqId irq)
-{
- pgpe_db0_glb_bcast_t db0C0Data, db0C1Data;
- uint8_t localPS = 0;
- uint32_t cme_flags = in32(CME_LCL_FLAGS);
- uint64_t pmsrData;
- PkMachineContext ctx;
-
- //read DB0 for both cores and update PMSR
- if (cme_flags & CME_FLAGS_CORE0_GOOD)
- {
- CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C0, CME_SCOM_EQ, db0C0Data.value);
- localPS = (db0C0Data.value >>
- ((MAX_QUADS - G_db_thread_data.quadNum - 1) * 8)) & 0xFF;
- pmsrData = (db0C0Data.value << 8) & 0xFF00000000000000;
- pmsrData |= ((uint64_t)localPS << 48) & 0x00FF000000000000;
-
- out64(CME_LCL_PMSRS0, pmsrData);
- out32_sh(CME_LCL_EISR_CLR, BIT32(4));//Clear DB0_C0
- }
-
- if (cme_flags & CME_FLAGS_CORE1_GOOD)
- {
- CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C1, CME_SCOM_EQ, db0C1Data.value);
- localPS = (db0C1Data.value >>
- ((MAX_QUADS - G_db_thread_data.quadNum - 1) * 8)) & 0xFF;
- pmsrData = (db0C1Data.value << 8) & 0xFF00000000000000;
- pmsrData |= ((uint64_t)localPS << 48) & 0x00FF000000000000;
-
- out64(CME_LCL_PMSRS1, pmsrData);
- out32_sh(CME_LCL_EISR_CLR, BIT32(5));//Clear DB0_C1
- }
-
- out32(CME_LCL_ICCR_OR, BIT32(5));//Send Direct InterCME_IN0(Ack to QM-CME)
- out32(CME_LCL_ICCR_CLR, BIT32(5));//Clear Ack
- out32(CME_LCL_EISR_CLR, BIT32(7));//Clear InterCME_IN0
-
- pk_irq_vec_restore(&ctx);
-}
-
-//
-//p9_cme_pmcr_thread
-//
-void p9_cme_pstate_pmcr_thread(void* arg)
-{
- int32_t c;
- PkMachineContext ctx;
- cme_scom_pmcrs0_t pmcr[2];
- ppm_pig_t ppmPigData;
- uint32_t eisr;
- uint32_t coreMask[CORES_PER_EX];
- coreMask[0] = CME_MASK_C0;
- coreMask[1] = CME_MASK_C1;
-
- G_pmcr_thread_data.seqNum = 0;
-
- G_pmcr_thread_data.coreGood[0] = 0;
- G_pmcr_thread_data.coreGood[1] = 0;
- G_pmcr_thread_data.cmeFlags = in32(CME_LCL_FLAGS);
-
- if (G_pmcr_thread_data.cmeFlags & CME_FLAGS_CORE0_GOOD)
- {
- G_pmcr_thread_data.coreGood[0] = 1;
- out64(CME_LCL_EIMR_CLR, BIT64(34));//Enable PMCR0
- }
-
- if (G_pmcr_thread_data.cmeFlags & CME_FLAGS_CORE1_GOOD)
- {
- G_pmcr_thread_data.coreGood[1] = 1;
- out64(CME_LCL_EIMR_CLR, BIT64(35));//Enable PMCR1
- }
-
- pk_semaphore_create(&G_cme_pstate_record.sem[0], 0, 1);
-
- while(1)
- {
- //pend on sempahore
- pk_semaphore_pend(&G_cme_pstate_record.sem[0], PK_WAIT_FOREVER);
- wrteei(1);
-
- //Determine which core have pending request
- for(c = 0; c < CORES_PER_EX; c++)
- {
- if (G_pmcr_thread_data.coreGood[c])
- {
- eisr = in32_sh(CME_LCL_EISR); //EISR
-
- if (eisr & (BIT32(2) >> c))
- {
- //Clear interrupt and read PMCR
- out32_sh(CME_LCL_EISR_CLR, BIT32(2) >> c);
- pmcr[c].value = in64(CME_LCL_PMCRS0 + (c << 5));
-
- //Send Phase 1
- ppmPigData.value = 0;
- ppmPigData.fields.req_intr_type = 0;
- ppmPigData.value |= (((pmcr[c].value & PIG_PAYLOAD_PS_PHASE1_MASK)));
- ppmPigData.value |= ((G_pmcr_thread_data.seqNum & 0x6) << 57);
- send_pig_packet(ppmPigData.value, coreMask[c]);
- G_pmcr_thread_data.seqNum++;
-
- //Send Phase 2
- ppmPigData.value = 0;
- ppmPigData.fields.req_intr_type = 1;
- ppmPigData.value |= ((pmcr[c].value & PIG_PAYLOAD_PS_PHASE2_MASK) << 16);
- ppmPigData.value |= ((G_pmcr_thread_data.seqNum & 0x6) << 57);
- send_pig_packet(ppmPigData.value, coreMask[c]);
- G_pmcr_thread_data.seqNum++;
- }
- }
- }
-
- pk_irq_vec_restore(&ctx);
- }
-}
-
-//
-//p9_cme_db_thread
-//
-void p9_cme_pstate_db_thread(void* arg)
-{
- uint32_t cme_flags;
- PkMachineContext ctx;
- //int rc = 0;
- cppm_cmedb0_t dbData;
- uint8_t intercme_acked;
- uint64_t eisr, pmsrData;
- ppm_pig_t ppmPigData;
- uint32_t pir;
- uint8_t localPS;
-
- //\todo Read the data from HOMER code. RTC
- p9_pstate_vpd_init();
-
- //Read CME_LCL_FLAGS
- cme_flags = in32(CME_LCL_FLAGS);
-
- //Determine quad number and exID for this CME
- asm volatile ("mfpir %[data] \n" : [data]"=r"(pir) );
-
- //We found a bug in HW late, so this is a workaround. However, in SIMICS the model
- //is as per original spec.
-#if !SIMICS_TUNING
- G_db_thread_data.quadNum = (pir & PIR_INSTANCE_NUM_MASK);
-#else
- G_db_thread_data.quadNum = QUAD_FROM_CME_INSTANCE_NUM((pir & PIR_INSTANCE_NUM_MASK));
-#endif
-
- if (cme_flags & CME_FLAGS_QMGR_MASTER)
- {
- G_db_thread_data.qmFlag = 1;
-
- if (cme_flags & CME_FLAGS_SIBLING_FUNCTIONAL)
- {
- G_db_thread_data.siblingCMEFlag = 1;
- }
- else
- {
- G_db_thread_data.siblingCMEFlag = 0;
- }
- }
- else
- {
- G_db_thread_data.qmFlag = 0;
- G_db_thread_data.siblingCMEFlag = 0;
- }
-
- //if quadManager
- if (G_db_thread_data.qmFlag)
- {
- if (cme_flags & CME_FLAGS_CORE0_GOOD)
- {
- out32_sh(CME_LCL_EIMR_CLR, BIT32(4));//Enable DB0_0
- out32_sh(CME_LCL_EIMR_OR, BIT32(5));//Disable DB0_1
- g_eimr_override |= BIT64(37);
- G_db_thread_data.cmeMaskGoodCore = CME_MASK_C0;
- }
- else if (cme_flags & CME_FLAGS_CORE1_GOOD)
- {
- out32_sh(CME_LCL_EIMR_OR, BIT32(4));//Disable DB0_0
- out32_sh(CME_LCL_EIMR_CLR, BIT32(5));//Enable DB0_1
- g_eimr_override |= BIT64(36);
- G_db_thread_data.cmeMaskGoodCore = CME_MASK_C1;
- }
-
- out64(CME_LCL_EIMR_OR, BIT64(7));//Disable InterCME_IN0
- g_eimr_override |= BIT64(7);
-
- G_db_thread_data.dpll_pstate0_value = G_gpst.pstate0_frequency_khz / G_gpst.frequency_step_khz;
- }
- else
- {
- out64(CME_LCL_EIMR_OR, BIT64(36) | BIT64(37));//Disable DB0_0 and DB0_1
- out64(CME_LCL_EIMR_CLR, BIT64(7)); //Enable InterCME_IN0
- g_eimr_override |= BIT64(37);
- g_eimr_override |= BIT64(36);
- }
-
-
- //\todo (RTC) Set intial GlobalPS, LocalPS, resClkIdx, etc.
- //Most likely will come from SGPE. Need to know precisely
-
- //Only Quad Manager CME executes. The sibling CME
- //has intercme_in0 enabled
- if (G_db_thread_data.qmFlag)
- {
- pk_semaphore_create(&G_cme_pstate_record.sem[1], 0, 1);
-
- while(1)
- {
- //pend on sempahore
- pk_semaphore_pend(&G_cme_pstate_record.sem[1], PK_WAIT_FOREVER);
- wrteei(1);
-
- if (cme_flags & CME_FLAGS_CORE0_GOOD)
- {
- out32_sh(CME_LCL_EISR_CLR, BIT32(4));
- out32_sh(CME_LCL_EISR_CLR, BIT32(5));
- CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C0, CME_SCOM_EQ, dbData.value);
- }
- else if (cme_flags & CME_FLAGS_CORE1_GOOD)
- {
- out32_sh(CME_LCL_EISR_CLR, BIT32(5));
- CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C1, CME_SCOM_EQ, dbData.value);
- }
-
- //Update analog
- if (G_resclkEnabled)
- {
- resclk_update();
- }
-
-#if !SIMICS_TUNING
- freq_update(dbData.value);
-#endif
-
- //Notify sibling CME(if any)
- if (G_db_thread_data.siblingCMEFlag == 1)
- {
- //Send interCME interrupt
- out32(CME_LCL_ICCR_OR, BIT32(5)); //Send direct InterCME_IN0
- out32(CME_LCL_ICCR_CLR, BIT32(5));//Clear
-
-#if !SIMICS_TUNING
- //poll on interCME interrupt
- intercme_acked = 0;
-#else
- intercme_acked = 1;
-#endif
-
- while (!intercme_acked)
- {
- eisr = in64(CME_LCL_EISR);
-
- if (eisr & 0x0100000000000000)
- {
- intercme_acked = 1;
- }
- }
-
- out32(CME_LCL_EISR_CLR, BIT32(7));//Clear InterCME_IN0
- }
-
- //Update PMSR
- localPS = (dbData.value >>
- ((MAX_QUADS - G_db_thread_data.quadNum - 1) * 8)) & 0xFF;
- pmsrData = (dbData.value << 8) & 0xFF00000000000000;
- pmsrData |= ((uint64_t)localPS << 48) & 0x00FF000000000000;
-
- if (cme_flags & CME_FLAGS_CORE0_GOOD)
- {
- out64(CME_LCL_PMSRS0, pmsrData);
- }
-
- if (cme_flags & CME_FLAGS_CORE1_GOOD)
- {
- out64(CME_LCL_PMSRS1, pmsrData);
- }
-
- //Send type4(ack doorbell)
- ppmPigData.value = 0;
- ppmPigData.fields.req_intr_type = 4;
- ppmPigData.fields.req_intr_payload = 0;
- send_pig_packet(ppmPigData.value, G_db_thread_data.cmeMaskGoodCore);
-
- pk_irq_vec_restore(&ctx);
- }
- }
-}
-
-//
-//freq_update
-//
-void freq_update(uint64_t dbData)
-{
- uint8_t localPS = (dbData >>
- ((MAX_QUADS - G_db_thread_data.quadNum - 1) * 8)) & 0xFF;
-
- //Adjust DPLL
- cppm_ippmcmd_t cppm_ippmcmd;
- qppm_dpll_freq_t dpllFreq;
-
- //Write new value of DPLL using INTERPPM
- dpllFreq.value = 0;
- dpllFreq.fields.fmax = (uint16_t)(G_db_thread_data.dpll_pstate0_value - localPS) << 3;
- dpllFreq.fields.fmult = (uint16_t)(G_db_thread_data.dpll_pstate0_value - localPS) << 3;
- dpllFreq.fields.fmin = (uint16_t)(G_db_thread_data.dpll_pstate0_value - localPS) << 3;
- CME_PUTSCOM(CPPM_IPPMWDATA, G_db_thread_data.cmeMaskGoodCore, dpllFreq.value);
- cppm_ippmcmd.value = 0;
- cppm_ippmcmd.fields.qppm_reg = QPPM_DPLL_FREQ & 0x000000ff;
- cppm_ippmcmd.fields.qppm_rnw = 0;
- CME_PUTSCOM(CPPM_IPPMCMD, G_db_thread_data.cmeMaskGoodCore, cppm_ippmcmd.value);
-}
-
-//
-//resclk_update
-//
-void resclk_update()
-{
- uint64_t val;
- uint8_t tidx, step;
- int32_t i;
-
- //get targetIndex from Table1(ControlIndex) by indexing with localPState
- tidx = G_db_thread_data.resClkTblIdx;
-
- for (i = NUM_FREQ_REGIONS - 1; i >= 0; i--)
- {
- if (G_freq2idx[i].pstate > G_db_thread_data.localPS)
- {
- tidx = i;
- break;
- }
- }
-
- //walk Table2[Resonant Grids Control Data)
- if (tidx > G_db_thread_data.resClkTblIdx)
- {
- step = 1;
- }
- else
- {
- step = -1;
- }
-
- while(G_db_thread_data.resClkTblIdx != tidx)
- {
- G_db_thread_data.resClkTblIdx += step;
- val = (uint64_t)(G_cgm_table[G_db_thread_data.resClkTblIdx]) << 48;
- val |= G_db_thread_data.qaccr21_23InitVal;
-
-#if !SIMICS_TUNING
- //int rc = 0;
- cppm_ippmcmd_t cppm_ippmcmd;
- //Write val to QACCR
- CME_PUTSCOM(CPPM_IPPMWDATA, G_db_thread_data.cmeMaskGoodCore, val);
- cppm_ippmcmd.value = 0;
- cppm_ippmcmd.fields.qppm_reg = QPPM_QACCR & 0x000000ff;
- cppm_ippmcmd.fields.qppm_rnw = 0;
- CME_PUTSCOM(CPPM_IPPMCMD, G_db_thread_data.cmeMaskGoodCore, cppm_ippmcmd.value);
-#endif
- }
-}
//
//send_pig_packet
diff --git a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.h b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.h
index 57313ebc..5ed3c178 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.h
+++ b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.h
@@ -32,38 +32,51 @@
/// \brief Shared and global definitions for pstate H codes.
/// \owner Rahul Batra Email: rbatra@us.ibm.com
///
+#ifndef _P9_CME_PSTATE_H_
+#define _P9_CME_PSTATE_H_
#include "pk.h"
-#include "p9_pstate_common.h"
+#include "pstate_pgpe_cme_api.h"
#include "gpehw_common.h"
+enum PMCR_CONTROL
+{
+ PMCR0_DISABLE = 0x1,
+ PMCR1_DISABLE = 0x2,
+ PMCR0_ENABLE = 0x4,
+ PMCR1_ENABLE = 0x8
+};
+
void p9_cme_pstate_pmcr_thread(void*);
void p9_cme_pstate_db_thread(void*);
void p9_cme_pstate_pmcr_handler(void*, PkIrqId);
void p9_cme_pstate_db_handler(void*, PkIrqId);
void p9_cme_pstate_intercme_in0_handler(void*, PkIrqId);
+int send_pig_packet(uint64_t data, uint32_t coreMask);
+
typedef struct
{
PkSemaphore sem[2];
+ uint32_t quadNum;
+ uint32_t pstatesEnabled;
} CmePstateRecord;
typedef struct
{
uint64_t seqNum;
- uint32_t cmeFlags;
- uint8_t coreGood[CORES_PER_EX];
} cme_pstate_pmcr_data_t;
typedef struct
{
- uint8_t qmFlag;
- uint8_t siblingCMEFlag;
+ uint32_t qmFlag;
+ uint32_t siblingCMEFlag;
uint32_t cmeMaskGoodCore;
- uint8_t globalPS; //\todo use PState as type
- uint8_t localPS; //\todo use PState as type
- uint8_t resClkTblIdx;
- uint8_t qaccr21_23InitVal;
- uint8_t quadNum;
- uint8_t dpll_pstate0_value;
+ uint32_t globalPS;
+ uint32_t localPS;
+ uint32_t resClkTblIdx;
+ uint32_t qaccr21_23InitVal;
+ uint32_t dpll_pstate0_value;
} cme_pstate_db_data_t;
+
+#endif //_P9_CME_PSTATE_H_
diff --git a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c
new file mode 100644
index 00000000..f26e5ef0
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c
@@ -0,0 +1,528 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "pk.h"
+#include "ppe42_scom.h"
+
+#include "cme_firmware_registers.h"
+#include "cme_register_addresses.h"
+#include "cppm_firmware_registers.h"
+#include "cppm_register_addresses.h"
+#include "ppm_firmware_registers.h"
+#include "ppm_register_addresses.h"
+#include "qppm_firmware_registers.h"
+#include "qppm_register_addresses.h"
+
+#include "ppehw_common.h"
+#include "cmehw_common.h"
+#include "cmehw_interrupts.h"
+
+#include "p9_cme_irq.h"
+#include "p9_cme_flags.h"
+#include "p9_cme_pstate.h"
+#include "p9_cme_header.h"
+#include "pstate_pgpe_cme_api.h"
+#include "p9_pstate_vpd.h"
+#include "ppe42_cache.h"
+
+
+//
+//Globals
+//
+extern CmePstateRecord G_cme_pstate_record;
+cme_pstate_db_data_t G_db_thread_data;
+
+//\todo Use PState Parameter Block structures. RTC
+extern global_pstate_table_t G_gpst;
+extern freq_2_idx_entry_t G_freq2idx[NUM_FREQ_REGIONS];
+extern uint16_t G_cgm_table[CGM_TRANSITIONS];
+extern uint8_t G_resclkEnabled;
+extern cme_header_t* G_cme_header;
+
+//
+//Function Prototypes
+//
+inline void p9_cme_pstate_process_db0();
+inline void p9_cme_pstate_db0_start(cppm_cmedb0_t dbData, uint32_t cme_flags);
+inline void p9_cme_pstate_db0_glb_bcast(cppm_cmedb0_t dbData, uint32_t cme_flags);
+inline void p9_cme_pstate_db0_suspend(cppm_cmedb0_t dbData, uint32_t cme_flags);
+inline void p9_cme_pstate_freq_update(uint64_t dbData);
+inline void p9_cme_pstate_resclk_update();
+
+//
+//Doorbell0 interrupt handler
+//
+//Only enabled on QuadManager-CME
+void p9_cme_pstate_db_handler(void* arg, PkIrqId irq)
+{
+ pk_semaphore_post((PkSemaphore*)arg);
+}
+
+//
+//p9_cme_db_thread
+//
+void p9_cme_pstate_db_thread(void* arg)
+{
+ PK_TRACE("DB_TH: Started\n");
+ uint32_t cme_flags;
+ PkMachineContext ctx;
+ uint32_t pir;
+
+ //\todo Read the data from HOMER code. RTC
+ p9_pstate_vpd_init();
+
+ //Read CME_LCL_FLAGS
+ cme_flags = in32(CME_LCL_FLAGS);
+
+ //Determine quad number and exID for this CME
+ asm volatile ("mfpir %[data] \n" : [data]"=r"(pir) );
+
+ //We found a bug in HW late, so this is a workaround. However, in SIMICS the model
+ //is as per original spec.
+#if !SIMICS_TUNING
+ G_cme_pstate_record.quadNum = (pir & PIR_INSTANCE_NUM_MASK);
+#else
+ G_cme_pstate_record.quadNum = QUAD_FROM_CME_INSTANCE_NUM((pir & PIR_INSTANCE_NUM_MASK));
+#endif
+
+ if (cme_flags & CME_FLAGS_QMGR_MASTER)
+ {
+ G_db_thread_data.qmFlag = 1;
+
+ if (cme_flags & CME_FLAGS_SIBLING_FUNCTIONAL)
+ {
+ G_db_thread_data.siblingCMEFlag = 1;
+ }
+ else
+ {
+ G_db_thread_data.siblingCMEFlag = 0;
+ }
+ }
+ else
+ {
+ G_db_thread_data.qmFlag = 0;
+ G_db_thread_data.siblingCMEFlag = 0;
+ }
+
+ //if quadManager
+ if (G_db_thread_data.qmFlag)
+ {
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
+ {
+ out32_sh(CME_LCL_EIMR_CLR, BIT32(4));//Enable DB0_0
+ out32_sh(CME_LCL_EIMR_OR, BIT32(5));//Disable DB0_1
+ g_eimr_override |= BIT64(37);
+ G_db_thread_data.cmeMaskGoodCore = CME_MASK_C0;
+ }
+ else if (cme_flags & CME_FLAGS_CORE1_GOOD)
+ {
+ out32_sh(CME_LCL_EIMR_OR, BIT32(4));//Disable DB0_0
+ out32_sh(CME_LCL_EIMR_CLR, BIT32(5));//Enable DB0_1
+ g_eimr_override |= BIT64(36);
+ G_db_thread_data.cmeMaskGoodCore = CME_MASK_C1;
+ }
+
+ out64(CME_LCL_EIMR_OR, BIT64(7));//Disable InterCME_IN0
+ g_eimr_override |= BIT64(7);
+
+ G_db_thread_data.dpll_pstate0_value = G_gpst.pstate0_frequency_khz / G_gpst.frequency_step_khz;
+ }
+ else
+ {
+ out64(CME_LCL_EIMR_OR, BIT64(36) | BIT64(37));//Disable DB0_0 and DB0_1
+ out64(CME_LCL_EIMR_CLR, BIT64(7)); //Enable InterCME_IN0
+ g_eimr_override |= BIT64(37);
+ g_eimr_override |= BIT64(36);
+ }
+
+ //Only Quad Manager CME executes this. The sibling CME
+ //has intercme_in0 enabled
+ if (G_db_thread_data.qmFlag)
+ {
+ pk_semaphore_create(&G_cme_pstate_record.sem[1], 0, 1);
+
+ PK_TRACE("DB_TH: Inited\n");
+
+ while(1)
+ {
+ //pend on sempahore
+ pk_semaphore_pend(&G_cme_pstate_record.sem[1], PK_WAIT_FOREVER);
+ wrteei(1);
+
+ p9_cme_pstate_process_db0();
+
+ pk_irq_vec_restore(&ctx);
+ }
+ }
+
+ PK_TRACE("DB_TH: Exit\n");
+}
+
+//
+//Process Doorbell0
+//
+inline void p9_cme_pstate_process_db0()
+{
+ cppm_cmedb0_t dbData;
+ uint32_t cme_flags = in32(CME_LCL_FLAGS);
+
+ PK_TRACE("DB_TH: Process DB0 Enter\n");
+
+ //Read DB0 value
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
+ {
+ out32_sh(CME_LCL_EISR_CLR, BIT32(4));
+ out32_sh(CME_LCL_EISR_CLR, BIT32(5));
+ CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C0, CME_SCOM_EQ, dbData.value);
+ }
+ else if (cme_flags & CME_FLAGS_CORE1_GOOD)
+ {
+ out32_sh(CME_LCL_EISR_CLR, BIT32(5));
+ CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C1, CME_SCOM_EQ, dbData.value);
+ }
+
+ PK_TRACE("DB_TH: DB0 0x%x\n"dbData.value);
+
+ if(dbData.fields.cme_message_number0 == MSGID_DB0_START_PSTATE_BROADCAST)
+ {
+ p9_cme_pstate_db0_start(dbData, cme_flags);
+ }
+ else if(dbData.fields.cme_message_number0 == MSGID_DB0_GLOBAL_ACTUAL_BROADCAST)
+ {
+ p9_cme_pstate_db0_glb_bcast(dbData, cme_flags);
+ }
+ else if(dbData.fields.cme_message_number0 == MSGID_DB0_STOP_PSTATE_BROADCAST)
+ {
+ p9_cme_pstate_db0_suspend(dbData, cme_flags);
+ }
+ else
+ {
+ pk_halt();
+ }
+
+ PK_TRACE("DB_TH: Process DB0 Exit\n");
+}
+
+//
+//Doorbell0 Start
+//
+inline void p9_cme_pstate_db0_start(cppm_cmedb0_t dbData, uint32_t cme_flags)
+{
+ PK_TRACE("DB_TH: DB0 Start Enter\n");
+ uint32_t intercme_acked;
+ uint64_t eisr, pmsrData;
+ uint8_t localPS;
+ ppm_pig_t ppmPigData;
+
+ if (G_cme_pstate_record.pstatesEnabled == 1)
+ {
+ //Send type4(ack doorbell)
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 4;
+ ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_ERROR;
+ send_pig_packet(ppmPigData.value, G_db_thread_data.cmeMaskGoodCore);
+ PK_TRACE("DB_TH: DB0 Start while already started\n");
+ pk_halt();
+ }
+
+ //\TODO RTC: 152965
+ //Check operable bits
+ //Check if resonant clkss are either all 0s or "OFF" encode(from the Parm)
+ //Check for iVRM disable
+ //Check for VDM disable
+
+ //Pstate Update
+#if !SIMICS_TUNING
+ p9_cme_pstate_freq_update(dbData.value);
+#endif
+
+ //Notify sibling CME(if any)
+ if (G_db_thread_data.siblingCMEFlag == 1)
+ {
+ //Send interCME interrupt
+ out32(CME_LCL_ICCR_OR, BIT32(5)); //Send direct InterCME_IN0
+ out32(CME_LCL_ICCR_CLR, BIT32(5));//Clear
+
+#if !SIMICS_TUNING
+ //poll on interCME interrupt
+ intercme_acked = 0;
+#else
+ intercme_acked = 1;
+#endif
+
+ while (!intercme_acked)
+ {
+ eisr = in64(CME_LCL_EISR);
+
+ if (eisr & 0x0100000000000000)
+ {
+ intercme_acked = 1;
+ }
+ }
+
+ out32(CME_LCL_EISR_CLR, BIT32(7));//Clear InterCME_IN0
+ }
+
+ //Update PMSR
+ localPS = (dbData.value >>
+ ((MAX_QUADS - G_cme_pstate_record.quadNum - 1) * 8)) & 0xFF;
+ pmsrData = (dbData.value << 8) & 0xFF00000000000000;
+ pmsrData |= ((uint64_t)localPS << 48) & 0x00FF000000000000;
+
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
+ {
+ out64(CME_LCL_PMSRS0, pmsrData);
+ }
+
+ if (cme_flags & CME_FLAGS_CORE1_GOOD)
+ {
+ out64(CME_LCL_PMSRS1, pmsrData);
+ }
+
+ //\TODO RTC: 152965
+ //Enable Resonant Clks if flag
+ //Enable ivrm if flag
+ //Enable vdm if flag
+
+ G_cme_pstate_record.pstatesEnabled = 1;
+
+ //Send type4(ack doorbell)
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 4;
+ ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_PSTATE_PROTO_ACK;
+ send_pig_packet(ppmPigData.value, G_db_thread_data.cmeMaskGoodCore);
+
+ //Clear Pending PMCR interrupts and Enable PMCR Interrupts
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
+ {
+ out32_sh(CME_LCL_EISR_CLR, BIT32(2));
+ out64(CME_LCL_EIMR_CLR, BIT64(34));//Enable PMCR0
+ }
+
+ if (cme_flags & CME_FLAGS_CORE1_GOOD)
+ {
+ out32_sh(CME_LCL_EISR_CLR, BIT32(3));
+ out64(CME_LCL_EIMR_CLR, BIT64(35));//Enable PMCR1
+ }
+
+ PK_TRACE("DB_TH: DB0 Start Exit\n");
+}
+
+//
+//Doorbell0 Global Broadcast
+//
+inline void p9_cme_pstate_db0_glb_bcast(cppm_cmedb0_t dbData, uint32_t cme_flags)
+{
+ PK_TRACE("DB_TH: DB0 GlbBcast Enter\n");
+ uint32_t intercme_acked;
+ uint64_t eisr, pmsrData;
+ uint8_t localPS;
+ ppm_pig_t ppmPigData;
+
+ if (G_cme_pstate_record.pstatesEnabled == 0)
+ {
+ //Send type4(ack doorbell)
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 4;
+ ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_ERROR;
+ send_pig_packet(ppmPigData.value, G_db_thread_data.cmeMaskGoodCore);
+ PK_TRACE("DB_TH: DB0Bcast while PS disabled\n");
+ pk_halt();
+ }
+
+ //Update analog
+ if (G_resclkEnabled)
+ {
+ p9_cme_pstate_resclk_update();
+ }
+
+#if !SIMICS_TUNING
+ p9_cme_pstate_freq_update(dbData.value);
+#endif
+
+ //Notify sibling CME(if any)
+ if (G_db_thread_data.siblingCMEFlag == 1)
+ {
+ //Send interCME interrupt
+ out32(CME_LCL_ICCR_OR, BIT32(5)); //Send direct InterCME_IN0
+ out32(CME_LCL_ICCR_CLR, BIT32(5));//Clear
+
+#if !SIMICS_TUNING
+ //poll on interCME interrupt
+ intercme_acked = 0;
+#else
+ intercme_acked = 1;
+#endif
+
+ while (!intercme_acked)
+ {
+ eisr = in64(CME_LCL_EISR);
+
+ if (eisr & 0x0100000000000000)
+ {
+ intercme_acked = 1;
+ }
+ }
+
+ out32(CME_LCL_EISR_CLR, BIT32(7));//Clear InterCME_IN0
+ }
+
+ //Update PMSR
+ localPS = (dbData.value >>
+ ((MAX_QUADS - G_cme_pstate_record.quadNum - 1) * 8)) & 0xFF;
+ pmsrData = (dbData.value << 8) & 0xFF00000000000000;
+ pmsrData |= ((uint64_t)localPS << 48) & 0x00FF000000000000;
+
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
+ {
+ out64(CME_LCL_PMSRS0, pmsrData);
+ }
+
+ if (cme_flags & CME_FLAGS_CORE1_GOOD)
+ {
+ out64(CME_LCL_PMSRS1, pmsrData);
+ }
+
+ //Send type4(ack doorbell)
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 4;
+ ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_PSTATE_PROTO_ACK;
+ send_pig_packet(ppmPigData.value, G_db_thread_data.cmeMaskGoodCore);
+ PK_TRACE("DB_TH: DB0 GlbBcast Exit\n");
+}
+
+//
+//Doorbell0 Suspend
+//
+inline void p9_cme_pstate_db0_suspend(cppm_cmedb0_t dbData, uint32_t cme_flags)
+{
+ PK_TRACE("DB_TH: DB0 Suspend Enter\n");
+ ppm_pig_t ppmPigData;
+
+ if (G_cme_pstate_record.pstatesEnabled == 0)
+ {
+ //Send type4(ack doorbell)
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 4;
+ ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_ERROR;
+ send_pig_packet(ppmPigData.value, G_db_thread_data.cmeMaskGoodCore);
+ pk_halt();
+ }
+
+ G_cme_pstate_record.pstatesEnabled = 0;
+
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
+ {
+ out64(CME_LCL_EIMR_OR, BIT64(34));//Disable PMCR0
+ }
+
+ if (cme_flags & CME_FLAGS_CORE1_GOOD)
+ {
+ out64(CME_LCL_EIMR_OR, BIT64(35));//Disable PMCR1
+ }
+
+ //\TODO RTC: 152965
+ //Disable iVRM, move into bypass
+ //Disable resonant clocking, move to non-resonant value
+
+ //Send type4(ack doorbell)
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 4;
+ ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_PSTATE_SUSPENDED;
+ send_pig_packet(ppmPigData.value, G_db_thread_data.cmeMaskGoodCore);
+ PK_TRACE("DB_TH: DB0 Suspend Exit\n");
+}
+
+//
+//p9_cme_pstate_freq_update
+//
+inline void p9_cme_pstate_freq_update(uint64_t dbData)
+{
+ uint8_t localPS = (dbData >>
+ ((MAX_QUADS - G_cme_pstate_record.quadNum - 1) * 8)) & 0xFF;
+
+ //Adjust DPLL
+ cppm_ippmcmd_t cppm_ippmcmd;
+ qppm_dpll_freq_t dpllFreq;
+
+ //Write new value of DPLL using INTERPPM
+ dpllFreq.value = 0;
+ dpllFreq.fields.fmax = (uint16_t)(G_db_thread_data.dpll_pstate0_value - localPS) << 3;
+ dpllFreq.fields.fmult = (uint16_t)(G_db_thread_data.dpll_pstate0_value - localPS) << 3;
+ dpllFreq.fields.fmin = (uint16_t)(G_db_thread_data.dpll_pstate0_value - localPS) << 3;
+ CME_PUTSCOM(CPPM_IPPMWDATA, G_db_thread_data.cmeMaskGoodCore, dpllFreq.value);
+ cppm_ippmcmd.value = 0;
+ cppm_ippmcmd.fields.qppm_reg = QPPM_DPLL_FREQ & 0x000000ff;
+ cppm_ippmcmd.fields.qppm_rnw = 0;
+ CME_PUTSCOM(CPPM_IPPMCMD, G_db_thread_data.cmeMaskGoodCore, cppm_ippmcmd.value);
+}
+
+//
+//p9_cme_pstate_resclk_update
+//
+inline void p9_cme_pstate_resclk_update()
+{
+ uint64_t val;
+ uint8_t tidx, step;
+ int32_t i;
+
+ //get targetIndex from Table1(ControlIndex) by indexing with localPState
+ tidx = G_db_thread_data.resClkTblIdx;
+
+ for (i = NUM_FREQ_REGIONS - 1; i >= 0; i--)
+ {
+ if (G_freq2idx[i].pstate > G_db_thread_data.localPS)
+ {
+ tidx = i;
+ break;
+ }
+ }
+
+ //walk Table2[Resonant Grids Control Data)
+ if (tidx > G_db_thread_data.resClkTblIdx)
+ {
+ step = 1;
+ }
+ else
+ {
+ step = -1;
+ }
+
+ while(G_db_thread_data.resClkTblIdx != tidx)
+ {
+ G_db_thread_data.resClkTblIdx += step;
+ val = (uint64_t)(G_cgm_table[G_db_thread_data.resClkTblIdx]) << 48;
+ val |= G_db_thread_data.qaccr21_23InitVal;
+
+#if !SIMICS_TUNING
+ cppm_ippmcmd_t cppm_ippmcmd;
+ //Write val to QACCR
+ CME_PUTSCOM(CPPM_IPPMWDATA, G_db_thread_data.cmeMaskGoodCore, val);
+ cppm_ippmcmd.value = 0;
+ cppm_ippmcmd.fields.qppm_reg = QPPM_QACCR & 0x000000ff;
+ cppm_ippmcmd.fields.qppm_rnw = 0;
+ CME_PUTSCOM(CPPM_IPPMCMD, G_db_thread_data.cmeMaskGoodCore, cppm_ippmcmd.value);
+#endif
+ }
+}
diff --git a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_pmcr.c b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_pmcr.c
new file mode 100644
index 00000000..eeec7fad
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_pmcr.c
@@ -0,0 +1,131 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_pmcr.c $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "pk.h"
+#include "ppe42_scom.h"
+
+#include "cme_firmware_registers.h"
+#include "cme_register_addresses.h"
+#include "cppm_firmware_registers.h"
+#include "cppm_register_addresses.h"
+#include "ppm_firmware_registers.h"
+#include "ppm_register_addresses.h"
+#include "qppm_firmware_registers.h"
+#include "qppm_register_addresses.h"
+
+#include "ppehw_common.h"
+#include "cmehw_common.h"
+#include "cmehw_interrupts.h"
+
+#include "p9_cme_irq.h"
+#include "p9_cme_flags.h"
+#include "p9_cme_pstate.h"
+#include "p9_cme_header.h"
+#include "pstate_pgpe_cme_api.h"
+#include "p9_pstate_vpd.h"
+#include "ppe42_cache.h"
+
+//
+//Globals
+//
+cme_pstate_pmcr_data_t G_pmcr_thread_data;
+extern CmePstateRecord G_cme_pstate_record;
+
+//
+//PMCR Interrupt Handler
+//
+void p9_cme_pstate_pmcr_handler(void* arg, PkIrqId irq)
+{
+ pk_semaphore_post((PkSemaphore*)arg);
+}
+
+//
+//p9_cme_pmcr_thread
+//
+void p9_cme_pstate_pmcr_thread(void* arg)
+{
+ PK_TRACE("PMCR_TH: Enter\n");
+ int32_t c;
+ PkMachineContext ctx;
+ cme_scom_pmcrs0_t pmcr[2];
+ ppm_pig_t ppmPigData;
+ uint32_t eisr;
+ uint32_t coreMask[CORES_PER_EX];
+ uint32_t cme_flags;
+ coreMask[0] = CME_MASK_C0;
+ coreMask[1] = CME_MASK_C1;
+
+ G_pmcr_thread_data.seqNum = 0;
+
+ cme_flags = in32(CME_LCL_FLAGS);
+
+ pk_semaphore_create(&G_cme_pstate_record.sem[0], 0, 1);
+
+ PK_TRACE("PMCR_TH: Inited\n");
+
+ while(1)
+ {
+ //pend on sempahore
+ pk_semaphore_pend(&G_cme_pstate_record.sem[0], PK_WAIT_FOREVER);
+ wrteei(1);
+
+ //Determine which core have pending request
+ for(c = 0; c < CORES_PER_EX; c++)
+ {
+ if (cme_flags & (CME_FLAGS_CORE0_GOOD >> c))
+ {
+ eisr = in32_sh(CME_LCL_EISR); //EISR
+
+ if (eisr & (BIT32(2) >> c))
+ {
+ //Clear interrupt and read PMCR
+ out32_sh(CME_LCL_EISR_CLR, BIT32(2) >> c);
+ pmcr[c].value = in64(CME_LCL_PMCRS0 + (c << 5));
+
+ //Send Phase 1
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 0;
+ ppmPigData.value |= (((pmcr[c].value & PIG_PAYLOAD_PS_PHASE1_MASK)));
+
+ ppmPigData.value |= ((G_pmcr_thread_data.seqNum & 0x6) << 57);
+ send_pig_packet(ppmPigData.value, coreMask[c]);
+ G_pmcr_thread_data.seqNum++;
+
+ //Send Phase 2
+ ppmPigData.value = 0;
+ ppmPigData.fields.req_intr_type = 1;
+ ppmPigData.value |= ((pmcr[c].value & PIG_PAYLOAD_PS_PHASE2_MASK) << 16);
+ ppmPigData.value |= ((G_pmcr_thread_data.seqNum & 0x6) << 57);
+ send_pig_packet(ppmPigData.value, coreMask[c]);
+ G_pmcr_thread_data.seqNum++;
+ PK_TRACE("PMCR_TH: Fwd PMCR %d\n", c);
+ }
+ }
+ }
+
+ pk_irq_vec_restore(&ctx);
+ }
+
+ PK_TRACE("PMCR_TH: Exit\n");
+}
diff --git a/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk b/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk
index 4a8b5ce6..7bfb7e3d 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk
+++ b/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk
@@ -1,4 +1,3 @@
-
# IBM_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
#
@@ -25,14 +24,19 @@
# IBM_PROLOG_END_TAG
+
TOP-C-SOURCES = p9_cme_main.c \
p9_cme_irq.c
UTILS-C-SOURCES = utils/p9_putringutils.c \
utils/plat_ring_traverse.c
-PSTATE-C-SOURCES = pstate_cme/p9_cme_pstate.c \
- pstate_cme/p9_pstate_vpd.c
+PSTATE-C-SOURCES = pstate_cme/p9_cme_pstate.c \
+ pstate_cme/p9_cme_thread_db.c \
+ pstate_cme/p9_cme_thread_pmcr.c \
+ pstate_cme/p9_cme_header.c \
+ pstate_cme/p9_cme_intercme.c \
+ pstate_cme/p9_pstate_vpd.c
STOP-C-SOURCES = stop_cme/p9_cme_stop_irq_handlers.c \
stop_cme/p9_cme_stop_enter_thread.c \
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe.h
index 3cfe39eb..078c883e 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe.h
@@ -51,18 +51,28 @@
#include "qppm_firmware_registers.h"
#include "p9_pgpe_irq.h"
-#include "p9_pstate_common.h"
+#include "pstate_pgpe_cme_api.h"
#include "p9_pm_hcd_flags.h"
+#include "ipc_api.h"
+#include "ipc_async_cmd.h"
+
+//
+//#Defines
+//
+#define OCC_IPC_IMMEDIATE_RESP 0x0080
/// PGPE PState
typedef struct
{
- PkSemaphore sem[1];
+ PkSemaphore sem_process_req;
+ PkSemaphore sem_actuate;
+ PkSemaphore sem_sgpe_wait;
} PgpePstateRecord;
/// PGPE PState
-void p9_pgpe_pstate_pig_handler(void* arg, PkIrqId irq);
-void p9_pgpe_pstate_thread(void* arg);
+void p9_pgpe_irq_handler_pcb_type1(void* arg, PkIrqId irq);
+void p9_pgpe_thread_process_requests(void* arg);
+void p9_pgpe_thread_actuate_pstates(void* arg);
///PGPE PState Info
void p9_pgpe_gen_pstate_info();
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_boot_temp.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_boot_temp.c
index 05a971c0..789f5b8b 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_boot_temp.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_boot_temp.c
@@ -57,6 +57,11 @@ void p9_pgpe_boot_pgpe_header_init()
G_pgpe_header_data->magic_number[0] = 0x32323232;//magic
G_pgpe_header_data->_system_reset_addr = (uint32_t*)0xffff2040;//system_reset_address
G_pgpe_header_data->IVPR_address = (uint32_t*)0xffff2000;//IVPR address
+#if !BOOT_TEMP_SET_FULL_OCC_IPC_FUNC
+ G_pgpe_header_data->pgpeflags = (uint16_t)(0x0080); //OCC IPC Immediate Response
+#else
+ G_pgpe_header_data->pgpeflags = (uint16_t)(0x0000); //OCC IPC Full Functionality
+#endif //BOOT_TEMP_SET_FULL_OCC_IPC_FUNC
G_pgpe_header_data->gppb_sram_addr = (uint32_t*)0xfff27000;//GPPB Sram Offset
G_pgpe_header_data->gppb_memory_offset = 0;//GPPB Memory Offset
G_pgpe_header_data->gppb_block_length = 0x2000;//GPPB Block Length
@@ -64,7 +69,8 @@ void p9_pgpe_boot_pgpe_header_init()
G_pgpe_header_data->pstate_tbl_length = 0x6000;//Pstate Tables Length
G_pgpe_header_data->occ_pstate_tbl_addr = (uint32_t*)0xfff29000;//OCC Pstate table address
G_pgpe_header_data->occ_pstate_tbl_length = 0x100;//OCC Pstate table length
- G_pgpe_header_data->pgpe_beacon = (uint32_t*)0xfff26ff0;
+ G_pgpe_header_data->pgpe_beacon = (uint32_t*)(0xfff26fe0 + 4);
+ G_pgpe_header_data->actual_quad_status_addr = (uint32_t*)(0xfff26fe0 + 8);
}
//
@@ -84,7 +90,11 @@ void p9_pgpe_boot_gppb_init()
gppb->options.options = 0;
gppb->reference_frequency_khz = 4150000;
gppb->frequency_step_khz = 16667;
- gppb->ext_vdd_step_size_mv = 50;
+ gppb->ext_vrm_transition_start_ns = 50;
+ gppb->ext_vrm_transition_rate_inc_uv_per_us = 10000;
+ gppb->ext_vrm_transition_rate_dec_uv_per_us = 10000;
+ gppb->ext_vrm_stabilization_time_us = 500;
+ gppb->ext_vrm_step_size_mv = 50;
gppb->nest_frequency_mhz = 2000;
gppb->operating_points[ULTRA].frequency_mhz = 4150;
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c
index 9e7d49cf..0242fd42 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.c
@@ -30,6 +30,9 @@ GlobalPstateParmBlock* G_gppb;
//Global array to store calculated slopes
VpdOperatingPoint G_operating_points[NUM_VPD_PTS_SET][VPD_PV_POINTS];
+uint8_t G_pstate0_dpll_value;
+uint32_t G_ext_vrm_inc_rate_mult_usperus;
+uint32_t G_ext_vrm_dec_rate_mult_usperus;
extern pgpe_header_data_t* G_pgpe_header_data;
//
@@ -57,6 +60,16 @@ void p9_pgpe_gppb_init()
//Calculate slope co-efficents.
p9_pgpe_gppb_compute_PsV_slopes();
+
+ //Dpll value corresponding to Pstate 0
+ G_pstate0_dpll_value = ((G_gppb->reference_frequency_khz + (G_gppb->frequency_step_khz - 1)) /
+ G_gppb->frequency_step_khz);
+
+ //External VRM increasing rate in us/uv
+ G_ext_vrm_inc_rate_mult_usperus = 1 / G_gppb->ext_vrm_transition_rate_inc_uv_per_us;
+
+ //External VRM decreasing rate in us/uv
+ G_ext_vrm_dec_rate_mult_usperus = 1 / G_gppb->ext_vrm_transition_rate_dec_uv_per_us;
}
//
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h
index 9e701157..ae603670 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_gppb.h
@@ -33,6 +33,7 @@
//#define REGION_TURBO_ULTRA 2
#define EVID_SLOPE_FP_SHIFT 13
+#define MAX_DPLL_VALUE 255
#define NUM_VPD_PTS_SET 4
#define VPD_PT_SET_RAW 0
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.c
index 2d073e6a..c819b021 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.c
@@ -29,7 +29,8 @@ pgpe_header_data_t* G_pgpe_header_data;
//
//Set the pgpe_header_data struct to point to PGPE HEADER in SRAM
//
-//\todo: RTC 164339 Get this address passed from linker script.
+//\TODO: RTC 164339
+//Get this address passed from linker script.
//
void p9_pgpe_header_init()
{
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h
index 030f0e2e..1c91be93 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h
@@ -41,7 +41,7 @@ typedef struct pgpe_header_data
uint32_t shared_sram_length;
uint32_t build_date;
uint32_t version;
- uint16_t qmflags;
+ uint16_t pgpeflags;
uint16_t reserved0[3];
uint32_t* gppb_sram_addr;
uint32_t reserved1;
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.c
new file mode 100644
index 00000000..c025196e
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.c
@@ -0,0 +1,413 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.c $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "pk.h"
+#include "p9_pgpe.h"
+#include "ppe42_cache.h"
+#include "ipc_api.h"
+#include "ipc_async_cmd.h"
+#include "p9_pgpe_header.h"
+#include "pstate_pgpe_occ_api.h"
+//#include "pstate_pgpe_sgpe_api.h"
+#include "ipc_messages.h"
+#include "occhw_shared_data.h"
+#include "p9_pgpe_ipc_handlers.h"
+#include "p9_pgpe_pstate.h"
+#include "qppm_firmware_registers.h"
+#include "qppm_register_addresses.h"
+
+//
+//#Defines
+//
+
+//
+//External Global Data
+//
+extern ipc_req_t G_ipc_pend_tbl[MAX_IPC_PEND_TBL_ENTRIES];
+extern uint8_t G_pstatesEnabled;
+extern PgpePstateRecord G_pgpe_pstate_record;
+extern uint32_t G_already_sem_posted;
+extern uint8_t G_pmcrOwner;
+extern pgpe_header_data_t* G_pgpe_header_data;
+
+//
+//p9_pgpe_ipc_init
+//
+//Called during PGPE initialziation to enable IPC functions
+//and init task list
+//
+void p9_pgpe_ipc_init()
+{
+ uint32_t i;
+
+ ipc_init();
+ ipc_enable();
+
+ for (i = 0; i < MAX_IPC_PEND_TBL_ENTRIES; i++)
+ {
+ G_ipc_pend_tbl[i].cmd = NULL;
+ G_ipc_pend_tbl[i].pending_ack = 0;
+ G_ipc_pend_tbl[i].pending_processing = 0;
+ }
+
+ G_already_sem_posted = 0;
+}
+
+//
+//p9_pgpe_ipc_405_start_stop
+//
+//IPC function called upon receiving 'Pstate Start/Stop' IPC from OCC
+//
+void p9_pgpe_ipc_405_start_stop(ipc_msg_t* cmd, void* arg)
+{
+ PK_TRACE_DBG("START_STOP: Entry\n");
+
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)cmd;
+ ipcmsg_start_stop_t* args = (ipcmsg_start_stop_t*)async_cmd->cmd_data;
+
+ if(G_pgpe_header_data->pgpeflags & OCC_IPC_IMMEDIATE_RESP)
+ {
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_START].pending_ack = 0;
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_START].pending_processing = 0;
+
+ //Yes, here we post to process thread when START/STOP is rcv.
+ //This is done to ensure that pk_irq_vec_restore is called correctly
+ //We can call it here, but other IPCs could be processed in this invocation
+ //of IPC interrupt handler and pk_irq_vec_restore can get called twice.
+ //Much cleaner to call it always from process thread.
+ if (G_already_sem_posted == 0)
+ {
+ pk_semaphore_post(&G_pgpe_pstate_record.sem_process_req);
+ G_already_sem_posted = 1;
+ }
+ }
+ else
+ {
+ //START
+ if (args->action == PGPE_ACTION_PSTATE_START)
+ {
+ if (G_ipc_pend_tbl[IPC_PEND_PSTATE_START].pending_ack == 0)
+ {
+ if(G_pstatesEnabled == 0)
+ {
+ PK_TRACE_DBG("START_STOP: Start Rcvd\n");
+
+ //Add task
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_START].cmd = cmd;
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_START].pending_ack = 1;
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_START].pending_processing = 0;
+
+ //Post to Actuate Thread
+ pk_semaphore_post(&G_pgpe_pstate_record.sem_actuate);
+ }
+ else
+ {
+ PK_TRACE_DBG("START_STOP: Pstate Already Started\n");
+ args->msg_cb.rc = PGPE_RC_REQ_PSTATE_ALREADY_STARTED;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+ }
+ else
+ {
+ PK_TRACE_DBG("START_STOP: Duplicate\n");
+ args->msg_cb.rc = PGPE_RC_REQ_WHILE_PENDING_ACK;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+ }
+ //STOP
+ else if(args->action == PGPE_ACTION_PSTATE_STOP)
+ {
+ PK_TRACE_DBG("START_STOP: Stop Rcvd\n");
+
+ if (G_ipc_pend_tbl[IPC_PEND_PSTATE_STOP].pending_ack == 0)
+ {
+ if(G_pstatesEnabled == 1)
+ {
+ G_pstatesEnabled = 0;
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_STOP].cmd = cmd;
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_STOP].pending_ack = 1;
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_STOP].pending_processing = 0;
+ }
+ else
+ {
+ PK_TRACE_DBG("START_STOP: Pstate Already Stopped\n");
+ args->msg_cb.rc = PGPE_RC_REQ_PSTATE_ALREADY_SUSPENDED;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+ }
+ else
+ {
+ PK_TRACE_DBG("START_STOP: Duplicate\n");
+ args->msg_cb.rc = PGPE_RC_REQ_WHILE_PENDING_ACK;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+ }
+ }
+
+ PK_TRACE_DBG("START_STOP: Exit\n");
+}
+
+//
+//p9_pgpe_ipc_405_clips
+//
+//IPC function called upon receiving 'Clip Update' IPC from OCC
+//
+void p9_pgpe_ipc_405_clips(ipc_msg_t* cmd, void* arg)
+{
+ PK_TRACE_DBG("405_CLIPS: Entry\n");
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)cmd;
+ ipcmsg_set_pmcr_t* args = (ipcmsg_set_pmcr_t*)async_cmd->cmd_data;
+
+ if (G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_ack == 0)
+ {
+ G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].cmd = cmd;
+ G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_processing = 1;
+ G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_ack = 1;
+ }
+ else
+ {
+ args->msg_cb.rc = PGPE_RC_REQ_WHILE_PENDING_ACK;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+
+ if (G_already_sem_posted == 0)
+ {
+ pk_semaphore_post(&G_pgpe_pstate_record.sem_process_req);
+ G_already_sem_posted = 1;
+ }
+
+ PK_TRACE_DBG("405_CLIPS: Exit\n");
+}
+
+//
+//p9_pgpe_ipc_405_set_pmcr
+//
+//IPC function called upon receiving 'Set PMCR' IPC from OCC
+//
+void p9_pgpe_ipc_405_set_pmcr(ipc_msg_t* cmd, void* arg)
+{
+ PK_TRACE_DBG("405_SET_PMCR: Entry\n");
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)cmd;
+ ipcmsg_set_pmcr_t* args = (ipcmsg_set_pmcr_t*)async_cmd->cmd_data;
+
+ if (G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].pending_ack == 0)
+ {
+ if(G_pmcrOwner != PMCR_OWNER_OCC)
+ {
+ args->msg_cb.rc = PGPE_RC_OCC_NOT_PMCR_OWNER;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+ G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].cmd = cmd;
+ G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].pending_processing = 1;
+ G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].pending_ack = 1;
+ }
+ }
+ else
+ {
+ PK_TRACE_DBG("405_SET_PMCR: Duplicate\n");
+ args->msg_cb.rc = PGPE_RC_REQ_WHILE_PENDING_ACK;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+
+ if (G_already_sem_posted == 0)
+ {
+ pk_semaphore_post(&G_pgpe_pstate_record.sem_process_req);
+ G_already_sem_posted = 1;
+ }
+
+ PK_TRACE_DBG("405_SET_PMCR: Exit\n");
+}
+
+//
+//p9_pgpe_ipc_405_wof_control
+//
+//IPC function called upon receiving 'WOF Control' IPC from OCC
+//
+void p9_pgpe_ipc_405_wof_control(ipc_msg_t* cmd, void* arg)
+{
+ PK_TRACE_DBG("405_WOF_CTRL: Entry\n");
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)cmd;
+ ipcmsg_wof_control_t* args = (ipcmsg_wof_control_t*)async_cmd->cmd_data;
+
+ if (G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_ack == 0)
+ {
+ G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].cmd = cmd;
+ G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_processing = 1;
+ G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_ack = 1;
+ }
+ else
+ {
+ args->msg_cb.rc = PGPE_RC_REQ_WHILE_PENDING_ACK;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+
+ if (G_already_sem_posted == 0)
+ {
+ pk_semaphore_post(&G_pgpe_pstate_record.sem_process_req);
+ G_already_sem_posted = 1;
+ }
+
+ PK_TRACE_DBG("405_WOF_CTRL: Exit\n");
+}
+
+//
+//p9_pgpe_ipc_405_wof_vfrt
+//
+//IPC function called upon receiving 'WOF VFRT' IPC from OCC
+//
+void p9_pgpe_ipc_405_wof_vfrt(ipc_msg_t* cmd, void* arg)
+{
+ PK_TRACE_DBG("405_WOF_VFRT: Entry\n");
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)cmd;
+ ipcmsg_wof_vfrt_t* args = (ipcmsg_wof_vfrt_t*)async_cmd->cmd_data;
+
+ if (G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].pending_ack == 0)
+ {
+ G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].cmd = cmd;
+ G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].pending_processing = 1;
+ G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].pending_ack = 1;
+ }
+ else
+ {
+ args->msg_cb.rc = PGPE_RC_REQ_WHILE_PENDING_ACK;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+
+ if (G_already_sem_posted == 0)
+ {
+ pk_semaphore_post(&G_pgpe_pstate_record.sem_process_req);
+ G_already_sem_posted = 1;
+ }
+
+ PK_TRACE_DBG("405_WOF_VFRT: Exit\n");
+}
+
+//
+//p9_pgpe_ipc_sgpe_suspend_pstates
+//
+//IPC function called upon receiving 'Suspend PStates' IPC from SGPE
+//
+void p9_pgpe_ipc_sgpe_suspend_pstates(ipc_msg_t* cmd, void* arg)
+{
+ PK_TRACE_DBG("SGPE_SUSPEND_PSTATES: Entry\n");
+
+ if (G_ipc_pend_tbl[IPC_PEND_SGPE_SUSPEND_PSTATES].pending_ack == 0 &&
+ G_ipc_pend_tbl[IPC_PEND_SGPE_SUSPEND_PSTATES].pending_processing == 0)
+ {
+ G_ipc_pend_tbl[IPC_PEND_SGPE_SUSPEND_PSTATES].cmd = cmd;
+ G_ipc_pend_tbl[IPC_PEND_SGPE_SUSPEND_PSTATES].pending_processing = 1;
+ G_ipc_pend_tbl[IPC_PEND_SGPE_SUSPEND_PSTATES].pending_ack = 1;
+ }
+ else
+ {
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)cmd;
+ ipcmsg_s2p_suspend_pstate_t* args =
+ (ipcmsg_s2p_suspend_pstate_t*)async_cmd->cmd_data;
+ args->fields.return_code = SGPE_PGPE_RC_REQ_WHILE_PENDING_ACK;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+
+ if (G_already_sem_posted == 0)
+ {
+ pk_semaphore_post(&G_pgpe_pstate_record.sem_process_req);
+ G_already_sem_posted = 1;
+ }
+
+ PK_TRACE_DBG("SGPE_SUSPEND_PSTATES: Exit\n");
+}
+
+//
+//p9_pgpe_ipc_sgpe_updt_active_cores
+//
+//IPC function called upon receiving 'Update Active Cores' IPC from SGPE
+//
+void p9_pgpe_ipc_sgpe_updt_active_cores(ipc_msg_t* cmd, void* arg)
+{
+ PK_TRACE_DBG("SGPE_UPDT_CORES: Entry\n");
+
+ if (G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_ack == 0 &&
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_processing == 0)
+ {
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].cmd = cmd;
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_processing = 1;
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_ack = 1;
+ }
+ else
+ {
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)cmd;
+ ipcmsg_s2p_update_active_cores_t* args =
+ (ipcmsg_s2p_update_active_cores_t*)async_cmd->cmd_data;
+ args->fields.return_code = SGPE_PGPE_RC_REQ_WHILE_PENDING_ACK;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+
+ if (G_already_sem_posted == 0)
+ {
+ pk_semaphore_post(&G_pgpe_pstate_record.sem_process_req);
+ G_already_sem_posted = 1;
+ }
+
+ PK_TRACE_DBG("SGPE_UPDT_CORES: Exit\n");
+}
+
+//
+//p9_pgpe_ipc_sgpe_updt_active_quads
+//
+//IPC function called upon receiving 'Update Active Quads' IPC from SGPE
+//
+void p9_pgpe_ipc_sgpe_updt_active_quads(ipc_msg_t* cmd, void* arg)
+{
+ PK_TRACE_DBG("SGPE_UPDT_QUADS: Entry\n");
+
+ if (G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].pending_ack == 0 &&
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].pending_processing == 0 &&
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_ack == 0 &&
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_processing == 0)
+ {
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].cmd = cmd;
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].pending_processing = 1;
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].pending_ack = 1;
+
+ }
+ else
+ {
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)cmd;
+ ipcmsg_s2p_update_active_quads_t* args =
+ (ipcmsg_s2p_update_active_quads_t*)async_cmd->cmd_data;
+ args->fields.return_code = SGPE_PGPE_RC_REQ_WHILE_PENDING_ACK;
+ ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ }
+
+ if (G_already_sem_posted == 0)
+ {
+ pk_semaphore_post(&G_pgpe_pstate_record.sem_process_req);
+ G_already_sem_posted = 1;
+ }
+
+ PK_TRACE_DBG("SGPE_UPDT_QUADS: Exit\n");
+}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.h
new file mode 100644
index 00000000..f336a526
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.h
@@ -0,0 +1,51 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_ipc_handlers.h $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef _P9_PGPE_IPC_H_
+#define _P9_PGPE_IPC_H_
+
+#include "pk.h"
+
+//
+//PGPE IPC Initialization
+//
+void p9_pgpe_ipc_init();
+
+//
+//405 IPCs
+//
+void p9_pgpe_ipc_405_start_stop(ipc_msg_t* cmd, void* arg);
+void p9_pgpe_ipc_405_clips(ipc_msg_t* cmd, void* arg);
+void p9_pgpe_ipc_405_set_pmcr(ipc_msg_t* cmd, void* arg);
+void p9_pgpe_ipc_405_wof_control(ipc_msg_t* cmd, void* arg);
+void p9_pgpe_ipc_405_wof_vfrt(ipc_msg_t* cmd, void* arg);
+
+//
+//SGPE IPCs
+//
+void p9_pgpe_ipc_sgpe_updt_active_cores(ipc_msg_t* cmd, void* arg);
+void p9_pgpe_ipc_sgpe_updt_active_quads(ipc_msg_t* cmd, void* arg);
+void p9_pgpe_ipc_sgpe_suspend_pstates(ipc_msg_t* cmd, void* arg);
+
+#endif //_P9_PGPE_IPC_H_
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.c
index 6ab938dc..e371d552 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.c
@@ -35,10 +35,6 @@
#include "pk.h"
#include "p9_pgpe_irq.h"
-//-------------------------------------------------------------------//
-// DO NOT modify this file unless you're the owner //
-//-------------------------------------------------------------------//
-
// Notes:
// - The following two lists, ext_irq_vectors_gpe[][] and IDX_PRTY_LVL_<task_abbr>,
// must match. IDX_PRTY_LVL_<task_abbr> is the tasks priority level and serves
@@ -48,38 +44,44 @@ const uint64_t ext_irq_vectors_gpe[NUM_EXT_IRQ_PRTY_LEVELS][2] =
{
{
- IRQ_VEC_PRTY0_GPE, IRQ_VEC_PRTY3_GPE2 | /* 0: IDX_PRTY_LVL_HIPRTY */
+ IRQ_VEC_PRTY0_GPE, IRQ_VEC_PRTY5_GPE2 | /* 0 */
+ IRQ_VEC_PRTY4_GPE2 |
+ IRQ_VEC_PRTY3_GPE2 |
IRQ_VEC_PRTY2_GPE2 |
IRQ_VEC_PRTY1_GPE2 |
IRQ_VEC_PRTY0_GPE
} ,
{
- IRQ_VEC_PRTY1_GPE2, IRQ_VEC_PRTY3_GPE2 | /* 1: IDX_PRTY_LVL_OCBERR */
+ IRQ_VEC_PRTY1_GPE2, IRQ_VEC_PRTY5_GPE2 | /* 1 */
+ IRQ_VEC_PRTY4_GPE2 |
+ IRQ_VEC_PRTY3_GPE2 |
IRQ_VEC_PRTY2_GPE2 |
IRQ_VEC_PRTY1_GPE2
} ,
{
- IRQ_VEC_PRTY2_GPE2, IRQ_VEC_PRTY3_GPE2 | /* 2: IDX_PRTY_LVL_IPI2HI */
+ IRQ_VEC_PRTY2_GPE2, IRQ_VEC_PRTY5_GPE2 | /* 2 */
+ IRQ_VEC_PRTY4_GPE2 |
+ IRQ_VEC_PRTY3_GPE2 |
IRQ_VEC_PRTY2_GPE2
} ,
- { IRQ_VEC_PRTY3_GPE2, IRQ_VEC_PRTY3_GPE2 } , /* 3: IDX_PRTY_LVL_TYPE1 */
-
- { IRQ_VEC_PRTY4_GPE2, IRQ_VEC_PRTY4_GPE2 } /* 4: IDX_PRTY_LVL_DISABLED */
+ {
+ IRQ_VEC_PRTY3_GPE2, IRQ_VEC_PRTY5_GPE2 | /* 2 */
+ IRQ_VEC_PRTY4_GPE2 |
+ IRQ_VEC_PRTY3_GPE2
+ } ,
- /* 0: IDX_PRTY_VEC 1: IDX_MASK_VEC */
-};
+ {
+ IRQ_VEC_PRTY4_GPE2, IRQ_VEC_PRTY5_GPE2 | /* 2 */
+ IRQ_VEC_PRTY4_GPE2
+ } ,
+ { IRQ_VEC_PRTY5_GPE2, IRQ_VEC_PRTY5_GPE2 } , /* 3 */
-/*const uint8_t IDX_PRTY_LVL_HIPRTY = 0;
-const uint8_t IDX_PRTY_LVL_OCBERR = 1;
-const uint8_t IDX_PRTY_LVL_IPI2HI = 2;
-const uint8_t IDX_PRTY_LVL_TYPE1 = 3;
-const uint8_t IDX_PRTY_LVL_DISABLED = 4;
+ { IRQ_VEC_PRTY6_GPE2, IRQ_VEC_PRTY6_GPE2 } /* 4 */
-const uint8_t IDX_PRTY_VEC = 0;
-const uint8_t IDX_MASK_VEC = 1;*/
+};
uint8_t g_oimr_stack[NUM_EXT_IRQ_PRTY_LEVELS];
int g_oimr_stack_ctr = -1;
@@ -87,20 +89,18 @@ uint8_t g_current_prty_level = NUM_EXT_IRQ_PRTY_LEVELS - 1;
uint64_t g_oimr_override = 0x0000000000000000;
uint64_t g_oimr_override_stack[NUM_EXT_IRQ_PRTY_LEVELS];
+
//
// Unified IRQ priority and masking handler.
-// - Locates the highest priority IRQ task vector that has at least one of its
-// interrupts in the current external PK interrupt vector.
+// Locates the highest priority IRQ task vector that has at least one of its
+// interrupts in the current external PK interrupt vector.
//
void pk_unified_irq_prty_mask_handler(void)
{
uint8_t iPrtyLvl, bFound;
uint64_t ext_irq_vector_pk;
- //
// 1. Identify the priority level of the interrupt.
- //
-
ext_irq_vector_pk = ((uint64_t)in32(OCB_G0ISR0 + APPCFG_OCC_INSTANCE_ID * 8)) << 32 |
(uint64_t)in32(OCB_G0ISR1 + APPCFG_OCC_INSTANCE_ID * 8);
//ext_irq_vector_pk = ((uint64_t)in32(OCB_OISR0))<<32 |
@@ -121,58 +121,11 @@ void pk_unified_irq_prty_mask_handler(void)
}
while (++iPrtyLvl < (NUM_EXT_IRQ_PRTY_LEVELS - 1)); // No need to check DISABLED.
- //
- // Only manipulate OIMR masks for task level prty levels. Let shared non-task
- // IRQs (iPrtyLvl=0) be processed by the PK kernel in usual fashion.
- //
+ // 2. Only manipulate OIMR masks for task level prty levels. Let shared non-task
+ // IRQs (iPrtyLvl=0) be processed by the PK kernel in usual fashion.
if (bFound)
{
-
- //
- // 2. Save current mask (assume current prty level).
- //
-
- // Note, reading EIMR is NOT safe because overrides may already have
- // happened to the EIMR. And we always want to restore
- // the EIMR to a known value when we exit our thread.
- //
- if (++g_oimr_stack_ctr < NUM_EXT_IRQ_PRTY_LEVELS)
- {
- //prev: g_oimr_stack[g_oimr_stack_ctr] = ((uint64_t)in32(OCB_OIMR0))<<32 |
- // (uint64_t)in32(OCB_OIMR1);
- // Make a note of present prty level and then update tracker to new prty level.
- g_oimr_stack[g_oimr_stack_ctr] = g_current_prty_level;
- g_current_prty_level = iPrtyLvl; // Update prty level tracker.
- g_oimr_override_stack[g_oimr_stack_ctr] = g_oimr_override;
- }
- else
- {
- MY_TRACE_ERR("Code bug: OIMR S/R stack counter=%d >= max=%d.",
- g_oimr_stack_ctr, NUM_EXT_IRQ_PRTY_LEVELS);
- pk_halt();
- }
-
- //
- // 3. Write the new mask for this priority level.
- //
-
- // First, clear all those IRQs that could possibly interrupt this instance.
- // This includes all those IRQs which belong to this instance as well as
- // those high-prty IRQs shared with the other instances.
- //
- out32(OCB_OIMR0_CLR, (uint32_t)(IRQ_VEC_ALL_OUR_IRQS >> 32));
- out32(OCB_OIMR1_CLR, (uint32_t)IRQ_VEC_ALL_OUR_IRQS);
-
- // Second, mask IRQs belonging to this task and lower prty tasks.
- // Note, that we do not modify the permanently disabled IRQs, such as the
- // _RESERVED_ ones. Nor do we touch other instances' IRQs. Iow, the
- // IDX_PRTY_LVL_DISABLED mask is NOT part of the mask we apply below.
- //
- out32(OCB_OIMR0_OR, (uint32_t)((ext_irq_vectors_gpe[iPrtyLvl][IDX_MASK_VEC] |
- g_oimr_override) >> 32) );
- out32(OCB_OIMR1_OR, (uint32_t)(ext_irq_vectors_gpe[iPrtyLvl][IDX_MASK_VEC] |
- g_oimr_override) );
-
+ pk_irq_save_and_set_mask(iPrtyLvl);
}
else
{
@@ -181,19 +134,58 @@ void pk_unified_irq_prty_mask_handler(void)
pk_halt();
}
-
- //
- // 4. Return the priority vector in d5 and let hwmacro_get_ext_irq do the
- // rest, i.e. route first found IRQ in the returned priority vector
- // to the registered [unified] interrupt handler.
- //
-
+ // 3. Return the priority vector in d5 and let hwmacro_get_ext_irq do the
+ // rest, i.e. route first found IRQ in the returned priority vector
+ // to the registered [unified] interrupt handler.
uint32_t register l_vecH asm("r5");
uint32_t register l_vecL asm("r6") __attribute__((unused));
-
l_vecL = 0;
asm volatile ("lvd %[data], 0(%[addr]) \n" \
: [data]"=r"(l_vecH) \
: [addr]"r"(&ext_irq_vectors_gpe[iPrtyLvl][IDX_PRTY_VEC]) );
}
+
+//
+//pk_irq_save_and_set_mask()
+//
+void pk_irq_save_and_set_mask(uint32_t iPrtyLvl)
+{
+ // Save current mask (assume current prty level).
+ // Note, reading OIMR is NOT safe because overrides may already have
+ // happened to the OIMR. And we always want to restore
+ // the OIMR to a known value when we exit our thread.
+ if (++g_oimr_stack_ctr < NUM_EXT_IRQ_PRTY_LEVELS)
+ {
+ //prev: g_oimr_stack[g_oimr_stack_ctr] = ((uint64_t)in32(OCB_OIMR0))<<32 |
+ // (uint64_t)in32(OCB_OIMR1);
+ // Make a note of present prty level and then update tracker to new prty level.
+ g_oimr_stack[g_oimr_stack_ctr] = g_current_prty_level;
+ g_current_prty_level = iPrtyLvl; // Update prty level tracker.
+ g_oimr_override_stack[g_oimr_stack_ctr] = g_oimr_override;
+ }
+ else
+ {
+ MY_TRACE_ERR("Code bug: OIMR S/R stack counter=%d >= max=%d.",
+ g_oimr_stack_ctr, NUM_EXT_IRQ_PRTY_LEVELS);
+ pk_halt();
+ }
+
+ // Write the new mask for this priority level.
+ // First, clear all those IRQs that could possibly interrupt this instance.
+ // This includes all those IRQs which belong to this instance as well as
+ // those high-prty IRQs shared with the other instances.
+ //
+ out32(OCB_OIMR0_CLR, (uint32_t)(IRQ_VEC_ALL_OUR_IRQS >> 32));
+ out32(OCB_OIMR1_CLR, (uint32_t)IRQ_VEC_ALL_OUR_IRQS);
+
+ // Second, mask IRQs belonging to this task and lower prty tasks.
+ // Note, that we do not modify the permanently disabled IRQs, such as the
+ // _RESERVED_ ones. Nor do we touch other instances' IRQs. Iow, the
+ // IDX_PRTY_LVL_DISABLED mask is NOT part of the mask we apply below.
+ out32(OCB_OIMR0_OR, (uint32_t)((ext_irq_vectors_gpe[iPrtyLvl][IDX_MASK_VEC] |
+ g_oimr_override) >> 32) );
+ out32(OCB_OIMR1_OR, (uint32_t)(ext_irq_vectors_gpe[iPrtyLvl][IDX_MASK_VEC] |
+ g_oimr_override) );
+
+}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.h
index 02770ae1..04b3d6f1 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.h
@@ -32,9 +32,6 @@
/// \brief Shared and global definitions for PGPE (GPE2) H-codes.
///
-//-------------------------------------------------------------------//
-// DO NOT modify this file unless you're the owner //
-//-------------------------------------------------------------------//
// Notes:
// - The only define names that should be changed/added/removed
@@ -43,7 +40,6 @@
// - IDX_PRTY_LVL_(task_abbr) and reflect in relevant H-code as well
// - All other define names are used in H-codes
// - The variable names and actions in this file must perfectly match associated
-// definitions in gpe2_irq_common.c
#ifndef _P9_PGPE_IRQ_H_
#define _P9_PGPE_IRQ_H_
@@ -68,38 +64,33 @@
#define IDX_PRTY_LVL_HIPRTY 0
#define IDX_PRTY_LVL_OCBERR 1
#define IDX_PRTY_LVL_IPI2HI 2
-#define IDX_PRTY_LVL_TYPE1_TYPE4 3
+#define IDX_PRTY_LVL_TYPE1 3
#define IDX_PRTY_LVL_DISABLED 4
#define IDX_PRTY_VEC 0
#define IDX_MASK_VEC 1
-#define NUM_EXT_IRQ_PRTY_LEVELS (uint8_t)(5)
+#define NUM_EXT_IRQ_PRTY_LEVELS (uint8_t)(7)
extern const uint64_t ext_irq_vectors_gpe[NUM_EXT_IRQ_PRTY_LEVELS][2];
-#define IRQ_VEC_PRTY0_GPE (uint64_t)(0x0001000000000000) // Non-task hi-prty IRQs
+#define IRQ_VEC_PRTY0_GPE (uint64_t)(0x0000000000000000) // Non-task hi-prty IRQs
// Shared between all instances
-#define IRQ_VEC_PRTY1_GPE2 (uint64_t)(0x0000000000000000) // Task1-OCCHW_IRQ_OCB_ERROR=HB loss?
-#define IRQ_VEC_PRTY2_GPE2 (uint64_t)(0x0000001000000000) // Task2-IPC msgs from 405
-#define IRQ_VEC_PRTY3_GPE2 (uint64_t)(0x0000000000020000) // Task3-CME interrupts
-#define IRQ_VEC_PRTY4_GPE2 (uint64_t)(0xFFFEFFEFFFFDFFFF) // Other instances' IRQs
+#define IRQ_VEC_PRTY1_GPE2 (uint64_t)(0x0080000000000000) // Task1-OCB_ERROR(HeartBeat Loss)/GPE3_HALT
+#define IRQ_VEC_PRTY2_GPE2 (uint64_t)(0x0001000000000000) // Task2-CHECK_STOP_GPE2
+#define IRQ_VEC_PRTY3_GPE2 (uint64_t)(0x0000000000000008) // Task3-IPI2-LO(Process Flags)
+#define IRQ_VEC_PRTY4_GPE2 (uint64_t)(0x0000001000000000) // Task4-IPI2-HI(IPC from OCC/SGPE)
+#define IRQ_VEC_PRTY5_GPE2 (uint64_t)(0x0000000000020000) // Task5-PCB_INTR_TYPE1(PCB Type1 from CME)
+#define IRQ_VEC_PRTY6_GPE2 (uint64_t)(0xFF7EFFE3FFFDFFF5) // Other instances' IRQs
// Unique to each instance
// We should never detect these
#define IRQ_VEC_ALL_OUR_IRQS ( IRQ_VEC_PRTY0_GPE | \
IRQ_VEC_PRTY1_GPE2 | \
IRQ_VEC_PRTY2_GPE2 | \
- IRQ_VEC_PRTY3_GPE2 ) // Note, we do not incl PRTY4 here!
+ IRQ_VEC_PRTY3_GPE2 | \
+ IRQ_VEC_PRTY4_GPE2 | \
+ IRQ_VEC_PRTY5_GPE2 ) // Note, we do not incl PRTY6 here!
#define IRQ_VEC_PRTY_CHECK ( IRQ_VEC_ALL_OUR_IRQS | \
- IRQ_VEC_PRTY4_GPE2 ) // This should be 0xFFFFFFFFFFFFFFFF
-
-/*extern const uint8_t IDX_PRTY_VEC;
-extern const uint8_t IDX_MASK_VEC;
-
-extern const uint8_t IDX_PRTY_LVL_HIPRTY;
-extern const uint8_t IDX_PRTY_LVL_OCBERR;
-extern const uint8_t IDX_PRTY_LVL_IPI2HI;
-extern const uint8_t IDX_PRTY_LVL_TYPE1;
-extern const uint8_t IDX_PRTY_LVL_DISABLED;*/
+ IRQ_VEC_PRTY6_GPE2 ) // This should be 0xFFFFFFFFFFFFFFFF
extern uint8_t g_current_prty_level;
extern uint8_t g_oimr_stack[NUM_EXT_IRQ_PRTY_LEVELS];
@@ -107,6 +98,7 @@ extern int g_oimr_stack_ctr;
extern uint64_t g_oimr_override_stack[NUM_EXT_IRQ_PRTY_LEVELS];
extern uint64_t g_oimr_override;
+void pk_irq_save_and_set_mask(uint32_t iPrtyLvl);
/// Restore a vector of interrupts by overwriting OIMR.
UNLESS__PPE42_IRQ_CORE_C__(extern)
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c
new file mode 100644
index 00000000..284480e4
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c
@@ -0,0 +1,147 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq_handlers.c $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "pk.h"
+#include "p9_pgpe.h"
+#include "p9_pgpe_pstate.h"
+#include "pstate_pgpe_occ_api.h"
+
+//
+//External Global Data
+//
+extern uint8_t G_coresPSRequest[MAX_CORES]; //per core requested pstate
+extern uint8_t G_pmcrOwner;
+extern uint8_t G_pstatesEnabled; //pstates_enabled/disable
+
+//
+//OCB Error Interrupt Handler
+//
+//\TODO:
+//Implement this handler. Implement Safe Mode
+void p9_pgpe_irq_handler_ocb_error(void* arg, PkIrqId irq)
+{
+ PK_TRACE_DBG("OCB Error: Enter\n");
+ PkMachineContext ctx;
+
+ pk_irq_vec_restore(&ctx);//Restore interrupts
+ PK_TRACE_DBG("OCB Error: Exit\n");
+}
+
+//
+//SGPE Halt Interrupt Handler
+//
+//\TODO: RTC 164107
+//Implement this handler. Implement Safe Mode
+void p9_pgpe_irq_handler_sgpe_halt(void* arg, PkIrqId irq)
+{
+ PK_TRACE_DBG("SGPE Halt: Enter\n");
+ PkMachineContext ctx;
+
+ pk_irq_vec_restore(&ctx);//Restore interrupts
+ PK_TRACE_DBG("SGPE Halt: Exit\n");
+}
+
+//
+//Checkstop GPE2 Interrupt Handler
+//
+//\TODO
+//Implement this handler. Should call code same as "Pstart STOP" IPC from OCC
+void p9_pgpe_irq_handler_xstop_gpe2(void* arg, PkIrqId irq)
+{
+ PK_TRACE_DBG("XSTOP GPE2: Enter\n");
+ PkMachineContext ctx;
+
+ pk_irq_vec_restore(&ctx);//Restore interrupts
+ PK_TRACE_DBG("XSTOP GPE2: Exit\n");
+}
+
+//
+//IPI2 Lo Priority Interrupt Handler
+//
+//\TODO: RTC 164107
+//Implement this handler. Should call "process_flags" function(needs to be implemented).
+void p9_pgpe_irq_handler_ipi2_lo(void* arg, PkIrqId irq)
+{
+ PK_TRACE_DBG("IPI2 Lo: Enter\n");
+ PkMachineContext ctx;
+
+ pk_irq_vec_restore(&ctx);//Restore interrupts
+ PK_TRACE_DBG("IPI2 Lo: Exit\n");
+}
+
+//
+//PCB Type 1 Interrupt Handler
+//
+void p9_pgpe_irq_handler_pcb_type1(void* arg, PkIrqId irq)
+{
+ PK_TRACE_DBG("PCB_TYPE1: Enter\n");
+
+ //Snapshot
+ PkMachineContext ctx;
+ ocb_opit0cn_t opit0cn;
+ ocb_opit1cn_t opit1cn;
+ uint32_t coresPendPSReq = in32(OCB_OPIT1PRA);
+ uint32_t c;
+
+ if (G_pstatesEnabled && (G_pmcrOwner == PMCR_OWNER_HOST ||
+ G_pmcrOwner == PMCR_OWNER_CHAR))
+ {
+
+ //Process pending requests
+ for (c = 0; c < MAX_CORES; c++)
+ {
+ //For each pending bit OPIT1PR[c] (OPIT1PR is 24 bits)
+ if (coresPendPSReq & (0x80000000 >> c))
+ {
+ //Read payload from OPIT0C[c] and OPIT1C[c] register corresponding to the core 'c'
+ //Bits 20:31 OPIT0C - Phase 1 OPIT1C - Phase 2
+ opit0cn.value = in32(OCB_OPIT0CN(c));
+ opit1cn.value = in32(OCB_OPIT1CN(c));
+
+ uint16_t op0 = opit0cn.fields.pcb_intr_payload;
+ uint16_t op1 = opit1cn.fields.pcb_intr_payload;
+
+ //make sure seq number matches for both phases
+ //otherwise, ignore the request
+ if (((op0 >> 10) && 0x3) ==
+ ((op1 >> 10) && 0x3))
+ {
+ //Extract the LowerPState field
+ G_coresPSRequest[c] = op1 & 0xff;
+ out32(OCB_OPIT1PRA_CLR, 0x80000000 >> c); //Clear out pending bits
+ }
+ }
+ }
+
+ p9_pgpe_pstate_do_auction(ALL_QUADS_BIT_MASK);
+ p9_pgpe_pstate_apply_clips();
+ }
+
+#if SIMICS_TUNING
+ out32(OCB_OPIT1PRA, 0x00000000); //Clear out pending bits
+ out32(OCB_OISR1_CLR, BIT32(14));
+#endif
+ pk_irq_vec_restore(&ctx);//Restore interrupts
+ PK_TRACE_DBG("PCB_TYPE1: Exit\n");
+}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_main.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_main.c
index 42ec5987..df7820f4 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_main.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_main.c
@@ -27,6 +27,7 @@
#include "p9_pgpe_header.h"
#include "p9_pgpe_gppb.h"
#include "p9_pgpe_boot_temp.h"
+#include "p9_pgpe_pstate.h"
PgpePstateRecord G_pgpe_pstate_record;
@@ -77,7 +78,7 @@ IRQ_HANDLER_DEFAULT //OCCHW_IRQ_STRM2_PUSH
IRQ_HANDLER_DEFAULT //OCCHW_IRQ_STRM3_PULL
IRQ_HANDLER_DEFAULT //OCCHW_IRQ_STRM3_PUSH
IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_PCB_INTR_TYPE0_PENDING
-IRQ_HANDLER(p9_pgpe_pstate_pig_handler, (void*) & G_pgpe_pstate_record.sem[0])
+IRQ_HANDLER(p9_pgpe_irq_handler_pcb_type1, (void*) & G_pgpe_pstate_record.sem_process_req)
//OCCHW_IRQ_PMC_PCB_INTR_TYPE1_PENDING
IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_PCB_INTR_TYPE2_PENDING
IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_PCB_INTR_TYPE3_PENDING
@@ -101,13 +102,18 @@ EXTERNAL_IRQ_TABLE_END
#define KERNEL_STACK_SIZE 512
#define THREAD_STACK_SIZE 512
-#define PGPE_THREAD_PRIORITY_PSTATE 1
+#define PGPE_THREAD_PRIORITY_PROCESS_REQUESTS 1
+#define PGPE_THREAD_PRIORITY_ACTUATE_PSTATES 2
uint8_t G_kernel_stack[KERNEL_STACK_SIZE];
-uint8_t G_p9_pgpe_pstate_thread_stack[THREAD_STACK_SIZE];
+//Thread Stacks
+uint8_t G_p9_pgpe_thread_process_requests_stack[THREAD_STACK_SIZE];
+uint8_t G_p9_pgpe_thread_actuate_pstates_stack[THREAD_STACK_SIZE];
-PkThread G_p9_pgpe_pstate_thread;
+//Thread Control Block
+PkThread G_p9_pgpe_thread_process_requests;
+PkThread G_p9_pgpe_thread_actuate_pstates;
void __eabi()
{
@@ -124,31 +130,43 @@ main(int argc, char** argv)
asm volatile ("tw 0, 31, 0");
}
-
// Initializes kernel data (stack, threads, timebase, timers, etc.)
pk_initialize((PkAddress)G_kernel_stack,
KERNEL_STACK_SIZE,
0,
PPE_TIMEBASE_HZ);
- // Initialize the thread control block for G_p9_pgpe_pstate_thread
- pk_thread_create(&G_p9_pgpe_pstate_thread,
- (PkThreadRoutine)p9_pgpe_pstate_thread,
+ // Initialize the thread control block for G_p9_pgpe_thread_process_requests
+ pk_thread_create(&G_p9_pgpe_thread_process_requests,
+ (PkThreadRoutine)p9_pgpe_thread_process_requests,
(void*)NULL,
- (PkAddress)G_p9_pgpe_pstate_thread_stack,
+ (PkAddress)G_p9_pgpe_thread_process_requests_stack,
(size_t)THREAD_STACK_SIZE,
- (PkThreadPriority)PGPE_THREAD_PRIORITY_PSTATE);
+ (PkThreadPriority)PGPE_THREAD_PRIORITY_PROCESS_REQUESTS);
+
+ PK_TRACE_BIN("G_p9_pgpe_thread_process_requests",
+ &G_p9_pgpe_thread_process_requests,
+ sizeof(G_p9_pgpe_thread_process_requests));
- PK_TRACE_BIN("G_p9_pgpe_pstate_thread",
- &G_p9_pgpe_pstate_thread,
- sizeof(G_p9_pgpe_pstate_thread));
+ // Initialize the thread control block for G_p9_pgpe_thread_actuate_pstates
+ pk_thread_create(&G_p9_pgpe_thread_actuate_pstates,
+ (PkThreadRoutine)p9_pgpe_thread_actuate_pstates,
+ (void*)NULL,
+ (PkAddress)G_p9_pgpe_thread_actuate_pstates_stack,
+ (size_t)THREAD_STACK_SIZE,
+ (PkThreadPriority)PGPE_THREAD_PRIORITY_ACTUATE_PSTATES);
- // Make G_p9_pgpe_pstate_thread runnable
- pk_thread_resume(&G_p9_pgpe_pstate_thread);
+ PK_TRACE_BIN("G_p9_pgpe_thread_actuate_pstates",
+ &G_p9_pgpe_thread_actuate_pstates,
+ sizeof(G_p9_pgpe_thread_actuate_pstates));
+
+ // Make G_p9_pgpe_thread pstates_update runnable
+ pk_thread_resume(&G_p9_pgpe_thread_process_requests);
+ pk_thread_resume(&G_p9_pgpe_thread_actuate_pstates);
//Do initialization
p9_pgpe_header_init();
-#if MIMIC_BOOT_TEMP
+#if USE_BOOT_TEMP
//This is to be used for development and testing/verif
//if Global Pstate Parameter Block is not initialized through other means.
//
@@ -167,6 +185,11 @@ main(int argc, char** argv)
//Setup FIT(Fixed-Interval Timer)
p9_pgpe_fit_init();
+ //Initialize all pstate related data to some default values
+ p9_pgpe_pstate_init();
+
+ PK_TRACE_DBG("Starting PK Threads\n");
+
// Start running the highest priority thread.
// This function never returns
pk_start_threads();
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c
index 94382d4b..12c93b9c 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c
@@ -23,463 +23,253 @@
/* */
/* IBM_PROLOG_END_TAG */
#include "p9_pgpe.h"
-#include "p9_pstate_common.h"
+#include "pstate_pgpe_cme_api.h"
#include "p9_pstates_common.h"
#include "p9_pgpe_gppb.h"
#include "p9_pgpe_boot_temp.h"
#include "avs_driver.h"
#include "p9_dd1_doorbell_wr.h"
+#include "p9_pgpe_pstate.h"
+#include "pstate_pgpe_occ_api.h"
+//#include "pstate_pgpe_sgpe_api.h"
+#include "ipc_messages.h"
+#include "p9_pgpe_header.h"
+//
+//Global External Data
+//
+extern pgpe_header_data_t* G_pgpe_header_data;
-#define CCSR_CORE_CONFIG_MASK 0xC0000000
+//
+//Global Data
+//
+uint8_t G_safeModeEnabled; //safe mode enabled/disabled
+uint8_t G_pstatesEnabled; //pstates_enabled/disable
+uint8_t G_pmcrOwner;
+uint8_t G_wofEnabled; //wof enable/disable
+uint8_t G_wofPending; //wof enable pending
+uint8_t G_psClipMax[MAX_QUADS],
+ G_psClipMin[MAX_QUADS]; //pmin and pmax clips
+uint8_t G_wofClip; //wof clip
+uint8_t G_coresPSRequest[MAX_CORES]; //per core requested pstate
+uint8_t G_quadPSComputed[MAX_QUADS]; //computed Pstate per quad
+uint8_t G_globalPSComputed; //computed global Pstate
+uint8_t G_quadPSTarget[MAX_QUADS]; //target Pstate per quad
+uint8_t G_globalPSTarget; //target global Pstate
+uint8_t G_quadPSCurr[MAX_QUADS]; //target Pstate per quad
+uint8_t G_globalPSCurr; //target global Pstate
+uint8_t G_quadPSNext[MAX_QUADS]; //target Pstate per quad
+uint8_t G_globalPSNext;
+uint32_t G_eVidCurr, G_eVidNext;
+VFRT_Hcode_t* G_vfrt_ptr;
+quad_state0_t* G_quadState0;
+quad_state1_t* G_quadState1;
-enum quadManager
-{
- QUAD_MANAGER_NONE = -1,
- QUAD_MANAGER_CME0 = 0,
- QUAD_MANAGER_CME1 = 1
-};
+#define GPE_BUFFER(declaration) \
+ declaration __attribute__ ((__aligned__(8))) __attribute__ ((section (".noncacheable")))
+GPE_BUFFER(ipc_async_cmd_t G_ipc_msg_pgpe_sgpe);
+GPE_BUFFER(ipcmsg_p2s_ctrl_stop_updates_t G_sgpe_control_updt);
-//External Voltage, GlobalPState, Local PStates
-uint32_t G_eVidCurr, G_eVidNext;
-uint8_t G_globalCurrPS, G_globalNextPS;
-uint8_t G_localPSCurr[MAX_QUADS];
-uint8_t G_localPSNext[MAX_QUADS];
-uint8_t G_globalPSTgt;
-uint8_t G_localPSTgt[MAX_QUADS];
-uint32_t G_tgtEVid;
-int8_t G_quadManagerCME[MAX_QUADS]; //0->CME0, 1->CME1, -1->Quad not configured
-uint8_t G_quadPendPSReq[MAX_QUADS];
-uint8_t G_coresPendPSReqData[MAX_CORES];
-uint32_t G_ccsr;
-extern PgpePstateRecord G_pgpe_pstate_record;
-extern GlobalPstateParmBlock* G_gppb;
-extern VpdOperatingPoint G_operating_points[NUM_VPD_PTS_SET][VPD_PV_POINTS];
//
-//Function Prototypes
+//Data passing between IPC interrupt and threads
//
-void p9_pgpe_pstate_get_config();
-void p9_pgpe_pstate_update_ext_volt();
-void p9_pgpe_pstate_freq_update();
+ipc_req_t G_ipc_pend_tbl[MAX_IPC_PEND_TBL_ENTRIES];
+uint32_t G_already_sem_posted;
-//
-//
-//
+extern VpdOperatingPoint G_operating_points[NUM_VPD_PTS_SET][VPD_PV_POINTS];
//
-//PIG Interrupt Handler
+//p9_pgpe_pstate_init
//
-void p9_pgpe_pstate_pig_handler(void* arg, PkIrqId irq)
+void p9_pgpe_pstate_init()
{
- //Read OCC_FLAG[PGPE_STARTNOTSTOP]]
- uint32_t occFlag = in32(OCB_OCCFLG);
+ uint32_t q;
+
+ G_safeModeEnabled = 0;
+ G_pstatesEnabled = 0;
+ G_wofEnabled = 0;
+ G_wofPending = 0;
- if (occFlag & BIT32(PGPE_START_NOT_STOP))
+ for (q = 0; q < MAX_QUADS; q++)
{
- pk_semaphore_post((PkSemaphore*)arg);
+ G_psClipMax[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_psClipMin[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_quadPSComputed[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_globalPSComputed = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_quadPSTarget[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_globalPSTarget = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_quadPSCurr[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_globalPSCurr = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_quadPSNext[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_globalPSNext = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
}
+ G_quadState0 = (quad_state0_t*)G_pgpe_header_data->actual_quad_status_addr;
+ G_quadState1 = (quad_state1_t*)(G_pgpe_header_data->actual_quad_status_addr + 2);
}
//
-//PState Thread
+//p9_pgpe_pstate_update_
//
-void p9_pgpe_pstate_thread(void* arg)
+void p9_pgpe_pstate_update(uint8_t* s)
{
- int32_t q, c;
- uint8_t psClipMax, psClipMin;
- uint32_t coresPendPSReq;
- ocb_opit0cn_t opit0cn;
- ocb_opit1cn_t opit1cn;
- PkMachineContext ctx;
- uint8_t effPSClipMin, effPSClipMax;
- uint8_t done;
-
- //\todo Set initial eVid, Global PState, Local PState, Max/Mins PStateClip for PGPE. RTC. 159900
- psClipMax = 0;
- psClipMin = 140;
- coresPendPSReq = 0;
- G_eVidCurr = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].vdd_mv;
- G_eVidNext = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].vdd_mv;
- G_globalCurrPS = G_globalNextPS = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ uint32_t q, c;
for (q = 0; q < MAX_QUADS; q++)
{
- G_localPSCurr[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
- G_localPSNext[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
- G_localPSTgt[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
- G_quadPendPSReq[q] = 0;
- }
+ for (c = (q * CORES_PER_QUAD); c < (q + 1)*CORES_PER_QUAD; c++)
+ {
+ G_coresPSRequest[c] = s[q];
+ }
- for (c = 0; c < MAX_CORES; c++)
- {
- G_coresPendPSReqData[c] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ G_quadPSCurr[q] = s[q];
+ G_quadPSNext[q] = s[q];
}
- //Initialization
- external_voltage_control_init(&G_eVidCurr);
- G_eVidCurr = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].vdd_mv; //\todo RTC 159900. Remove this
- p9_pgpe_pstate_get_config();
-
- out32(OCB_OIMR1_CLR, BIT32(14)); //Enable PCB_INTR_TYPE1
-
- pk_semaphore_create(&(G_pgpe_pstate_record.sem[0]), 0, 1);
-
- //Initialize IPC
- p9_pgpe_ipc_init();
-
-
- //Set OCC_SCRATCH2[PGPE_ACTIVE]
- out32(OCB_OCCS2, BIT32(PGPE_ACTIVE));
-#if EPM_P9_TUNING
- asm volatile ("tw 0, 31, 0");
-#endif
+ p9_pgpe_pstate_do_auction(ALL_QUADS_BIT_MASK);
+ p9_pgpe_pstate_apply_clips(NULL);
+}
- //Thread Loop
- while (1)
+//
+//p9_pgpe_pstate_do_auction
+//
+void p9_pgpe_pstate_do_auction(uint8_t quadAuctionRequest)
+{
+ PK_TRACE_DBG("AUCT: Enter\n");
+ //Get active cores and quads
+ uint32_t q, c;
+ uint32_t activeCores = G_quadState0->fields.core_poweron_state ;
+ activeCores = (activeCores << 16) | (G_quadState1->fields.core_poweron_state);
+ uint32_t activeQuads = G_quadState1->fields.requested_active_quad;
+
+ //Local PStates Auction
+ for (q = 0; q < MAX_QUADS; q++)
{
- //pend on semaphore
- pk_semaphore_pend(&(G_pgpe_pstate_record.sem[0]), PK_WAIT_FOREVER);
-
- done = 0;
-
- while (done == 0)
+ //Make sure quad is active
+ if ((activeQuads & (QUAD0_BIT_MASK >> q)) &
+ (quadAuctionRequest & (QUAD0_BIT_MASK >> q)))
{
- //Snapshot
- coresPendPSReq = in32(OCB_OPIT1PRA);
-
- //Make sure clips aren't below or above VPD points
- if (psClipMax < G_operating_points[VPD_PT_SET_BIASED_SYSP][ULTRA].pstate)
- {
- effPSClipMax = G_operating_points[VPD_PT_SET_BIASED_SYSP][ULTRA].pstate;
- }
- else
- {
- effPSClipMax = psClipMax;
- }
-
- if (psClipMin > G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate)
- {
- effPSClipMin = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
- }
- else
- {
- effPSClipMin = psClipMin;
- }
+ //Go through all the cores in this quad with pending request
+ //and find the lowest numbered PState
+ G_quadPSComputed[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
- //Process pending requests
- for (c = 0; c < MAX_CORES; c++)
+ for (c = (q * CORES_PER_QUAD); c < (q + 1)*CORES_PER_QUAD; c++)
{
- //For each pending bit OPIT1PR[c] (OPIT1PR is 24 bits)
- if (coresPendPSReq & (0x80000000 >> c))
+ if (activeCores & (0x80000000 >> c))
{
- //Read payload from OPIT0C[c] and OPIT1C[c] register corresponding to the core 'c'
- //Bits 20:31 OPIT0C - Phase 1 OPIT1C - Phase 2
- opit0cn.value = in32(OCB_OPIT0CN(c));
- opit1cn.value = in32(OCB_OPIT1CN(c));
-
- uint16_t op0 = opit0cn.fields.pcb_intr_payload;
- uint16_t op1 = opit1cn.fields.pcb_intr_payload;
-
- //make sure seq number matches for both phases
- //otherwise, ignore the request
- if (((op0 >> 10) && 0x3) ==
- ((op1 >> 10) && 0x3))
+ if (G_quadPSComputed[q] > G_coresPSRequest[c])
{
- //Extract the LowerPState field
- G_coresPendPSReqData[c] = op1 & 0xff;
- G_quadPendPSReq[QUAD_FROM_CORE(c)] = 1;
- out32(OCB_OPIT1PRA_CLR, 0x80000000 >> c); //Clear out pending bits
+ G_quadPSComputed[q] = G_coresPSRequest[c];
}
}
}
+ }
+ else
+ {
+ G_quadPSComputed[q] = 0xFF;
+ }
- //Local PStates Auction
- for (q = 0; q < MAX_QUADS; q++)
- {
- //Make sure quad is configured and there is a pending request
- if ((G_quadManagerCME[q] != QUAD_MANAGER_NONE) && (G_quadPendPSReq[q] == 1))
- {
- //Go through all the cores in this quad with pending request
- //and find the lowest numbered PState
- G_localPSTgt[q] = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
-
- for (c = (q * CORES_PER_QUAD); c < (q + 1)*CORES_PER_QUAD; c++)
- {
- if (G_ccsr & (0x80000000 >> c))
- {
- if (G_localPSTgt[q] > G_coresPendPSReqData[c])
- {
- G_localPSTgt[q] = G_coresPendPSReqData[c];
- }
- }
- }
-
- //Apply Clip
- if (G_localPSTgt[q] < effPSClipMax)
- {
- G_localPSTgt[q] = effPSClipMax;
- }
- else if (G_localPSTgt[q] > effPSClipMin)
- {
- G_localPSTgt[q] = effPSClipMin;
- }
-
- G_quadPendPSReq[q] = 0;
- }
- }
+ // PK_TRACE_DBG("AUCTION: G_quadPSComputed: 0x%x\n", G_quadPSComputed[q]);
+ }
- //Global PState Auction
- G_globalPSTgt = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
+ //Global PState Auction
+ G_globalPSComputed = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
- for (q = 0; q < MAX_QUADS; q++)
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if (activeQuads & (QUAD0_BIT_MASK >> q))
+ {
+ if (G_globalPSComputed > G_quadPSComputed[q])
{
- if ((G_quadManagerCME[q] != QUAD_MANAGER_NONE))
- {
- if (G_globalPSTgt > G_localPSTgt[q])
- {
- G_globalPSTgt = G_localPSTgt[q];
- }
- }
+ G_globalPSComputed = G_quadPSComputed[q];
}
+ }
+ }
+ PK_TRACE_DBG("AUCT glbPSCmpted: 0x%x\n", G_globalPSComputed);
+ PK_TRACE_DBG("AUCT: Exit\n");
+}
-#if EPM_P9_TUNING
- asm volatile ("tw 0, 31, 0");
-#endif
-
- //Determine targetVoltage
- G_tgtEVid = p9_pgpe_gppb_intp_vdd_from_ps(G_globalPSTgt, VPD_PT_SET_BIASED_SYSP, VPD_SLOPES_BIASED);
+//
+//p9_pgpe_pstate_apply_clips
+//
+void p9_pgpe_pstate_apply_clips()
+{
+ PK_TRACE_DBG("APCLP: Enter\n");
+ uint32_t q;
+ uint32_t activeQuads = G_quadState1->fields.requested_active_quad;
- //Higher number PState
- if (((int16_t)(G_globalPSTgt) - (int16_t)(G_globalCurrPS)) > 0)
- {
- if ((G_eVidCurr - G_tgtEVid) <= G_gppb->ext_vdd_step_size_mv)
- {
- G_eVidNext = G_tgtEVid;
- G_globalNextPS = G_globalPSTgt;
+ //Apply clips to quad computed
+ PK_TRACE_DBG("APCLP: 0x%x\n", activeQuads);
- for (q = 0; q < MAX_QUADS; q++)
- {
- G_localPSNext[q] = G_localPSTgt[q];
- }
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if (activeQuads & (QUAD0_BIT_MASK >> q))
+ {
+ uint8_t maxPS = G_psClipMax[q];
- done = 1;
- }
- else
+ if (G_wofEnabled == 1)
+ {
+ if (G_wofClip <= G_psClipMax[q])
{
- G_eVidNext = G_eVidCurr - G_gppb->ext_vdd_step_size_mv;
- G_globalNextPS = p9_pgpe_gppb_intp_ps_from_ext_vdd(G_eVidNext);
-
- for (q = 0; q < MAX_QUADS; q++)
- {
- if (G_localPSTgt[q] < G_globalNextPS) //Keep localPS under GlobalPS
- {
- G_localPSNext[q] = G_globalNextPS;
- }
- else
- {
- G_localPSNext[q] = G_localPSTgt[q];
- }
- }
+ maxPS = G_wofClip;
}
+ }
- p9_pgpe_pstate_freq_update();
- p9_pgpe_pstate_update_ext_volt();
+ if (G_quadPSComputed[q] > maxPS)
+ {
+ G_quadPSTarget[q] = maxPS;
}
- //Lower number PState
- else if (((int16_t)(G_globalPSTgt) - (int16_t)(G_globalCurrPS)) < 0)
+ else if(G_quadPSComputed[q] < G_psClipMin[q])
{
- if ((G_tgtEVid - G_eVidCurr) <= G_gppb->ext_vdd_step_size_mv)
- {
- G_eVidNext = G_tgtEVid;
- G_globalNextPS = G_globalPSTgt;
-
- for (q = 0; q < MAX_QUADS; q++)
- {
- G_localPSNext[q] = G_localPSTgt[q];
- }
-
- done = 1;
- }
- else
- {
- G_eVidNext = G_eVidCurr + G_gppb->ext_vdd_step_size_mv;
- G_globalNextPS = p9_pgpe_gppb_intp_ps_from_ext_vdd(G_eVidNext);
-
- for (q = 0; q < MAX_QUADS; q++)
- {
- if (G_localPSTgt[q] < G_globalNextPS) //Keep localPS under GlobalPS
- {
- G_localPSNext[q] = G_globalNextPS;
- }
- else
- {
- G_localPSNext[q] = G_localPSTgt[q];
- }
- }
- }
-
- p9_pgpe_pstate_update_ext_volt();
- p9_pgpe_pstate_freq_update();
+ G_quadPSTarget[q] = G_psClipMin[q];
}
else
{
- for (q = 0; q < MAX_QUADS; q++)
- {
- G_localPSNext[q] = G_localPSTgt[q];
- }
-
- p9_pgpe_pstate_freq_update();
- done = 1;
+ G_quadPSTarget[q] = G_quadPSComputed[q];
}
- }//Step-Loop
-
- pk_irq_vec_restore(&ctx);//Restore interrupts
- }//Thread Loop
-}
-
-
-//
-//p9_pgpe_pstate_update_ext_volt
-//
-void p9_pgpe_pstate_update_ext_volt()
-{
- //Update external voltage
- external_voltage_control_write(G_eVidNext);
-
-#if !EPM_P9_TUNING
- //Do we need the pk_sleep call here now that we only increase voltage
- //by small step-size?
- uint32_t vddDelta;
-
- if (G_eVidCurr > G_eVidNext)
- {
- vddDelta = G_eVidCurr - G_eVidNext;
- }
- else if(G_eVidCurr < G_eVidNext)
- {
- vddDelta = G_eVidNext - G_eVidCurr;
- }
- else
- {
- vddDelta = 1;
- }
-
- pk_sleep(PK_NANOSECONDS((vddDelta)));
-#endif
-
- G_eVidCurr = G_eVidNext;
-}
-
-//
-//frequency_update
-//
-void p9_pgpe_pstate_freq_update()
-{
- int32_t c, q;
- //int rc;
- uint32_t opit4pr;
- uint8_t pendingAcks = 0;
- uint8_t quadPendDBAck[MAX_QUADS];
- pgpe_db0_glb_bcast_t db0;
-
- //Send Doorbell0 to every core by doing a multicast operation
- db0.value = 0;
- db0.fields.msg_id = MSGID_DB0_GLOBAL_ACTUAL_BROADCAST;
- db0.fields.global_actual = G_globalNextPS;
- db0.fields.quad0_ps = G_localPSNext[0];
- db0.fields.quad1_ps = G_localPSNext[1];
- db0.fields.quad2_ps = G_localPSNext[2];
- db0.fields.quad3_ps = G_localPSNext[3];
- db0.fields.quad4_ps = G_localPSNext[4];
- db0.fields.quad5_ps = G_localPSNext[5];
- p9_dd1_db_multicast_wr(PCB_MUTLICAST_GRP1 | CPPM_CMEDB0, db0.value, G_ccsr);
- //GPE_PUTSCOM(PCB_MUTLICAST_GRP1 | CPPM_CMEDB0, db0.value);
-
- for (q = 0; q < MAX_QUADS; q++)
- {
- if (G_quadManagerCME[q] != QUAD_MANAGER_NONE)
- {
- quadPendDBAck[q] = 1;
}
else
{
- quadPendDBAck[q] = 0;
+ G_quadPSTarget[q] = 0xFF;
}
+
+ // PK_TRACE_DBG("APP_CLIP: G_quadPSTarget: 0x%x\n", G_quadPSTarget[q]);
}
- //Wait for all the acks to come
- pendingAcks = 1;
+ //Global PState Auction
+ G_globalPSTarget = G_operating_points[VPD_PT_SET_BIASED_SYSP][POWERSAVE].pstate;
- while (pendingAcks)
+ for (q = 0; q < MAX_QUADS; q++)
{
- //Process acks
- opit4pr = in32(OCB_OPIT4PRA);
-
- for (c = 0; c < MAX_CORES; c++)
+ if (activeQuads & (QUAD0_BIT_MASK >> q))
{
- if (opit4pr & (0x80000000 >> c))
+ if (G_globalPSTarget > G_quadPSTarget[q])
{
- if (quadPendDBAck[QUAD_FROM_CORE(c)])
- {
- quadPendDBAck[QUAD_FROM_CORE(c)] = 0;
- out32(OCB_OPIT4PRA_CLR, 0x80000000 >> c); //Clear out pending bits
- }
- else
- {
- pk_halt();
- }
- }
- }
-
- //Check if any pending left
- pendingAcks = 0;
-
- for (q = 0; q < MAX_QUADS; q++)
- {
- if (quadPendDBAck[q])
- {
- pendingAcks = 1;
+ G_globalPSTarget = G_quadPSTarget[q];
}
}
}
- //Update Current Global and Local PState
- G_globalCurrPS = G_globalNextPS;
-
- for (q = 0; q < MAX_QUADS; q++)
- {
- G_localPSCurr[q] = G_localPSNext[q];
- }
+ PK_TRACE_DBG("APCLP: glbPSTgt: 0x%x\n", G_globalPSTarget);
+ PK_TRACE_DBG("APCLP: Exit\n");
}
//
-//Determine which CMEs are quad manager
+//p9_pgpe_pstate_calc_wof
//
-void p9_pgpe_pstate_get_config()
+void p9_pgpe_pstate_calc_wof()
{
- int32_t q;
- ocb_ccsr_t ccsr;
- ccsr.value = in32(OCB_CCSR);
- G_ccsr = ccsr.value;
+ //\TODO RTC 162896
+ //Figure out how to calculate WOF Clip
+ G_wofClip = 150;
- for (q = 0; q < MAX_QUADS; q++)
- {
- //CME0 is quad manager
- if (ccsr.value & (CCSR_CORE_CONFIG_MASK >> (q * CORES_PER_QUAD)))
- {
- G_quadManagerCME[q] = QUAD_MANAGER_CME0;
- }
- else if (ccsr.value & (CCSR_CORE_CONFIG_MASK >> (q * CORES_PER_QUAD + 2)))
- {
- G_quadManagerCME[q] = QUAD_MANAGER_CME1;
- }
- else
- {
- G_quadManagerCME[q] = QUAD_MANAGER_NONE;
- }
- }
+ p9_pgpe_pstate_apply_clips();
+}
+
+void p9_pgpe_pstate_ipc_rsp_cb_sem_post(ipc_msg_t* msg, void* arg)
+{
+ pk_semaphore_post((PkSemaphore*)arg);
}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h
new file mode 100644
index 00000000..56771f6e
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h
@@ -0,0 +1,74 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.h $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef _P9_PGPE_PSTATE_HEADER_
+#define _P9_PGPE_PSTATE_HEADER_
+
+#include "pk.h"
+#include "ipc_api.h"
+#include "ipc_async_cmd.h"
+
+#define MAX_IPC_PEND_TBL_ENTRIES 9
+#define IPC_PEND_PSTATE_START 0
+#define IPC_PEND_PSTATE_STOP 1
+#define IPC_PEND_SGPE_ACTIVE_CORES_UPDT 2
+#define IPC_PEND_SGPE_ACTIVE_QUADS_UPDT 3
+#define IPC_PEND_CLIP_UPDT 4
+#define IPC_PEND_WOF_CTRL 5
+#define IPC_PEND_WOF_VFRT 6
+#define IPC_PEND_SET_PMCR_REQ 7
+#define IPC_PEND_SGPE_SUSPEND_PSTATES 8
+
+
+#define ALL_QUADS_BIT_MASK QUAD0_BIT_MASK | QUAD1_BIT_MASK | \
+ QUAD2_BIT_MASK | QUAD3_BIT_MASK | \
+ QUAD4_BIT_MASK | QUAD5_BIT_MASK
+#define QUAD0_BIT_MASK 0x80
+#define QUAD1_BIT_MASK 0x40
+#define QUAD2_BIT_MASK 0x20
+#define QUAD3_BIT_MASK 0x10
+#define QUAD4_BIT_MASK 0x8
+#define QUAD5_BIT_MASK 0x4
+
+//
+//Task list entry
+//
+typedef struct ipc_req
+{
+ ipc_msg_t* cmd;
+ uint8_t pending_ack;
+ uint8_t pending_processing;
+} ipc_req_t;
+
+//
+//Functions called by threads
+//
+void p9_pgpe_pstate_init();
+void p9_pgpe_pstate_update(uint8_t* quadPstates);
+void p9_pgpe_pstate_do_auction(uint8_t quadAuctionRequest);
+void p9_pgpe_pstate_calc_wof();
+void p9_pgpe_pstate_apply_clips();
+void p9_pgpe_pstate_ipc_rsp_cb_sem_post(ipc_msg_t* msg, void* arg);
+
+#endif //
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c
new file mode 100644
index 00000000..2bdd43ee
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c
@@ -0,0 +1,783 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_actuate_pstates.c $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "pk.h"
+#include "p9_pgpe.h"
+#include "p9_pgpe_header.h"
+#include "p9_pgpe_pstate.h"
+#include "ipc_api.h"
+#include "ipc_async_cmd.h"
+#include "p9_pgpe_gppb.h"
+#include "pstate_pgpe_occ_api.h"
+//#include "pstate_pgpe_sgpe_api.h"
+#include "ipc_messages.h"
+#include "p9_dd1_doorbell_wr.h"
+#include "avs_driver.h"
+
+//Constants, #defines
+#define CCSR_CORE_CONFIG_MASK 0x80000000
+
+//Local Function Prototypes
+void p9_pgpe_thread_actuate_start();
+void p9_pgpe_thread_actuate_stop();
+void p9_pgpe_wait_cme_db_ack(uint8_t msg_id, uint32_t activeCores);
+void p9_pgpe_thread_actuate_updt_ext_volt(uint32_t tgtEVid);
+void p9_pgpe_thread_actuate_freq_updt(uint32_t activeCores);
+void p9_pgpe_thread_actuate_do_step();
+void p9_pgpe_thread_actuate_init_actual_quad();
+
+//
+//External Global Data
+//
+extern PgpePstateRecord G_pgpe_pstate_record;
+extern uint8_t G_pstatesEnabled; //pstates_enabled/disable
+extern uint8_t G_wofEnabled; //wof enable/disable
+extern uint8_t G_quadPSTarget[MAX_QUADS]; //target Pstate per quad
+extern volatile uint8_t G_globalPSTarget; //target global Pstate
+extern uint8_t G_quadPSCurr[MAX_QUADS]; //target Pstate per quad
+extern volatile uint8_t G_globalPSCurr; //target global Pstate
+extern uint8_t G_quadPSNext[MAX_QUADS]; //target Pstate per quad
+extern uint8_t G_globalPSNext;
+extern uint32_t G_eVidCurr, G_eVidNext;
+extern GlobalPstateParmBlock* G_gppb;
+extern pgpe_header_data_t* G_pgpe_header_data;
+extern uint8_t G_psClipMax[MAX_QUADS],
+ G_psClipMin[MAX_QUADS]; //pmin and pmax clips
+extern uint8_t G_pmcrOwner;
+extern ipc_req_t G_ipc_pend_tbl[MAX_IPC_PEND_TBL_ENTRIES];
+extern uint8_t G_pstate0_dpll_value;
+extern uint32_t G_ext_vrm_inc_rate_mult_usperus;
+extern uint32_t G_ext_vrm_dec_rate_mult_usperus;
+extern VpdOperatingPoint G_operating_points[NUM_VPD_PTS_SET][VPD_PV_POINTS];
+extern quad_state0_t* G_quadState0;
+extern quad_state1_t* G_quadState1;
+extern ipc_async_cmd_t G_ipc_msg_pgpe_sgpe;
+GPE_BUFFER(extern ipcmsg_p2s_ctrl_stop_updates_t G_sgpe_control_updt);
+
+//Payload data non-cacheable region for IPCs sent to SGPE
+//
+//Thread Actuate PStates
+//
+void p9_pgpe_thread_actuate_pstates(void* arg)
+{
+ PK_TRACE_DBG("ACT_TH: Started\n");
+ uint32_t inRange, q = 0;
+ PkMachineContext ctx;
+ uint32_t restore_irq = 0;
+
+ pk_semaphore_create(&(G_pgpe_pstate_record.sem_actuate), 0, 1);
+ pk_semaphore_create(&(G_pgpe_pstate_record.sem_sgpe_wait), 0, 1);
+
+ PK_TRACE_DBG("ACT_TH: Inited\n");
+
+ //Initialize Shared SRAM to a known state
+ p9_pgpe_thread_actuate_init_actual_quad();
+
+#if PGPE_UNIT_TEST
+ out32(OCB_OCCS2, BIT32(30));
+#endif
+
+ //Thread Loop
+ while(1)
+ {
+ PK_TRACE_DBG("ACT_TH: Pend\n");
+ pk_semaphore_pend(&(G_pgpe_pstate_record.sem_actuate), PK_WAIT_FOREVER);
+ wrteei(1);
+
+ //Pstates Start. This call will unmask IPC and block on SGPE ACK
+ p9_pgpe_thread_actuate_start();
+
+ //Loop while Pstate is enabled
+ while(G_pstatesEnabled)
+ {
+ asm volatile ("tw 0, 31, 0");
+
+ if( G_globalPSCurr != G_globalPSTarget ||
+ G_quadPSCurr[0] ^ G_quadPSTarget[0] ||
+ G_quadPSCurr[1] ^ G_quadPSTarget[1] ||
+ G_quadPSCurr[2] ^ G_quadPSTarget[2] ||
+ G_quadPSCurr[3] ^ G_quadPSTarget[3] ||
+ G_quadPSCurr[4] ^ G_quadPSTarget[4] ||
+ G_quadPSCurr[5] ^ G_quadPSTarget[5] )
+ {
+ //We don't want actuate_step to interrupted by any external interrupt.
+ //However, we still want FIT Timer to be active, so we mask of all interrupts
+ //in the OIMR through UIH(by setting UIH priority lvl = 0)
+ pk_critical_section_enter(&ctx);
+ pk_irq_save_and_set_mask(0);
+ pk_critical_section_exit(&ctx);
+
+ restore_irq = 0;
+
+ //Do one actuate step
+ PK_TRACE_DBG("ACT_TH: PSTgt: 0x%x PSCurr: 0x%x\n", G_globalPSTarget, G_globalPSCurr);
+ p9_pgpe_thread_actuate_do_step();
+
+ //evaluate conditions for pending ACKs
+ inRange = 1;
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if (G_psClipMax[q] < G_quadPSCurr[q] ||
+ G_quadPSCurr[q] > G_psClipMin[q])
+ {
+ inRange = 0;
+ }
+ }
+
+ //ACK any pending and unmask IPC interrupt
+ if (inRange == 1)
+ {
+ if (G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_ack == 1)
+ {
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].cmd;
+ ipcmsg_clip_update_t* args = (ipcmsg_clip_update_t*)async_cmd->cmd_data;
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].cmd, IPC_RC_SUCCESS);
+ restore_irq = 1;
+ }
+ }
+
+ //Now, PGPE is done with actuate step, let's
+ //restore the interrupts in OIMR through UIH
+ pk_irq_vec_restore(&ctx);
+ }
+
+ //Check if IPC should be opened again
+ if (restore_irq == 1)
+ {
+ PK_TRACE_DBG("ACT_TH: IRQ Restore\n");
+ restore_irq = 0;
+ pk_irq_vec_restore(&ctx);
+ }
+ }
+
+ //Pstates Stop
+ //This call will unmask IPC and block on SGPE ACK
+ p9_pgpe_thread_actuate_stop();
+ }//Thread loop
+}
+
+//
+//p9_pgpe_thread_actuate_start()
+//
+void p9_pgpe_thread_actuate_start()
+{
+ PK_TRACE_DBG("ACT_TH: Start Enter\n");
+ ocb_ccsr_t ccsr;
+ ccsr.value = in32(OCB_CCSR);
+// PK_TRACE_DBG("ACT_TH: Read CCSR\n");
+ ocb_qcsr_t qcsr;
+ qcsr.value = in32(OCB_QCSR);
+// PK_TRACE_DBG("ACT_TH: Read QCSR\n");
+ uint8_t quadPstates[MAX_QUADS];
+ uint8_t lowestDpll, syncPstate;
+ qppm_dpll_freq_t dpll;
+ PkMachineContext ctx;
+ uint32_t active_conf_cores = 0;
+ uint32_t q;
+
+ //1. Send 'Control Stop Updates' IPC to SGPE
+#if SGPE_IPC_ENABLED == 1
+ uint32_t rc;
+ G_sgpe_control_updt.fields.msg_num = MSGID_PGPE_SGPE_CONTROL_STOP_UPDATES;
+ G_sgpe_control_updt.fields.return_code = 0x0;
+ G_sgpe_control_updt.fields.action = CTRL_STOP_UPDT_ENABLE_QUAD;
+ G_ipc_msg_pgpe_sgpe.cmd_data = &G_sgpe_control_updt;
+ ipc_init_msg(&G_ipc_msg_pgpe_sgpe.cmd,
+ IPC_MSGID_PGPE_SGPE_CONTROL_STOP_UPDATES,
+ p9_pgpe_pstate_ipc_rsp_cb_sem_post,
+ (void*)&G_pgpe_pstate_record.sem_sgpe_wait);
+
+ //send the command
+ PK_TRACE_DBG("ACT_TH: CtrlStopUpdt Sent\n");
+ rc = ipc_send_cmd(&G_ipc_msg_pgpe_sgpe.cmd);
+
+ if(rc)
+ {
+ pk_halt();
+ }
+
+ //Wait for SGPE ACK with alive Quads
+ pk_irq_vec_restore(&ctx);
+ pk_semaphore_pend(&(G_pgpe_pstate_record.sem_sgpe_wait), PK_WAIT_FOREVER);
+
+ PK_TRACE_DBG("ACT_TH: CtrlStopUpdt Resp\n");
+
+ if (G_sgpe_control_updt.fields.return_code == SGPE_PGPE_IPC_RC_SUCCESS)
+ {
+ //Update Shared Memory Region
+ G_quadState0->fields.core_poweron_state = (ccsr.value >> 8);
+ G_quadState1->fields.core_poweron_state = (ccsr.value & 0xFF) << 8;
+ G_quadState1->fields.requested_active_quad = G_sgpe_control_updt.fields.active_quads;
+ }
+ else
+ {
+ pk_halt();
+ }
+
+#else
+ G_quadState0->fields.core_poweron_state = (ccsr.value >> 16);
+ G_quadState1->fields.core_poweron_state = (ccsr.value & 0xFF00);
+
+ for (q = 0; q < MAX_QUADS; q++ )
+ {
+ if ((qcsr.fields.ex_config & (0x800 >> (2 * q))) ||
+ (qcsr.fields.ex_config & (0x400 >> (2 * q))))
+ {
+ G_quadState1->fields.requested_active_quad |= (0x80 >> q) ;
+ }
+ }
+
+ PK_TRACE_DBG("ACT_TH: Shr Mem Updt\n");
+#endif //_SGPE_IPC_ENABLED_
+
+ //2. Read DPLLs
+ lowestDpll = 255;
+ dpll.value = 0;
+ PK_TRACE_DBG("ACT_TH: DPLL0Value=0x%x\n", G_pstate0_dpll_value );
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if((G_quadState1->fields.requested_active_quad & (0x80 >> q)) &&
+ (qcsr.fields.ex_config & (0xC00 >> 2 * q)))
+ {
+#if SIMICS_TUNING == 0
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(QPPM_DPLL_FREQ, q), dpll.value);
+#else
+ dpll.fields.fmax = (G_pstate0_dpll_value
+ - G_operating_points[VPD_PT_SET_BIASED_SYSP][NOMINAL].pstate) << 3;
+#endif
+
+ if ((dpll.fields.fmax >> 3) < lowestDpll )
+ {
+ lowestDpll = dpll.fields.fmax >> 3;
+ }
+
+ PK_TRACE_DBG("ACT_TH: Quad[%d]: DPLL=0x%x\n", q, (dpll.fields.fmax ));
+ active_conf_cores |= (0xF0000000 >> q * 4);
+ }
+ }
+
+ //3. Determine Sync Pstate
+ //
+ //\TODO: Need Greg's Response
+ //Why does HCode Spec says current frequency might not
+ //correspond to frequency of any Pstate? As I understand,
+ //DPLL encoding and frequency/pstate have same step size, so
+ //they should correspond one to one
+ //
+ syncPstate = G_pstate0_dpll_value - lowestDpll;
+
+ //Init Core PStates
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if((qcsr.fields.ex_config & (0xC00 >> 2 * q)))
+ {
+ quadPstates[q] = syncPstate;
+ }
+ else
+ {
+ quadPstates[q] = 0xFF;
+ }
+ }
+
+ p9_pgpe_pstate_update(quadPstates);
+ PK_TRACE_DBG("ACT_TH: Sync Pstate=0x%x\n", syncPstate);
+ PK_TRACE_DBG("ACT_TH: LowDPLL:0x%x\n", q, lowestDpll);
+ PK_TRACE_DBG("ACT_TH: GlblPsTgt:0x%x\n", G_globalPSTarget);
+
+ //4. Set External VRM
+ //\TODO: Need Greg's Response
+ //Why does spec says to read external VDD. Is there
+ //any other reason besides PGPE storing it
+ external_voltage_control_init(&G_eVidCurr);
+#if SIMICS_TUNING
+ G_eVidCurr = p9_pgpe_gppb_intp_vdd_from_ps(G_globalPSTarget, VPD_PT_SET_BIASED_SYSP, VPD_SLOPES_BIASED);
+#endif
+ G_eVidNext = p9_pgpe_gppb_intp_vdd_from_ps(G_globalPSTarget, VPD_PT_SET_BIASED_SYSP, VPD_SLOPES_BIASED);
+ p9_pgpe_thread_actuate_updt_ext_volt(G_eVidNext);
+ G_globalPSCurr = G_globalPSTarget;
+
+ PK_TRACE_DBG("ACT_TH: eVidCurr=0x%x\n", G_eVidCurr);
+ PK_TRACE_DBG("ACT_TH: eVidNext=0x%x\n", G_eVidNext);
+ PK_TRACE_DBG("ACT_TH: GlbPSCurr:0x%x\n", G_globalPSCurr );
+
+ //5. Determine PMCR Owner
+ //We save it off so that CMEs that are currently in STOP11
+ //can be told upon STOP11 Exit
+ PK_TRACE_DBG("ACT_TH: g_oimr_override:0x%llx\n", g_oimr_override);
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)G_ipc_pend_tbl[IPC_PEND_PSTATE_START].cmd;
+ ipcmsg_start_stop_t* args = (ipcmsg_start_stop_t*)async_cmd->cmd_data;
+
+ if (args->pmcr_owner == PMCR_OWNER_HOST)
+ {
+ G_pmcrOwner = PMCR_OWNER_HOST;
+ g_oimr_override &= ~(BIT64(46));
+ out32(OCB_OIMR1_CLR, BIT32(14)); //Enable PCB_INTR_TYPE1
+ }
+ else if (args->pmcr_owner == PMCR_OWNER_OCC)
+ {
+ G_pmcrOwner = PMCR_OWNER_OCC;
+ g_oimr_override |= BIT64(46);
+ out32(OCB_OIMR1_OR, BIT32(14)); //Disable PCB_INTR_TYPE1
+ }
+ else if (args->pmcr_owner == PMCR_OWNER_CHAR)
+ {
+ G_pmcrOwner = PMCR_OWNER_CHAR;
+ g_oimr_override &= ~(BIT64(46));
+ out32(OCB_OIMR1_CLR, BIT32(14)); //Enable PCB_INTR_TYPE1
+ }
+ else
+ {
+ pk_halt();
+ }
+
+ PK_TRACE_DBG("ACT_TH: g_oimr_override:0x%llx\n", g_oimr_override);
+ //Set LMCR for each CME
+#if !SIMICS_TUNING
+
+ //8 Byte write to LMCR register in SIMICS results in error
+ //So, adding a build flag for SIMICS this out. Instead, in SIMICS set this through command line
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if(G_quadState1->fields.requested_active_quad & (0x80 >> q))
+ {
+ //CME0 within this quad
+ if (qcsr.fields.ex_config & (0x800 >> 2 * q))
+ {
+ if (G_pmcrOwner == PMCR_OWNER_HOST)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_LMCR_CLR, q, 0), BIT64(0));
+ }
+ else if (G_pmcrOwner == PMCR_OWNER_OCC)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_LMCR_OR, q, 0), BIT64(0));
+ }
+ }
+
+ //CME1 within this quad
+ if (qcsr.fields.ex_config & (0x400 >> 2 * q))
+ {
+ if (G_pmcrOwner == PMCR_OWNER_HOST)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_LMCR_CLR, q, 1), BIT64(0));
+ }
+ else if (G_pmcrOwner == PMCR_OWNER_OCC)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_LMCR_OR, q, 1), BIT64(0));
+ }
+ }
+ }
+ }
+
+#endif
+
+ //6. Send Doorbell0 to every active CME by doing a multicast operation
+ //
+ //\TODO: Need Greg's Response
+ //Check if this is fine
+ //Slight deviation from Hcode Spec. PGPE sends DB0 to
+ //configured and active cores bc sibling CME reads DB register
+ //to set it's PMSR. They are not communicated by quad manager.
+ //
+ pgpe_db0_start_ps_bcast_t db0;
+ db0.value = 0;
+ db0.fields.msg_id = MSGID_DB0_START_PSTATE_BROADCAST;
+ db0.fields.global_actual = G_globalPSTarget;
+ db0.fields.quad0_ps = G_quadPSTarget[0];
+ db0.fields.quad1_ps = G_quadPSTarget[1];
+ db0.fields.quad2_ps = G_quadPSTarget[2];
+ db0.fields.quad3_ps = G_quadPSTarget[3];
+ db0.fields.quad4_ps = G_quadPSTarget[4];
+ db0.fields.quad5_ps = G_quadPSTarget[5];
+ p9_dd1_db_multicast_wr(PCB_MUTLICAST_GRP1 | CPPM_CMEDB0, db0.value, active_conf_cores);
+ PK_TRACE_DBG("ACT_TH: Mltcast DB0\n");
+ p9_pgpe_wait_cme_db_ack(MSGID_DB0_START_PSTATE_BROADCAST, active_conf_cores);//Wait for ACKs from all QuadManagers
+ PK_TRACE_DBG("ACT_TH: DB0 ACKed\n");
+
+ //7. Enable PStates
+ G_pstatesEnabled = 1;
+
+ //8. Send Pstate Start ACK to OCC
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_START].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_PSTATE_START].cmd, IPC_RC_SUCCESS);
+
+ pk_irq_vec_restore(&ctx);
+ PK_TRACE_DBG("ACT_TH: Start Exit\n");
+}
+
+//
+//p9_pgpe_thread_actuate_stop()
+//
+void p9_pgpe_thread_actuate_stop()
+{
+ PK_TRACE_DBG("ACT_TH: Stop Enter\n");
+ uint32_t q;
+ PkMachineContext ctx;
+ uint32_t active_conf_cores = 0;
+ ocb_qcsr_t qcsr;
+ qcsr.value = in32(OCB_QCSR);
+
+ //Determine active and configured cores
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if(G_quadState1->fields.requested_active_quad & (0x80 >> q))
+ {
+ if (qcsr.fields.ex_config & (0x800 >> 2 * q))
+ {
+ active_conf_cores |= (0xC0000000 >> q * 4);
+ }
+
+ if (qcsr.fields.ex_config & (0x400 >> 2 * q))
+ {
+ active_conf_cores |= (0x30000000 >> q * 4);
+ }
+ }
+ }
+
+ pgpe_db0_stop_ps_bcast_t db0_stop;
+ db0_stop.value = 0;
+ db0_stop.fields.msg_id = MSGID_DB0_STOP_PSTATE_BROADCAST;
+ p9_dd1_db_multicast_wr(PCB_MUTLICAST_GRP1 | CPPM_CMEDB0, db0_stop.value, active_conf_cores);
+
+ //Wait for ACKs from all CMEs
+ p9_pgpe_wait_cme_db_ack(MSGID_DB0_STOP_PSTATE_BROADCAST, active_conf_cores);
+
+#if SGPE_IPC_ENABLED == 1
+ uint32_t rc;
+ //Send "Disable Core & Quad Stop Updates" IPC to SGPE
+ G_sgpe_control_updt.fields.return_code = 0x0;
+ G_sgpe_control_updt.fields.action = CTRL_STOP_UPDT_DISABLE_CORE_QUAD;
+ G_ipc_msg_pgpe_sgpe.cmd_data = &G_sgpe_control_updt;
+ ipc_init_msg(&G_ipc_msg_pgpe_sgpe.cmd,
+ IPC_MSGID_PGPE_SGPE_CONTROL_STOP_UPDATES,
+ p9_pgpe_pstate_ipc_rsp_cb_sem_post,
+ (void*)&G_pgpe_pstate_record.sem_sgpe_wait);
+
+ //send the command
+ rc = ipc_send_cmd(&G_ipc_msg_pgpe_sgpe.cmd);
+
+ if(rc)
+ {
+ pk_halt();
+ }
+
+ //Wait for SGPE ACK with alive Quads
+ pk_irq_vec_restore(&ctx);
+ pk_semaphore_pend(&(G_pgpe_pstate_record.sem_actuate), PK_WAIT_FOREVER);
+
+ if (G_sgpe_control_updt.fields.return_code != SGPE_PGPE_IPC_RC_SUCCESS)
+ {
+ pk_halt();
+ }
+
+#endif// _SGPE_IPC_ENABLED_
+
+ //Send STOP ACK to OCC
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)G_ipc_pend_tbl[IPC_PEND_PSTATE_STOP].cmd;
+ ipcmsg_start_stop_t* args = (ipcmsg_start_stop_t*)async_cmd->cmd_data;
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_STOP].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_PSTATE_STOP].cmd, IPC_RC_SUCCESS);
+
+ pk_irq_vec_restore(&ctx);
+ PK_TRACE_DBG("ACT_TH: Stop Exit\n");
+}
+
+//
+//p9_pgpe_thread_actuate_do_step
+//
+void p9_pgpe_thread_actuate_do_step()
+{
+ PK_TRACE_DBG("ACT_TH: Step Entry\n");
+ uint32_t q;
+ ocb_qcsr_t qcsr;
+ qcsr.value = in32(OCB_QCSR);
+ uint32_t active_conf_cores = 0;
+ uint32_t targetEVid = p9_pgpe_gppb_intp_vdd_from_ps(G_globalPSTarget, VPD_PT_SET_BIASED_SYSP, VPD_SLOPES_BIASED);
+
+ //Determine active and configured cores
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if(G_quadState1->fields.requested_active_quad & (0x80 >> q))
+ {
+ if (qcsr.fields.ex_config & (0x800 >> 2 * q))
+ {
+ active_conf_cores |= (0xC0000000 >> q * 4);
+ }
+
+ if (qcsr.fields.ex_config & (0x400 >> 2 * q))
+ {
+ active_conf_cores |= (0x30000000 >> q * 4);
+ }
+ }
+ }
+
+ //Higher number PState
+ if (((int16_t)(G_globalPSTarget) - (int16_t)(G_globalPSCurr)) > 0)
+ {
+ if ((G_eVidCurr - targetEVid ) <= G_gppb->ext_vrm_step_size_mv)
+ {
+ G_eVidNext = targetEVid;
+ G_globalPSNext = G_globalPSTarget;
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ G_quadPSNext[q] = G_quadPSTarget[q];
+ }
+ }
+ else
+ {
+ G_eVidNext = G_eVidCurr - G_gppb->ext_vrm_step_size_mv;
+ G_globalPSNext = p9_pgpe_gppb_intp_ps_from_ext_vdd(G_eVidNext);
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if (G_quadPSTarget[q] > G_globalPSNext) //Keep localPS under GlobalPS
+ {
+ G_quadPSNext[q] = G_globalPSNext;
+ }
+ else
+ {
+ G_quadPSNext[q] = G_quadPSTarget[q];
+ }
+ }
+ }
+
+ p9_pgpe_thread_actuate_freq_updt(active_conf_cores);
+ p9_pgpe_thread_actuate_updt_ext_volt(targetEVid);
+ }
+ //Lower number PState
+ else if (((int16_t)(G_globalPSTarget) - (int16_t)(G_globalPSCurr)) < 0)
+ {
+ if ((targetEVid - G_eVidCurr) <= G_gppb->ext_vrm_step_size_mv)
+ {
+ G_eVidNext = targetEVid;
+ G_globalPSNext = G_globalPSTarget;
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ G_quadPSNext[q] = G_quadPSTarget[q];
+ }
+ }
+ else
+ {
+ G_eVidNext = G_eVidCurr + G_gppb->ext_vrm_step_size_mv;
+ G_globalPSNext = p9_pgpe_gppb_intp_ps_from_ext_vdd(G_eVidNext);
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if (G_quadPSTarget[q] < G_globalPSNext) //Keep localPS under GlobalPS
+ {
+ G_quadPSNext[q] = G_globalPSNext;
+ }
+ else
+ {
+ G_quadPSNext[q] = G_quadPSTarget[q];
+ }
+ }
+ }
+
+ p9_pgpe_thread_actuate_updt_ext_volt(targetEVid);
+ p9_pgpe_thread_actuate_freq_updt(active_conf_cores);
+ }
+ else
+ {
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ G_quadPSNext[q] = G_quadPSTarget[q];
+ }
+
+ p9_pgpe_thread_actuate_freq_updt(active_conf_cores);
+ }
+
+ //Update current
+ G_globalPSCurr = G_globalPSNext;
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if(G_quadState1->fields.requested_active_quad & (0x80 >> q) &&
+ (qcsr.fields.ex_config & (0xC00 >> 2 * q)))
+ {
+ G_quadPSCurr[q] = G_quadPSNext[q];
+ }
+ }
+
+ //Update Shared SRAM
+ G_quadState0->fields.quad0_pstate = G_quadPSCurr[0];
+ G_quadState0->fields.quad1_pstate = G_quadPSCurr[1];
+ G_quadState0->fields.quad2_pstate = G_quadPSCurr[2];
+ G_quadState0->fields.quad3_pstate = G_quadPSCurr[3];
+ G_quadState1->fields.quad4_pstate = G_quadPSCurr[4];
+ G_quadState1->fields.quad5_pstate = G_quadPSCurr[5];
+
+ PK_TRACE_DBG("ACT_TH: Step Exit\n");
+}
+
+//
+//p9_pgpe_thread_actuate_updt_ext_volt
+//
+//Update External VRM to G_eVidNext
+void p9_pgpe_thread_actuate_updt_ext_volt(uint32_t tgtEVid)
+{
+#if !EPM_P9_TUNING
+ uint32_t delay_us;
+
+ //Decreasing
+ if (G_eVidNext < G_eVidCurr)
+ {
+ delay_us = (G_eVidCurr - G_eVidNext) *
+ G_ext_vrm_dec_rate_mult_usperus;
+ }
+ //Increasing
+ else if(G_eVidNext > G_eVidCurr)
+ {
+ delay_us = (G_eVidNext - G_eVidCurr) *
+ G_ext_vrm_inc_rate_mult_usperus;
+ }
+
+#endif
+
+ //Update external voltage
+ external_voltage_control_write(G_eVidNext);
+
+#if !EPM_P9_TUNING
+
+ //Delay for delay_us
+ if (delay_us > 0)
+ {
+ pk_sleep(PK_MICROSECONDS((delay_us)));
+ }
+
+ if(G_eVidNext == tgtEVid)
+ {
+ pk_sleep(PK_MICROSECONDS((G_gppd->ext_vrm_stabilization_time_us)));
+ }
+
+#endif
+
+ G_eVidCurr = G_eVidNext;
+}
+
+//
+//Frequency Update
+//
+//Sends a DB0 to all active CMEs, so that Quad Managers(CMEs) update DPLL
+void p9_pgpe_thread_actuate_freq_updt(uint32_t activeCores)
+{
+ PK_TRACE_DBG("ACT_TH: Freq Updt Enter\n");
+ pgpe_db0_glb_bcast_t db0;
+ db0.value = 0;
+ db0.fields.msg_id = MSGID_DB0_GLOBAL_ACTUAL_BROADCAST;
+ db0.fields.global_actual = G_globalPSNext;
+ db0.fields.quad0_ps = G_quadPSNext[0];
+ db0.fields.quad1_ps = G_quadPSNext[1];
+ db0.fields.quad2_ps = G_quadPSNext[2];
+ db0.fields.quad3_ps = G_quadPSNext[3];
+ db0.fields.quad4_ps = G_quadPSNext[4];
+ db0.fields.quad5_ps = G_quadPSNext[5];
+ p9_dd1_db_multicast_wr(PCB_MUTLICAST_GRP1 | CPPM_CMEDB0, db0.value, activeCores);
+ p9_pgpe_wait_cme_db_ack(MSGID_DB0_GLOBAL_ACTUAL_BROADCAST, activeCores);//Wait for ACKs from all CMEs
+ PK_TRACE_DBG("ACT_TH: Freq Updt Exit\n");
+}
+
+
+//
+//Wait for CME to ack DB0
+//
+void p9_pgpe_wait_cme_db_ack(uint8_t msg_id, uint32_t active_conf_cores)
+{
+ int32_t c, q;
+ uint32_t opit4pr;
+ uint8_t pendingAcks = 0;
+ uint8_t quadPendDBAck[MAX_QUADS];
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if (active_conf_cores & (0xF0000000 >> (q * 4)))
+ {
+ quadPendDBAck[q] = 1;
+ }
+ else
+ {
+ quadPendDBAck[q] = 0;
+ }
+ }
+
+ //Wait for all the acks to come
+ pendingAcks = 1;
+
+ while (pendingAcks)
+ {
+ //Process acks
+ opit4pr = in32(OCB_OPIT4PRA);
+
+ for (c = 0; c < MAX_CORES; c++)
+ {
+ if (opit4pr & (CCSR_CORE_CONFIG_MASK >> c))
+ {
+ if (quadPendDBAck[QUAD_FROM_CORE(c)])
+ {
+ quadPendDBAck[QUAD_FROM_CORE(c)] = 0;
+ out32(OCB_OPIT4PRA_CLR, CCSR_CORE_CONFIG_MASK >> c); //Clear out pending bits
+ }
+ else
+ {
+ pk_halt();
+ }
+ }
+ }
+
+ //Check if any pending left
+ pendingAcks = 0;
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if (quadPendDBAck[q])
+ {
+ pendingAcks = 1;
+ }
+ }
+ }
+}
+
+
+
+
+void p9_pgpe_thread_actuate_init_actual_quad()
+{
+ G_quadState0->fields.quad0_pstate = 0xff;
+ G_quadState0->fields.quad1_pstate = 0xff;
+ G_quadState0->fields.quad2_pstate = 0xff;
+ G_quadState0->fields.quad3_pstate = 0xff;
+ G_quadState0->fields.core_poweron_state = 0;
+
+ G_quadState1->fields.quad4_pstate = 0xff;
+ G_quadState1->fields.quad5_pstate = 0xff;
+ G_quadState1->fields.core_poweron_state = 0x0;
+ G_quadState1->fields.requested_active_quad = 0x0;
+}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c
new file mode 100644
index 00000000..a800ab97
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c
@@ -0,0 +1,574 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_thread_process_requests.c $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "p9_pgpe.h"
+#include "gpehw_common.h"
+#include "p9_pgpe_pstate.h"
+#include "pstate_pgpe_occ_api.h"
+//#include "pstate_pgpe_sgpe_api.h"
+#include "ipc_messages.h"
+#include "ipc_api.h"
+#include "ipc_async_cmd.h"
+#include "p9_pgpe_header.h"
+
+//
+//External Global Data
+//
+extern PgpePstateRecord G_pgpe_pstate_record;
+extern pgpe_header_data_t* G_pgpe_header_data;
+extern uint8_t G_pstatesEnabled; //pstates_enabled/disable
+extern uint8_t G_wofEnabled; //pstates_enabled/disable
+extern uint8_t G_wofPending; //wof enable pending
+extern VFRT_Hcode_t* G_vfrt_ptr;
+extern ipc_req_t G_ipc_pend_tbl[MAX_IPC_PEND_TBL_ENTRIES];
+extern uint8_t G_psClipMax[MAX_QUADS],
+ G_psClipMin[MAX_QUADS]; //pmin and pmax clips
+extern uint8_t G_coresPSRequest[MAX_CORES]; //per core requested pstate
+extern uint32_t G_already_sem_posted;
+extern quad_state0_t* G_quadState0;
+extern quad_state1_t* G_quadState1;
+extern pgpe_header_data_t* G_pgpe_header_data;
+extern ipc_async_cmd_t G_ipc_msg_pgpe_sgpe;
+GPE_BUFFER(extern ipcmsg_p2s_ctrl_stop_updates_t G_sgpe_control_updt);
+
+//
+//Local Function Prototypes
+//
+void p9_pgpe_process_sgpe_updt_active_cores();
+void p9_pgpe_process_sgpe_updt_active_quads();
+void p9_pgpe_process_clip_updt();
+void p9_pgpe_process_wof_ctrl();
+void p9_pgpe_process_wof_vfrt();
+void p9_pgpe_process_set_pmcr_req();
+
+//
+//Process Request Thread
+//
+void p9_pgpe_thread_process_requests(void* arg)
+{
+ PK_TRACE_DBG("PROCTH:Started\n");
+
+ uint32_t restore_irq;
+ PkMachineContext ctx;
+
+ //Initialization
+ pk_semaphore_create(&(G_pgpe_pstate_record.sem_process_req), 0, 1);
+
+ //IPC Init
+ p9_pgpe_ipc_init();
+
+ //Set OCC_FLAG[PGPE_ACTIVE]
+ out32(OCB_OCCFLG_OR, BIT32(4));
+#if EPM_P9_TUNING
+ asm volatile ("tw 0, 31, 0");
+#endif
+
+ PK_TRACE_DBG("PROCTH:Inited\n");
+
+ while(1)
+ {
+ //pend on semaphore
+ pk_semaphore_pend(&(G_pgpe_pstate_record.sem_process_req), PK_WAIT_FOREVER);
+ wrteei(1);
+
+ G_already_sem_posted = 0;
+ restore_irq = 1;
+
+ PK_TRACE_DBG("PROCTH: Process Task\n");
+
+ //Go through IPC Pending Table
+ if (G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_processing)
+ {
+ p9_pgpe_process_sgpe_updt_active_cores();
+
+ if(G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_ack == 1)
+ {
+ restore_irq = 0;
+ }
+ }
+
+ if (G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].pending_processing)
+ {
+ p9_pgpe_process_sgpe_updt_active_quads();
+
+ if(G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].pending_ack == 1)
+ {
+ restore_irq = 0;
+ }
+ }
+
+ if (G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_processing)
+ {
+ p9_pgpe_process_clip_updt();
+
+ if(G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_ack == 1)
+ {
+ restore_irq = 0;
+ }
+ }
+
+ if (G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_processing)
+ {
+ p9_pgpe_process_wof_ctrl();
+
+ if(G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_ack == 1)
+ {
+ restore_irq = 0;
+ }
+ }
+
+ if (G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].pending_processing)
+ {
+ p9_pgpe_process_wof_vfrt();
+
+ if(G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].pending_ack == 1)
+ {
+ restore_irq = 0;
+ }
+ }
+
+ if (G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].pending_processing)
+ {
+ p9_pgpe_process_set_pmcr_req();
+
+ if(G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].pending_ack == 1)
+ {
+ restore_irq = 0;
+ }
+ }
+
+ //Pstate START/STOP IPCs are processed and acked in actuate thread,
+ //so don't call pk_irq_vec_restore if they are pending.
+ if(G_ipc_pend_tbl[IPC_PEND_PSTATE_STOP].pending_ack == 1 ||
+ G_ipc_pend_tbl[IPC_PEND_PSTATE_STOP].pending_ack == 1 )
+ {
+ restore_irq = 0;
+ }
+
+ //Restore IPC if no pending acks. Otherwise, actuate thread will
+ //eventuall restore IPC interrupt
+ if (restore_irq == 1)
+ {
+ PK_TRACE_DBG("PROCTH: IRQ Restore\n");
+ pk_irq_vec_restore(&ctx);
+ }
+ }
+}
+
+//
+//p9_pgpe_process_sgpe_updt_active_cores
+//
+void p9_pgpe_process_sgpe_updt_active_cores()
+{
+ PK_TRACE_DBG("PROCTH: Core Updt Entry\n");
+
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].cmd;
+ ipcmsg_s2p_update_active_cores_t* args = (ipcmsg_s2p_update_active_cores_t*)async_cmd->cmd_data;
+
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_processing = 0;
+
+ //Active core updates should only be received if both
+ //Pstate and WOF are enabled
+ if(G_pstatesEnabled == 0 || G_wofEnabled == 0)
+ {
+ if(G_pstatesEnabled == 0)
+ {
+ args->fields.return_code = PGPE_RC_PSTATES_DISABLED;
+ }
+ else
+ {
+ args->fields.return_code = PGPE_WOF_RC_NOT_ENABLED;
+ }
+
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+
+ //Update Shared Memory Region
+ G_quadState0->fields.core_poweron_state = (args->fields.active_cores >> 8);
+ G_quadState1->fields.core_poweron_state = (args->fields.active_cores & 0xFF) << 8;
+
+ //Do auction
+ p9_pgpe_pstate_do_auction(ALL_QUADS_BIT_MASK);
+
+ //If entry type then send ACK to SGPE immediately
+ //Otherwise, wait to ACK until WOF Clip has been applied(from actuate_pstate thread)
+ if (args->fields.update_type == UPDATE_ACTIVE_TYPE_ENTRY)
+ {
+ args->fields.return_code = PGPE_RC_SUCCESS;
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_CORES_UPDT].cmd, IPC_RC_SUCCESS);
+ }
+
+ p9_pgpe_pstate_calc_wof();
+ }
+
+ PK_TRACE_DBG("PROCTH: Core Updt Exit\n");
+}
+
+//
+//p9_pgpe_process_sgpe_updt_active_quads
+//
+void p9_pgpe_process_sgpe_updt_active_quads()
+{
+ PK_TRACE_DBG("PROCTH: Quad Updt Entry\n");
+
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].cmd;
+ ipcmsg_s2p_update_active_quads_t* args = (ipcmsg_s2p_update_active_quads_t*)async_cmd->cmd_data;
+
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].pending_processing = 0;
+
+ //Active quad updates should only be received if Pstates are enabled
+ if(G_pstatesEnabled == 0)
+ {
+ args->fields.return_code = PGPE_RC_PSTATES_DISABLED;
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+ //Update Shared Memory Region
+ G_quadState1->fields.requested_active_quad = args->fields.requested_quads;
+
+ //Do auction
+ p9_pgpe_pstate_do_auction(ALL_QUADS_BIT_MASK);
+
+ if(G_wofEnabled == 1)
+ {
+ //Set OCCFLG[REQUESTED_ACTIVE_QUAD_UPDATE]
+ GPE_PUTSCOM(OCB_OCCFLG_OR, BIT32(30));
+
+ //If entry type then send ACK to SGPE immediately
+ //Otherwise, wait to ACK until WOF-VFRT updated is received from OCC
+ if (args->fields.update_type == UPDATE_ACTIVE_TYPE_ENTRY)
+ {
+ args->fields.return_code = PGPE_RC_SUCCESS;
+ G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_SGPE_ACTIVE_QUADS_UPDT].cmd, IPC_RC_SUCCESS);
+ }
+ }
+ else
+ {
+ p9_pgpe_pstate_apply_clips();
+ }
+ }
+
+ PK_TRACE_DBG("PROCTH: Quad Updt Exit\n");
+}
+
+//
+//p9_pgpe_process_clip_updt
+//
+void p9_pgpe_process_clip_updt()
+{
+ PK_TRACE_DBG("PROCTH: Clip Updt Entry\n");
+
+ uint32_t q;
+ uint32_t rc;
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].cmd;
+ ipcmsg_clip_update_t* args = (ipcmsg_clip_update_t*)async_cmd->cmd_data;
+
+ G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_processing = 0;
+
+ if(G_pgpe_header_data->pgpeflags & OCC_IPC_IMMEDIATE_RESP)
+ {
+ PK_TRACE_DBG("PROCTH: Clip Updt Imme\n");
+ G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_ack = 0;
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ G_psClipMax[q] = args->ps_val_clip_max[q];
+ G_psClipMin[q] = args->ps_val_clip_min[q];
+ }
+
+ p9_pgpe_pstate_apply_clips(&G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT]);
+
+ if (G_pstatesEnabled == 0)
+ {
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].pending_ack = 0;
+ rc = ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_CLIP_UPDT].cmd, IPC_RC_SUCCESS);
+
+ if (rc != IPC_RC_SUCCESS)
+ {
+ pk_halt();
+ }
+ else
+ {
+ PK_TRACE_DBG("PROCTH: Clip Upd Acked\n");
+ }
+ }
+ }
+
+ PK_TRACE_DBG("PROCTH: Clip Upd Exit\n");
+}
+
+//
+//p9_pgpe_process_wof_ctrl
+//
+void p9_pgpe_process_wof_ctrl()
+{
+ PK_TRACE_DBG("PROCTH: WOF Ctrl Enter\n");
+
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].cmd;
+ ipcmsg_wof_control_t* args = (ipcmsg_wof_control_t*)async_cmd->cmd_data;
+
+ G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_processing = 0;
+
+ if(G_pgpe_header_data->pgpeflags & OCC_IPC_IMMEDIATE_RESP)
+ {
+ G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_ack = 0;
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+ if(G_pstatesEnabled == 0 )
+ {
+ args->msg_cb.rc = PGPE_RC_PSTATES_DISABLED;
+ G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+ //If WOF ON
+ if (args->action == PGPE_ACTION_WOF_ON)
+ {
+ if(G_wofEnabled == 1)
+ {
+ G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+ G_wofPending = 1;
+ }
+ }
+ else if (args->action == PGPE_ACTION_WOF_OFF)
+ {
+ if(G_wofEnabled == 0)
+ {
+ G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_WOF_CTRL].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+#if SGPE_IPC_ENABLED == 1
+ uint32_t rc;
+ PkMachineContext ctx;
+ //Send "Disable Core Stop Updates" IPC to SGPE
+ G_sgpe_control_updt.fields.return_code = 0x0;
+ G_sgpe_control_updt.fields.action = CTRL_STOP_UPDT_DISABLE_CORE;
+ G_ipc_msg_pgpe_sgpe.cmd_data = &G_sgpe_control_updt;
+ ipc_init_msg(&G_ipc_msg_pgpe_sgpe.cmd,
+ IPC_MSGID_PGPE_SGPE_CONTROL_STOP_UPDATES,
+ p9_pgpe_pstate_ipc_rsp_cb_sem_post,
+ (void*)&G_pgpe_pstate_record.sem_sgpe_wait);
+
+ //send the command
+ rc = ipc_send_cmd(&G_ipc_msg_pgpe_sgpe.cmd);
+
+ if(rc)
+ {
+ pk_halt();
+ }
+
+ //Wait for SGPE ACK with alive Quads
+ pk_irq_vec_restore(&ctx);
+ pk_semaphore_pend(&(G_pgpe_pstate_record.sem_actuate), PK_WAIT_FOREVER);
+
+ if (G_sgpe_control_updt.fields.return_code == SGPE_PGPE_IPC_RC_SUCCESS)
+ {
+ //Update Shared Memory Region
+ G_quadState0->fields.core_poweron_state = G_sgpe_control_updt.fields.active_cores >> 8;
+ G_quadState1->fields.core_poweron_state = G_sgpe_control_updt.fields.active_cores & 0xFF;
+ G_quadState1->fields.requested_active_quad = G_sgpe_control_updt.fields.active_quads;
+ }
+ else
+ {
+ pk_halt();
+ }
+
+#endif// _SGPE_IPC_ENABLED_
+ }
+ }
+ }
+ }
+
+ PK_TRACE_DBG("PROCTH: WOF Ctrl Exit\n");
+}
+
+//
+//p9_pgpe_process_wof_vfrt
+//
+void p9_pgpe_process_wof_vfrt()
+{
+ PK_TRACE_DBG("PROCTH: WOF VFRT Enter\n");
+
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].cmd;
+ ipcmsg_wof_vfrt_t* args = (ipcmsg_wof_vfrt_t*)async_cmd->cmd_data;
+
+ G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].pending_processing = 0;
+
+ if(G_pgpe_header_data->pgpeflags & OCC_IPC_IMMEDIATE_RESP)
+ {
+ G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].pending_ack = 0;
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+ if(G_pstatesEnabled == 0 || (G_wofEnabled == 0 && G_wofPending == 0))
+ {
+ G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].pending_ack = 0;
+ args->msg_cb.rc = PGPE_RC_PSTATES_DISABLED;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+ //Update VFRT pointer
+ G_vfrt_ptr = args->vfrt_ptr;
+
+ //If active_quads field of this IPC matches requested active quads
+ //in Shared SRAM, then clear OCCFLG[REQUESTED_ACTIVE_QUAD_UPDATE]
+ if (args->active_quads == G_quadState1->fields.requested_active_quad)
+ {
+ GPE_PUTSCOM(OCB_OCCFLG_CLR, BIT32(30));
+ p9_pgpe_pstate_calc_wof();
+ }
+
+ if (G_wofPending == 1)
+ {
+ G_wofEnabled = 1;
+ G_wofPending = 0;
+
+#if SGPE_IPC_ENABLED == 1
+ uint32_t rc;
+ PkMachineContext ctx;
+ //Send "Disable Core Stop Updates" IPC to SGPE
+ G_sgpe_control_updt.fields.return_code = 0x0;
+ G_sgpe_control_updt.fields.action = CTRL_STOP_UPDT_DISABLE_CORE;
+ G_ipc_msg_pgpe_sgpe.cmd_data = &G_sgpe_control_updt;
+ ipc_init_msg(&G_ipc_msg_pgpe_sgpe.cmd,
+ IPC_MSGID_PGPE_SGPE_CONTROL_STOP_UPDATES,
+ p9_pgpe_pstate_ipc_rsp_cb_sem_post,
+ (void*)&G_pgpe_pstate_record.sem_sgpe_wait);
+
+ //send the command
+ rc = ipc_send_cmd(&G_ipc_msg_pgpe_sgpe.cmd);
+
+ if(rc)
+ {
+ pk_halt();
+ }
+
+ //Wait for SGPE ACK with alive Quads
+ pk_irq_vec_restore(&ctx);
+ pk_semaphore_pend(&(G_pgpe_pstate_record.sem_actuate), PK_WAIT_FOREVER);
+
+ if (G_sgpe_control_updt.fields.return_code == SGPE_PGPE_IPC_RC_SUCCESS)
+ {
+ //Update Shared Memory Region
+ G_quadState0->fields.core_poweron_state = G_sgpe_control_updt.fields.active_cores >> 8;
+ G_quadState1->fields.core_poweron_state = G_sgpe_control_updt.fields.active_cores & 0xFF;
+ G_quadState1->fields.requested_active_quad = G_sgpe_control_updt.fields.active_quads;
+ }
+ else
+ {
+ pk_halt();
+ }
+
+#endif// _SGPE_IPC_ENABLED_
+ }
+
+ G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].pending_ack = 0;
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_WOF_VFRT].cmd, IPC_RC_SUCCESS);
+ }
+ }
+
+ PK_TRACE_DBG("PROCTH: WOF VFRT Exit\n");
+}
+
+//
+//p9_pgpe_process_set_pmcr_req
+//
+void p9_pgpe_process_set_pmcr_req()
+{
+ PK_TRACE_DBG("PROCTH: Set PMCR Enter\n");
+
+ uint32_t q, c;
+ ipc_async_cmd_t* async_cmd = (ipc_async_cmd_t*)G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].cmd;
+ ipcmsg_set_pmcr_t* args = (ipcmsg_set_pmcr_t*)async_cmd->cmd_data;
+
+ G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].pending_processing = 0;
+
+ if(G_pgpe_header_data->pgpeflags & OCC_IPC_IMMEDIATE_RESP)
+ {
+ G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].pending_ack = 0;
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+ if (G_pstatesEnabled == 0 )
+ {
+ PK_TRACE_DBG("PROCTH: Pstates Disabled\n");
+ args->msg_cb.rc = PGPE_RC_PSTATES_DISABLED;
+ G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].pending_ack = 0;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].cmd, IPC_RC_SUCCESS);
+ }
+ else
+ {
+ PK_TRACE_DBG("PROCTH: Upd coresPSReq\n");
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ for (c = (q * CORES_PER_QUAD); c < (q + 1)*CORES_PER_QUAD; c++)
+ {
+ G_coresPSRequest[c] = (args->pmcr[q] >> 48) & 0x00FF;
+ }
+
+ PK_TRACE_DBG("PROCTH: coresPSReq: 0x%x\n", G_coresPSRequest[q * CORES_PER_QUAD]);
+ }
+
+ p9_pgpe_pstate_do_auction(ALL_QUADS_BIT_MASK);
+ p9_pgpe_pstate_apply_clips();
+
+ //Send ACK to OCC
+ G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].pending_ack = 0;
+ args->msg_cb.rc = PGPE_RC_SUCCESS;
+ ipc_send_rsp(G_ipc_pend_tbl[IPC_PEND_SET_PMCR_REQ].cmd, IPC_RC_SUCCESS);
+ }
+ }
+
+ PK_TRACE_DBG("PROCTH: Set PMCR Exit\n");
+}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pk_app_cfg.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pk_app_cfg.h
index c6e5b84a..818abb00 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pk_app_cfg.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pk_app_cfg.h
@@ -38,9 +38,12 @@
#define EPM_P9_TUNING 1
#define SIMICS_TUNING 0
#define GEN_PSTATE_TBL 0
-#define MIMIC_BOOT_TEMP 1
+#define USE_BOOT_TEMP 1
+#define BOOT_TEMP_SET_FULL_OCC_IPC_FUNC 1
#define DEV_DEBUG 1
+#define PGPE_UNIT_TEST 1
#define PK_TRACE_TIMER_OUTPUT 0
+#define SGPE_IPC_ENABLED 0
///This application uses IPC code
#define GLOBAL_CFG_USE_IPC
@@ -66,6 +69,29 @@
#endif /* APPCFG_USE_EXT_TIMEBASE */
// --------------------
+#if PK_TRACE_LEVEL == 0 /*No TRACEs*/
+ #define PK_TRACE_ENABLE 0
+ #define PK_KERNEL_TRACE_ENABLE 0
+#elif PK_TRACE_LEVEL == 1 /*only PK_TRACE_INF*/
+ #define PK_TRACE_ENABLE 1
+ #define PK_TRACE_DBG_SUPPRESS 1
+ #define PK_TRACE_CRIT_ENABLE 1
+ #define PK_TRACE_CKPT_ENABLE 0
+ #define PK_KERNEL_TRACE_ENABLE 0
+#elif PK_TRACE_LEVEL == 2 /*only PK_TRACE_INF+DBG+KERNEL*/
+ #define PK_TRACE_ENABLE 1
+ #define PK_TRACE_DBG_SUPPRESS 1
+ #define PK_TRACE_CRIT_ENABLE 1
+ #define PK_TRACE_CKPT_ENABLE 1
+ #define PK_KERNEL_TRACE_ENABLE 1
+#else /*All TRACEs*/
+ #define PK_TRACE_ENABLE 1
+ #define PK_TRACE_DBG_SUPPRESS 0
+ #define PK_TRACE_CRIT_ENABLE 1
+ #define PK_TRACE_CKPT_ENABLE 1
+ #define PK_KERNEL_TRACE_ENABLE 1
+#endif
+
// GPE2 is the PGPE and is the route owner for now.
// (Change this to #3 when pulling in SGPE)
@@ -97,6 +123,6 @@
OCCHW_IRQ_CHECK_STOP_GPE2 OCCHW_IRQ_TYPE_EDGE OCCHW_IRQ_POLARITY_RISING OCCHW_IRQ_MASKED \
OCCHW_IRQ_IPI2_HI_PRIORITY OCCHW_IRQ_TYPE_EDGE OCCHW_IRQ_POLARITY_RISING OCCHW_IRQ_MASKED \
OCCHW_IRQ_IPI2_LO_PRIORITY OCCHW_IRQ_TYPE_EDGE OCCHW_IRQ_POLARITY_RISING OCCHW_IRQ_MASKED \
- OCCHW_IRQ_PMC_PCB_INTR_TYPE1_PENDING OCCHW_IRQ_TYPE_LEVEL OCCHW_IRQ_POLARITY_HI OCCHW_IRQ_MASKED \
+ OCCHW_IRQ_PMC_PCB_INTR_TYPE1_PENDING OCCHW_IRQ_TYPE_LEVEL OCCHW_IRQ_POLARITY_HI OCCHW_IRQ_MASKED \
OCCHW_IRQ_PMC_PCB_INTR_TYPE4_PENDING OCCHW_IRQ_TYPE_LEVEL OCCHW_IRQ_POLARITY_HI OCCHW_IRQ_MASKED
#endif /*__PK_APP_CFG_H__*/
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk
index 7fc5607c..73eee021 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk
@@ -79,6 +79,11 @@ OBJS+=$(TOP_OBJECTS)
$(IMAGE)_TRACE_HASH_PREFIX := $(shell echo $(IMAGE) | md5sum | cut -c1-4 \
| xargs -i printf "%d" 0x{})
+# Options for PK_TRACE
+$(IMAGE)_COMMONFLAGS+= -DPK_TRACE_LEVEL=0
+$(IMAGE)_COMMONFLAGS+= -DPK_TRACE_TIMER_OUTPUT=0
+
+
#Note: Flags are resolved very late - so local variables can't be
# used to build them
$(IMAGE)_COMMONFLAGS+= -DPK_TIMER_SUPPORT=1
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/topfiles.mk b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/topfiles.mk
index 74711295..a21c605e 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/topfiles.mk
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/topfiles.mk
@@ -31,8 +31,12 @@ TOP-C-SOURCES = p9_pgpe_pstate.c \
p9_pgpe_gppb.c \
p9_pgpe_gen_pstate_info.c \
p9_pgpe_header.c \
- p9_pgpe_ipc.c \
- ipc_func_tables.c
+ ipc_func_tables.c \
+ p9_pgpe_thread_actuate_pstates.c \
+ p9_pgpe_thread_process_requests.c \
+ p9_pgpe_ipc_handlers.c \
+ p9_pgpe_irq_handlers.c
+
TOP-S-SOURCES =
TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-S-SOURCES:.S=.o)
OpenPOWER on IntegriCloud