summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRahul Batra <rbatra@us.ibm.com>2016-07-15 16:54:45 -0500
committerJoshua Hunsberger <jahunsbe@us.ibm.com>2017-10-23 16:30:34 -0500
commit336fd618d1bc9daa00d6151ba020966013cf1775 (patch)
treee16ddc1e8f28226b0d5280b29ff15a6c0c58e9e5
parent4c7a55edb33fe9198f99f5bcfacf75c8a04b6ca8 (diff)
downloadtalos-hcode-336fd618d1bc9daa00d6151ba020966013cf1775.tar.gz
talos-hcode-336fd618d1bc9daa00d6151ba020966013cf1775.zip
PState Initial Drop
Change-Id: I5dedbd16a9ec1d9c698e26e562f833a2c61eb31a Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/27116 Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c41
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h38
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c96
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.c965
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.h336
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/topfiles.mk6
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/Makefile27
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.c2
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.h9
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe.h67
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.c199
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.h144
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_main.c142
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c663
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pk_app_cfg.h37
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/pstate_gpe.mk2
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/topfiles.mk2
17 files changed, 1789 insertions, 987 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c
index b670ea59..375724c8 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c
@@ -52,7 +52,9 @@ const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2] =
/* 0: IDX_PRTY_VEC 1: IDX_MASK_VEC */
{
IRQ_VEC_PRTY0_CME,
- IRQ_VEC_PRTY6_CME | /* 0: IDX_PRTY_LVL_HIPRTY */
+ IRQ_VEC_PRTY8_CME | /* 0: IDX_PRTY_LVL_HIPRTY */
+ IRQ_VEC_PRTY7_CME |
+ IRQ_VEC_PRTY6_CME |
IRQ_VEC_PRTY5_CME |
IRQ_VEC_PRTY4_CME |
IRQ_VEC_PRTY3_CME |
@@ -62,7 +64,9 @@ const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2] =
},
{
IRQ_VEC_PRTY1_CME,
- IRQ_VEC_PRTY6_CME | /* 1: IDX_PRTY_LVL_BCE_DB3 */
+ IRQ_VEC_PRTY8_CME | /* 1: IDX_PRTY_LVL_BCE_DB3 */
+ IRQ_VEC_PRTY7_CME |
+ IRQ_VEC_PRTY6_CME |
IRQ_VEC_PRTY5_CME |
IRQ_VEC_PRTY4_CME |
IRQ_VEC_PRTY3_CME |
@@ -71,7 +75,9 @@ const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2] =
},
{
IRQ_VEC_PRTY2_CME,
- IRQ_VEC_PRTY6_CME | /* 2: IDX_PRTY_LVL_WAKE_DB2 */
+ IRQ_VEC_PRTY8_CME | /* 2: IDX_PRTY_LVL_WAKE_DB2 */
+ IRQ_VEC_PRTY7_CME |
+ IRQ_VEC_PRTY6_CME |
IRQ_VEC_PRTY5_CME |
IRQ_VEC_PRTY4_CME |
IRQ_VEC_PRTY3_CME |
@@ -79,26 +85,44 @@ const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2] =
},
{
IRQ_VEC_PRTY3_CME,
- IRQ_VEC_PRTY6_CME | /* 3: IDX_PRTY_LVL_STOP */
+ IRQ_VEC_PRTY8_CME | /* 3: IDX_PRTY_LVL_STOP */
+ IRQ_VEC_PRTY7_CME |
+ IRQ_VEC_PRTY6_CME |
IRQ_VEC_PRTY5_CME |
IRQ_VEC_PRTY4_CME |
IRQ_VEC_PRTY3_CME
},
{
IRQ_VEC_PRTY4_CME,
- IRQ_VEC_PRTY6_CME | /* 4: IDX_PRTY_LVL_DB1 */
+ IRQ_VEC_PRTY8_CME | /* 4: IDX_PRTY_LVL_DB1 */
+ IRQ_VEC_PRTY7_CME |
+ IRQ_VEC_PRTY6_CME |
IRQ_VEC_PRTY5_CME |
IRQ_VEC_PRTY4_CME
},
{
IRQ_VEC_PRTY5_CME,
- IRQ_VEC_PRTY6_CME | /* 5: IDX_PRTY_LVL_PMCR_DB0 */
+ IRQ_VEC_PRTY8_CME | /* 5: IDX_PRTY_LVL_DB0 */
+ IRQ_VEC_PRTY7_CME |
+ IRQ_VEC_PRTY6_CME |
IRQ_VEC_PRTY5_CME
},
{
IRQ_VEC_PRTY6_CME,
- IRQ_VEC_PRTY6_CME /* 6: IDX_PRTY_LVL_DISABLED */
+ IRQ_VEC_PRTY8_CME | /* 6: IDX_PRTY_LVL_INTERCME_IN0 */
+ IRQ_VEC_PRTY7_CME |
+ IRQ_VEC_PRTY6_CME
+ },
+ {
+ IRQ_VEC_PRTY7_CME,
+ IRQ_VEC_PRTY8_CME | /* 7: IDX_PRTY_LVL_PMCR */
+ IRQ_VEC_PRTY7_CME
+ },
+ {
+ IRQ_VEC_PRTY8_CME,
+ IRQ_VEC_PRTY8_CME /* 8: IDX_PRTY_LVL_DISABLED */
}
+
};
uint8_t g_current_prty_level = NUM_EXT_IRQ_PRTY_LEVELS - 1;
@@ -178,6 +202,5 @@ void pk_unified_irq_prty_mask_handler(void)
//l_vecL = 0;
asm volatile ("lvd %[data], 0(%[addr]) \n" \
: [data]"=r"(l_vecH) \
- : [addr]"r"(&ext_irq_vector_pk) );
-
+ : [addr]"r"(&(ext_irq_vectors_cme[iPrtyLvl][IDX_PRTY_VEC])) );
}
diff --git a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h
index 2a9729fe..45fc7a21 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h
+++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h
@@ -64,16 +64,18 @@
#define FALSE 0
// Priority Levels
-#define IDX_PRTY_LVL_HIPRTY 0
-#define IDX_PRTY_LVL_BCE_DB3 1
-#define IDX_PRTY_LVL_WAKE_DB2 2
-#define IDX_PRTY_LVL_STOP 3
-#define IDX_PRTY_LVL_DB1 4
-#define IDX_PRTY_LVL_PMCR_DB0 5
-#define IDX_PRTY_LVL_DISABLED 6
-#define IDX_PRTY_VEC 0
-#define IDX_MASK_VEC 1
-#define NUM_EXT_IRQ_PRTY_LEVELS (uint8_t)(7)
+#define IDX_PRTY_LVL_HIPRTY 0
+#define IDX_PRTY_LVL_BCE_DB3 1
+#define IDX_PRTY_LVL_WAKE_DB2 2
+#define IDX_PRTY_LVL_STOP 3
+#define IDX_PRTY_LVL_DB1 4
+#define IDX_PRTY_LVL_DB0 5
+#define IDX_PRTY_LVL_INTERCME_IN0 6
+#define IDX_PRTY_LVL_PMCR 7
+#define IDX_PRTY_LVL_DISABLED 8
+#define IDX_PRTY_VEC 0
+#define IDX_MASK_VEC 1
+#define NUM_EXT_IRQ_PRTY_LEVELS (uint8_t)(9)
extern const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2];
// Group0: Non-task hi-prty IRQs
@@ -86,10 +88,14 @@ extern const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2];
#define IRQ_VEC_PRTY3_CME (uint64_t)(0x000FCC0000000000)
// Group4: DB1
#define IRQ_VEC_PRTY4_CME (uint64_t)(0x0000000000C00000)
-// Group5: BD0 + PMCR
-#define IRQ_VEC_PRTY5_CME (uint64_t)(0x000000003C000000)
-// Group6: We should never detect these
-#define IRQ_VEC_PRTY6_CME (uint64_t)(0x01C003FFC33FFFFF)
+// Group5: DB0
+#define IRQ_VEC_PRTY5_CME (uint64_t)(0x000000000C000000)
+// Group6: INTERCME_IN0
+#define IRQ_VEC_PRTY6_CME (uint64_t)(0x0100000000000000)
+// Group7: PMCR
+#define IRQ_VEC_PRTY7_CME (uint64_t)(0x0000000030000000)
+// Group8: We should never detect these
+#define IRQ_VEC_PRTY8_CME (uint64_t)(0x00C003FFC33FFFFF)
// This should be 0xFFFFFFFFFFFFFFFF
#define IRQ_VEC_PRTY_CHECK ( IRQ_VEC_PRTY0_CME | \
@@ -98,7 +104,9 @@ extern const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2];
IRQ_VEC_PRTY3_CME | \
IRQ_VEC_PRTY4_CME | \
IRQ_VEC_PRTY5_CME | \
- IRQ_VEC_PRTY6_CME )
+ IRQ_VEC_PRTY6_CME | \
+ IRQ_VEC_PRTY7_CME | \
+ IRQ_VEC_PRTY8_CME )
extern uint8_t g_current_prty_level;
extern uint8_t g_eimr_stack[NUM_EXT_IRQ_PRTY_LEVELS];
diff --git a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c
index 77333c2e..81eee16e 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c
@@ -25,9 +25,11 @@
#include "pk.h"
#include "p9_cme_irq.h"
+#include "p9_cme_flags.h"
// CME Pstate Header and Structure
#include "p9_cme_pstate.h"
+CmePstateRecord G_cme_pstate_record;
// CME Stop Header and Structure
#include "p9_cme_stop.h"
@@ -42,7 +44,7 @@ IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PVREF_FAIL
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_OCC_HEARTBEAT_LOST
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_CORE_CHECKSTOP
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DROPOUT_FAIL
-IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_7
+IRQ_HANDLER(p9_cme_pstate_intercme_in0_handler, (void*)NULL) //CMEHW_IRQ_INTERCME_DIRECT_IN0
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_BCE_BUSY_HIGH
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_BCE_TIMEOUT
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL3_C0
@@ -77,12 +79,16 @@ IRQ_HANDLER_DEFAULT //CMEHW_IRQ_COMM_SEND_ACK
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_COMM_SEND_NACK
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_32
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_33
-IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PMCR_UPDATE_C0
-IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PMCR_UPDATE_C1
-IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL0_C0
-IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL0_C1
-IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_38
-IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_39
+IRQ_HANDLER(p9_cme_pstate_pmcr_handler, (void*) & (G_cme_pstate_record.sem[0]))
+//CMEHW_IRQ_PMCR_UPDATE_C0
+IRQ_HANDLER(p9_cme_pstate_pmcr_handler, (void*) & (G_cme_pstate_record.sem[0]))
+//CMEHW_IRQ_PMCR_UPDATE_C1
+IRQ_HANDLER(p9_cme_pstate_db_handler, (void*) & (G_cme_pstate_record.sem[1]))
+//CMEHW_IRQ_DOORBELL0_C0
+IRQ_HANDLER(p9_cme_pstate_db_handler, (void*) & (G_cme_pstate_record.sem[1]))
+//CMEHW_IRQ_DOORBELL0_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_INTERCME_IN1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_INTERCME_IN2
IRQ_HANDLER(p9_cme_stop_doorbell_handler, 0) //CMEHW_IRQ_DOORBELL1_C0
IRQ_HANDLER(p9_cme_stop_doorbell_handler, 0) //CMEHW_IRQ_DOORBELL1_C1
IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PECE_INTR_DISABLED_C0
@@ -110,21 +116,24 @@ IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_63
EXTERNAL_IRQ_TABLE_END
#define KERNEL_STACK_SIZE 256
-#define THREAD_STACK_SIZE 256
+#define THREAD_STACK_SIZE 512
#define CME_THREAD_PRIORITY_STOP_EXIT 1
#define CME_THREAD_PRIORITY_STOP_ENTRY 2
-#define CME_THREAD_PRIORITY_PSTATE_PMCR 3
+#define CME_THREAD_PRIORITY_PSTATE_DB 3
+#define CME_THREAD_PRIORITY_PSTATE_PMCR 4
uint8_t G_kernel_stack[KERNEL_STACK_SIZE];
uint8_t G_p9_cme_stop_enter_thread_stack[THREAD_STACK_SIZE];
uint8_t G_p9_cme_stop_exit_thread_stack[THREAD_STACK_SIZE];
-uint8_t G_p9_cme_pmcr_db0_thread_stack[THREAD_STACK_SIZE];
+uint8_t G_p9_cme_db_thread_stack[THREAD_STACK_SIZE];
+uint8_t G_p9_cme_pmcr_thread_stack[THREAD_STACK_SIZE];
PkThread G_p9_cme_stop_enter_thread;
PkThread G_p9_cme_stop_exit_thread;
-PkThread G_p9_cme_pmcr_db0_thread;
+PkThread G_p9_cme_db_thread;
+PkThread G_p9_cme_pmcr_thread;
int
main(int argc, char** argv)
@@ -152,7 +161,14 @@ main(int argc, char** argv)
pk_halt();
}
- //CMO-Temporary setting
+
+ //Currently, commenting this.
+ //This shouldn't really be here at all as SGPE will write this register.
+ //For verification in SIMICS, SOA, EPM currently just write the CME_LCL_FLAGS manually
+ //
+ //
+ //
+ /* //CMO-Temporary setting
// Setup up CME_LCL_FLAGS to indicate whether
// this CME is QMGR master or slave.
// Rules:
@@ -163,6 +179,7 @@ main(int argc, char** argv)
uint32_t l_pir;
asm volatile ("mfpir %[data] \n" : [data]"=r"(l_pir) );
+ #ifndef _SOA_SC_ENVIRONMENT_
if ( l_pir & PIR_INSTANCE_EVEN_ODD_MASK )
{
// Odd: Set slave status
@@ -174,6 +191,28 @@ main(int argc, char** argv)
out32(CME_LCL_FLAGS_OR, CME_FLAGS_QMGR_MASTER);
}
+ #else
+
+ if ( l_pir & PIR_INSTANCE_EVEN_ODD_MASK )
+ {
+ // Odd: Set slave status
+ out32(CME_LCL_FLAGS_OR, CME_FLAGS_QMGR_MASTER);
+ }
+ else
+ {
+ // Even: Set master status
+ out32(CME_LCL_FLAGS_CLR, CME_FLAGS_QMGR_MASTER);
+ }
+
+ #endif
+
+ //\todo Fix this
+ #ifndef _SOA_SC_ENVIRONMENT_
+ out32(CME_LCL_FLAGS_OR, CME_FLAGS_CORE0_GOOD | CME_FLAGS_CORE1_GOOD | CME_FLAGS_SIBLING_FUNCTIONAL);
+ #else
+ out32(CME_LCL_FLAGS_OR, CME_FLAGS_CORE0_GOOD | CME_FLAGS_CORE1_GOOD);
+ #endif
+ */
// Initialize the thread control block for G_p9_cme_stop_exit_thread
pk_thread_create(&G_p9_cme_stop_exit_thread,
(PkThreadRoutine)p9_cme_stop_exit_thread,
@@ -199,16 +238,28 @@ main(int argc, char** argv)
sizeof(G_p9_cme_stop_enter_thread));
// Initialize thread control blocks for the threads
- pk_thread_create( &G_p9_cme_pmcr_db0_thread,
- (PkThreadRoutine)pmcr_db0_thread,
+ pk_thread_create( &G_p9_cme_db_thread,
+ (PkThreadRoutine)p9_cme_pstate_db_thread,
(void*)NULL,
- (PkAddress)G_p9_cme_pmcr_db0_thread_stack,
+ (PkAddress)G_p9_cme_db_thread_stack,
(size_t)THREAD_STACK_SIZE,
- (PkThreadPriority)IDX_PRTY_LVL_PMCR_DB0);
+ (PkThreadPriority)CME_THREAD_PRIORITY_PSTATE_DB);
- PK_TRACE_BIN("G_p9_cme_pmcr_db0_thread",
- &G_p9_cme_pmcr_db0_thread,
- sizeof(G_p9_cme_pmcr_db0_thread));
+ PK_TRACE_BIN("G_p9_cme_db_thread",
+ &G_p9_cme_db_thread,
+ sizeof(G_p9_cme_db_thread));
+
+ // Initialize thread control blocks for the threads
+ pk_thread_create( &G_p9_cme_pmcr_thread,
+ (PkThreadRoutine)p9_cme_pstate_pmcr_thread,
+ (void*)NULL,
+ (PkAddress)G_p9_cme_pmcr_thread_stack,
+ (size_t)THREAD_STACK_SIZE,
+ (PkThreadPriority)CME_THREAD_PRIORITY_PSTATE_PMCR);
+
+ PK_TRACE_BIN("G_p9_cme_pmcr_thread",
+ &G_p9_cme_pmcr_thread,
+ sizeof(G_p9_cme_pmcr_thread));
// Make G_p9_cme_stop_exit_thread runnable
pk_thread_resume(&G_p9_cme_stop_exit_thread);
@@ -217,10 +268,15 @@ main(int argc, char** argv)
pk_thread_resume(&G_p9_cme_stop_enter_thread);
// Make G_p9_cme_pstate_thread runnable
- pk_thread_resume(&G_p9_cme_pmcr_db0_thread);
+ pk_thread_resume(&G_p9_cme_db_thread);
+
+ // Make G_p9_cme_pstate_thread runnable
+ pk_thread_resume(&G_p9_cme_pmcr_thread);
PK_TRACE("Launching threads");
+ ppe42_app_ctx_set(0);
+
// Start running the highest priority thread.
// This function never returns
pk_start_threads();
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 ed33dfa9..44f93821 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
@@ -28,723 +28,458 @@
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------
-/// \file pstate_cme.c
+/// \file p9_cme_pstate.c
/// \brief CME and QCME codes enforcing the Power protocols for Pstate, DPLL
/// actuation, iVRM, resonant clocking, and VDM.
-/// \owner Michael Olsen Email: cmolsen@us.ibm.com
-///
-
-/// Features of this H-code:
-/// - The thread works in conjunction with the pstate thread on the PGPE.
-///
-/// Assumptions:
-/// 1. PGPE is assumed up and running and ready at the time the QCME sends
-/// it registration request.
-///
+/// \owner Rahul Batra Email: rbatra@us.ibm.com
///
#include "pk.h"
+#include "ppe42_scom.h"
+
+#include "cme_firmware_registers.h"
#include "cme_register_addresses.h"
-#include "ppm_register_addresses.h"
-#include "ppm_firmware_registers.h"
-#include "cppm_register_addresses.h"
#include "cppm_firmware_registers.h"
-#include "qppm_register_addresses.h"
+#include "cppm_register_addresses.h"
+#include "ppm_firmware_registers.h"
+#include "ppm_register_addresses.h"
#include "qppm_firmware_registers.h"
-#include "ppe42_scom.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_pstate_common.h"
+#include "p9_pstate_vpd.h"
+#include "ppe42_cache.h"
+
//
-// HOMER variables updated by PGPE
+//Globals
//
-uint32_t ULTRA_TURBO_FREQ_STEPS_PS;
-
-#define PIG_PAYLOAD_MASK 0x0fff000000000000
-#define PIG_INTR_FIELD_MASK 0x7000000000000000
-#define PIG_INTR_GRANTED_MASK 0x0000000080000000
+extern CmePstateRecord G_cme_pstate_record;
+cme_pstate_db_data_t G_db_thread_data;
+cme_pstate_pmcr_data_t G_pmcr_thread_data;
-// Type1 specific defines
-#define PIG_PAYLOAD_PSTATE_MASK 0x03ff000000000000
-#define PIG_PAYLOAD_PSTATE_SEQ_INCR 0x0400000000000000 // Seq increment value
-
-
-int
-register_qcme_with_pgpe(void);
+//\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);
-void
-unified_irq_task_handler(void* arg, PkIrqId irq)
+//
+//PMCR Interrupt Handler
+//
+void p9_cme_pstate_pmcr_handler(void* arg, PkIrqId irq)
{
pk_semaphore_post((PkSemaphore*)arg);
}
-
-void
-unified_irq_nontask_handler(void* arg, PkIrqId irq)
+//
+//Doorbell0 interrupt handler
+//
+//Only enabled on QuadManager-CME
+void p9_cme_pstate_db_handler(void* arg, PkIrqId irq)
{
- MY_TRACE_ERR("Got an non-task IRQ=%d", irq);
- pk_halt();
+ pk_semaphore_post((PkSemaphore*)arg);
}
-
-int
-send_pig_packet(uint32_t addr, uint64_t data)
+//
+//InterCME_IN0 handler
+//
+void p9_cme_pstate_intercme_in0_handler(void* arg, PkIrqId irq)
{
- int rc = 0;
- uint64_t data_tmp;
+ pgpe_db0_glb_bcast_t db0C0Data, db0C1Data;
+ uint8_t localPS = 0;
+ uint32_t cme_flags = in32(CME_LCL_FLAGS);
+ uint64_t pmsrData;
+ PkMachineContext ctx;
- // First make sure no interrupt request is currently granted
- do
+ //read DB0 for both cores and update PMSR
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
{
- // Read PPMPIG status
- rc = getscom(0, addr, &data_tmp);
-
- if (rc)
- {
- MY_TRACE_ERR("getscom(addr=0x%08x) failed w/rc=0x%08x", addr, rc);
- pk_halt();
- }
+ 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
}
- while (((ppm_pig_t)data_tmp).fields.intr_granted);
-
- // Send PIG packet
- rc = putscom(0, addr, data);
- if (rc)
+ if (cme_flags & CME_FLAGS_CORE1_GOOD)
{
- MY_TRACE_ERR("putscom(addr=0x%08x) failed w/rc=0x%08x", addr, rc);
- pk_halt();
+ 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
}
- return rc;
-}
+ 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);
+}
-void
-pmcr_db0_thread(void* arg)
+//
+//p9_cme_pmcr_thread
+//
+void p9_cme_pstate_pmcr_thread(void* arg)
{
- int rc = 0, rc_api = API_RC_SUCCESS;
- uint8_t bDB0 = FALSE, bPMCR = FALSE;
+ int32_t c;
PkMachineContext ctx;
- PkSemaphore sem;
- uint64_t thisIrqPrtyVec;
- uint8_t irqPrty;
- uint8_t ps_local;
- int statusIrqDb0C0;
- int statusIrqDb0C1;
- int statusIrqPmcrC0;
- int statusIrqPmcrC1;
- uint8_t thisCoreIdx = 0xff; // Index=0 or =1
- uint8_t nextCoreIdx = 0xff; // Index=0 or =1
- PkIrqId IRQ_THIS = 0xff;
- uint8_t seqNum = 0; // Phase message sequence (0,1,2,3,0,..)
- uint32_t addr_db0 = 0;
- uint32_t addr_db0_0, addr_db0_1; // One for each of the two cores
- uint32_t addr_pmcr = 0;
- uint32_t addr_pmcr_0, addr_pmcr_1; // One for each of the two cores
- uint32_t addr_ppm_pig;
- uint32_t addr_ppm_pig_0, addr_ppm_pig_1; // One for each of the two cores
- uint64_t data_pmcr;
- cb_to_qcme_base_t cb_from_pgpe_base;
- cb_to_pgpe_ack_t cb_to_pgpe_ack;
- cb_to_pgpe_qcme_t cb_to_pgpe_qcme;
- uint32_t addr_ippmr, addr_ippmw, addr_ippmcmd;
- qppm_dpll_freq_t qppm_dpll_freq;
- cppm_ippmcmd_t cppm_ippmcmd;
- ppm_pig_t data_ppm_pig;
- uint64_t data;
- uint32_t data32;
- uint8_t fsm_unacked_qcme_registration;
- uint32_t l_pir;
- uint8_t bQcmeRegister;
- uint8_t thisCmeInstance;
-
-
- PK_TRACE("PMCR_DB0 thread starting...");
-
- // Lock this in now to avoid typing mistakes later-on. And make sure you're
- // using the correct PRTY level for this task.
- thisIrqPrtyVec = ext_irq_vectors_cme[IDX_PRTY_LVL_PMCR_DB0][IDX_PRTY_VEC];
-
-
- // Calculate anticipated SCOM addresses, or fractions of them up front
- //
-
- // Local PMCR0 used by cores "left" and "right"
- addr_pmcr_0 = CME_LCL_PMCRS0;
- addr_pmcr_1 = CME_LCL_PMCRS1;
-
- // CPPM_DB0_0/1 regs used by cores "left" and "right"
- addr_db0_0 = CPPM_CMEDB0 | CORE_SEL_LEFT;
- addr_db0_1 = CPPM_CMEDB0 | CORE_SEL_RIGHT;
-
- // PPM_PIG_0/1 belong to cores "left" and "right"
- addr_ppm_pig_0 = PPM_PIG | CORE_SEL_LEFT;
- addr_ppm_pig_1 = PPM_PIG | CORE_SEL_RIGHT;
-
-
- // Create a semaphore, updated by a single interrupt handler that services
- // two PMCR and two DB0 interrupts. Thus, max sem count set to four.
- pk_semaphore_create(&sem, 0, 4);
-
-
- //--------------------------------------------//
- // Register the unified interrupt handler. //
- //--------------------------------------------//
-
- // Notes:
- // - Register the two PMCR and the two DB0 interrupts
- // - Never consider IRQs beyond IRQ>=44 because they are reserved and
- // permanently firing.
- // - Also register high-priority interrupt handlers
- //
- for (irqPrty = 0; irqPrty < 44; irqPrty++)
- {
- if ( ext_irq_vectors_cme[IDX_PRTY_LVL_PMCR_DB0][IDX_PRTY_VEC] &
- (RIGHT_SHIFT_PTRN_0x8_64BIT >> irqPrty) )
- {
- rc = pk_irq_handler_set( irqPrty,
- unified_irq_task_handler,
- (void*)&sem );
+ 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;
- if (rc)
- {
- PK_TRACE("pk_irq_handler_set(%d) failed w/rc=0x%08x", irqPrty, rc);
- pk_halt();
- }
- }
- else if ( ext_irq_vectors_cme[IDX_PRTY_LVL_HIPRTY][IDX_PRTY_VEC] &
- (RIGHT_SHIFT_PTRN_0x8_64BIT >> irqPrty) )
- {
- rc = pk_irq_handler_set( irqPrty,
- unified_irq_nontask_handler,
- (void*)&sem );
+ G_pmcr_thread_data.seqNum = 0;
- if (rc)
- {
- PK_TRACE("pk_irq_handler_set(%d) failed w/rc=0x%08x", irqPrty, rc);
- pk_halt();
- }
- }
+ 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
+ }
- //
- // Clear (until Simics gets fixed) and unmask the [non-task] shared HIPRTY IRQs.
- //
- pk_irq_vec_status_clear( ext_irq_vectors_cme[IDX_PRTY_LVL_HIPRTY][IDX_PRTY_VEC]);
- pk_irq_vec_enable( ext_irq_vectors_cme[IDX_PRTY_LVL_HIPRTY][IDX_PRTY_VEC]);
-
- //
- // Clear and then unmask our interrupts.
- // (Note, this must be done BEFORE registering QCME as otherwise race
- // condition between EISR clearing and PGPE sending Ack.)
- //
- pk_irq_vec_status_clear( thisIrqPrtyVec);
- pk_irq_vec_enable( thisIrqPrtyVec);
-
+ pk_semaphore_create(&G_cme_pstate_record.sem[0], 0, 1);
- //------------------------------------------------------------------------------//
- // Determine QMGR status and register as QMGR, ie QCME, if CME is QMGR master //
- //------------------------------------------------------------------------------//
+ while(1)
+ {
+ //pend on sempahore
+ pk_semaphore_pend(&G_cme_pstate_record.sem[0], PK_WAIT_FOREVER);
+ wrteei(1);
- // First determine if this CME is a QMRG master, i.e. QCME
- //
- bQcmeRegister = FALSE;
+ //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
- asm volatile ("mfpir %[data] \n" : [data]"=r"(l_pir) );
+ 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++;
+ }
+ }
+ }
- thisCmeInstance = (uint8_t)(l_pir & PIR_INSTANCE_NUM_MASK);
+ pk_irq_vec_restore(&ctx);
+ }
+}
- rc = getscom( 0, CME_LCL_FLAGS, &data );
- data32 = (uint32_t)(data >> 32);
+//
+//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.
+#ifndef SIMICS_ENVIRONMENT
+ 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 ( data32 & CME_FLAGS_QMGR_MASTER )
- {
- bQcmeRegister = TRUE;
- MY_TRACE_DBG("This CME#%d is the QMGR master", thisCmeInstance);
- }
- else // Sanity check since this CME is NOT a QMGR mstr, that it is an odd CME. Otherwise, error.
+ if (cme_flags & CME_FLAGS_QMGR_MASTER)
{
- if ( l_pir & PIR_INSTANCE_EVEN_ODD_MASK ) // Sanity test that bit31==1 and thus this CME is odd.
+ G_db_thread_data.qmFlag = 1;
+
+ if (cme_flags & CME_FLAGS_SIBLING_FUNCTIONAL)
{
- bQcmeRegister = FALSE;
- MY_TRACE_DBG("This [odd] CME#%d is the QMGR slave", thisCmeInstance);
+ G_db_thread_data.siblingCMEFlag = 1;
}
else
{
- MY_TRACE_ERR("CME_LCL_FLAGS indicate QMGR slave status for even CME.");
- MY_TRACE_ERR("This is not allowed. Even CMEs must be QMGR master.");
- pk_halt();
+ G_db_thread_data.siblingCMEFlag = 0;
}
}
-
- // FSM Notes:
- // - Register this CME with PGPE if it's the QMGR master.
- // - Note that registration MUST be done AFTER clearing and unmasking
- // interrupts.
- //
- fsm_unacked_qcme_registration = 0;
-
- if (bQcmeRegister)
+ else
{
- // Format Type4 PIG message - Populate the CB, then the PIG payload
- //
- cb_to_pgpe_qcme.value = 0;
- cb_to_pgpe_qcme.fields.msg_id = MSGID_T4_REGISTER_QCME;
-
- data_ppm_pig.value = 0;
- data_ppm_pig.fields.req_intr_payload = cb_to_pgpe_qcme.value;
- data_ppm_pig.fields.req_intr_type = 4;
-
-//CMO - TBD - Determine which of the two cores are configured. Pick the smallest
-// numbered. We'll assume idx=0 for now. Another RTC story will deal
-// with the issue of picking the lowest registered core's PIG.
- addr_ppm_pig = addr_ppm_pig_0;
-
- // Assumption 1:
- // Before sending Type4 QCME registration, make sure PGPE is running.
- // For now, use pk_sleep.
- // Need some kind of handshake here. Or we need to know for sure that
- // PGPE is always running before QCME.
- pk_sleep(PK_NANOSECONDS(1000));
- rc = send_pig_packet(addr_ppm_pig, data_ppm_pig.value);
-
- if (rc)
- {
- MY_TRACE_ERR("send_pig_packet(addr=0x%08x) failed w/rc=0x%08x", addr_ppm_pig, rc);
- pk_halt();
- }
+ G_db_thread_data.qmFlag = 0;
+ G_db_thread_data.siblingCMEFlag = 0;
+ }
- // Update the unacked registration tracker
- if (!fsm_unacked_qcme_registration)
+ //if quadManager
+ if (G_db_thread_data.qmFlag)
+ {
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
{
- fsm_unacked_qcme_registration++;
+ 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
+ else if (cme_flags & CME_FLAGS_CORE1_GOOD)
{
- MY_TRACE_ERR("Code bug: fsm_unacked_qcme_registration (=%d) > 0",
- fsm_unacked_qcme_registration);
- pk_halt();
+ 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;
}
- }
-
-
- //
- // Reset indices and seq no
- //
- nextCoreIdx = 0;
- thisCoreIdx = 0xff;
- seqNum = 0;
-
-#if EPM_P9_TUNING
- asm volatile ( "tw 0, 31, 0" );
-#endif
- // FSM: Indicate PMCR thread is ready.
- out32(CME_LCL_FLAGS_OR, CME_FLAGS_PMCR_READY);
+ out64(CME_LCL_EIMR_OR, BIT64(7));//Disable InterCME_IN0
+ g_eimr_override |= BIT64(7);
-
- while(1)
+ 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);
+ }
- // Go to sleep
- pk_semaphore_pend(&sem, PK_WAIT_FOREVER);
+ //\todo (RTC) Set intial GlobalPS, LocalPS, resClkIdx, etc.
+ //Most likely will come from SGPE. Need to know precisely
- //
- // First we need to determine which of the four interrupts fired.
- // This incl which of the two cores, "left" (index0) or "right" (index1),
- // were used.
- // - Give priority to DB0 over PMCR. (More important to wrap up ongoing
- // PMCR request than to start a new.)
- // - If both of the PMCRs fired by the time we get to this point, alternate
- // between them using nextCoreIdx and thisCoreIdx.
- // - If both of the DB0s fired, we have an error.
- //
+ //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);
- do
+ while(1)
{
- bDB0 = bPMCR = FALSE;
-
- statusIrqDb0C0 = pk_irq_status_get(CMEHW_IRQ_DOORBELL0_C0);
- statusIrqDb0C1 = pk_irq_status_get(CMEHW_IRQ_DOORBELL0_C1);
+ //pend on sempahore
+ pk_semaphore_pend(&G_cme_pstate_record.sem[1], PK_WAIT_FOREVER);
+ wrteei(1);
- if (statusIrqDb0C0 && statusIrqDb0C1)
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
{
- // Both fired (We do NOT support this.)
- PK_TRACE("Code bug: Both DB0s fired. Probably PGPE problem.");
- pk_halt();
+ 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 (statusIrqDb0C0)
+ else if (cme_flags & CME_FLAGS_CORE1_GOOD)
{
- thisCoreIdx = 0; // "left" core idx
- IRQ_THIS = CMEHW_IRQ_DOORBELL0_C0;
- addr_db0 = addr_db0_0;
- addr_ppm_pig = addr_ppm_pig_0;
- bDB0 = TRUE;
+ out32_sh(CME_LCL_EISR_CLR, BIT32(5));
+ CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C1, CME_SCOM_EQ, dbData.value);
}
- else if (statusIrqDb0C1)
+
+ //Update analog
+ if (G_resclkEnabled)
{
- thisCoreIdx = 1; // "right" core idx
- IRQ_THIS = CMEHW_IRQ_DOORBELL0_C1;
- addr_db0 = addr_db0_1;
- addr_ppm_pig = addr_ppm_pig_1;
- bDB0 = TRUE;
+ resclk_update();
}
- else
+
+#ifndef SIMICS_ENVIRONMENT
+ freq_update(dbData.value);
+#endif
+
+ //Notify sibling CME(if any)
+ if (G_db_thread_data.siblingCMEFlag == 1)
{
- statusIrqPmcrC0 = pk_irq_status_get(CMEHW_IRQ_PMCR_UPDATE_C0);
- statusIrqPmcrC1 = pk_irq_status_get(CMEHW_IRQ_PMCR_UPDATE_C1);
+ //Send interCME interrupt
+ out32(CME_LCL_ICCR_OR, BIT32(5)); //Send direct InterCME_IN0
+ out32(CME_LCL_ICCR_CLR, BIT32(5));//Clear
+
+#ifndef SIMICS_ENVIRONMENT
+ //poll on interCME interrupt
+ intercme_acked = 0;
+#else
+ intercme_acked = 1;
+#endif
- if (statusIrqPmcrC0 && statusIrqPmcrC1)
+ while (!intercme_acked)
{
- // Both fired (We support this.)
- thisCoreIdx = nextCoreIdx;
- nextCoreIdx++;
- nextCoreIdx = nextCoreIdx - (nextCoreIdx >> 1) * 2;
+ eisr = in64(CME_LCL_EISR);
- if (thisCoreIdx != 0 && thisCoreIdx != 1)
+ if (eisr & 0x0100000000000000)
{
- PK_TRACE("Code bug: Illegal value of thisCoreIdx (=%d).", thisCoreIdx);
- pk_halt();
+ intercme_acked = 1;
}
}
- else if (statusIrqPmcrC0)
- {
- thisCoreIdx = 0; // "left" core idx
- }
- else if (statusIrqPmcrC1)
- {
- thisCoreIdx = 1; // "right" core idx
- }
- else
- {
- PK_TRACE("Illegal interrupt status.");
- PK_TRACE("Neither of the {PMCR,DB0}_C0/1 interrupts are set.");
- pk_halt();
- }
-
- bPMCR = TRUE;
- // Set the core specific values for the interrupt, pmcr addr and
- // ppmpig addr. Note, we already did this earlier for db0.
- if (thisCoreIdx == 0)
- {
- IRQ_THIS = CMEHW_IRQ_PMCR_UPDATE_C0;
- addr_pmcr = addr_pmcr_0;
- addr_ppm_pig = addr_ppm_pig_0;
- }
- else
- {
- IRQ_THIS = CMEHW_IRQ_PMCR_UPDATE_C1;
- addr_pmcr = addr_pmcr_1;
- addr_ppm_pig = addr_ppm_pig_1;
- }
+ out32(CME_LCL_EISR_CLR, BIT32(7));//Clear InterCME_IN0
}
- }
- while(0);
-
- MY_TRACE_DBG("IRQ_THIS=0x%02x, addr_ppm_pig=0x%08x",
- IRQ_THIS, addr_ppm_pig);
-
- // Clear the status of the currently selected interrupt
- pk_irq_status_clear(IRQ_THIS);
-
-
- //------------------------------------------------------------------//
- // Do the work //
- //------------------------------------------------------------------//
-
- if (bDB0)
- //-------------------------------------------//
- // Process DB0 //
- //-------------------------------------------//
- {
- MY_TRACE_DBG("IRQ_THIS=0x%02x, addr_db0=0x%08x, addr_ppm_pig=0x%08x",
- IRQ_THIS, addr_db0, addr_ppm_pig);
+ //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;
- // Get the payload from DB0
- rc = getscom(0, addr_db0, &cb_from_pgpe_base.value);
-
- if (rc)
+ if (cme_flags & CME_FLAGS_CORE0_GOOD)
{
- MY_TRACE_ERR("getscom(addr=0x%08x,data=0x%08x%08x) failed w/rc=0x%08x",
- addr_db0, cb_from_pgpe_base.value, rc);
- pk_halt();
+ out64(CME_LCL_PMSRS0, pmsrData);
}
-//MY_TRACE_DBG("DB0 payload = 0x%08x%08x",
-// (uint32_t)(cb_from_pgpe_base.value>>32),(uint32_t)(cb_from_pgpe_base.value));
-
- //
- // Act on msg_id and do what needs be done
- // Note that there's only support for PS_BROADCAST and Ack so far.
- //
- switch (cb_from_pgpe_base.fields.msg_id)
+ if (cme_flags & CME_FLAGS_CORE1_GOOD)
{
-
- case MSGID_DB0_PS_BROADCAST:
-
- if (fsm_unacked_qcme_registration)
- {
- MY_TRACE_ERR("Code bug: fsm_unacked_qcme_registration (=%d) != 0",
- fsm_unacked_qcme_registration);
- pk_halt();
- }
-
- ps_local = ((cb_to_qcme_ps_bc_t)cb_from_pgpe_base.value).fields.ps_local;
-
- MY_TRACE_DBG("cb_from_pgpe_ps_bc.fields.ps_local=%d", ps_local);
-
- // Update the DPLL_FREQ register
- //
-
- // In the following setup,
- // - use the CPPM that you received the DB0 on
- // - use CorePPM1 for the INTERPPM (done from PGPE)
- //
- if (thisCoreIdx == 0)
- {
- addr_ippmr = CPPM_IPPMRDATA | CORE_SEL_LEFT;
- addr_ippmw = CPPM_IPPMWDATA | CORE_SEL_LEFT;
- addr_ippmcmd = CPPM_IPPMCMD | CORE_SEL_LEFT;
- }
- else
- {
- addr_ippmr = CPPM_IPPMRDATA | CORE_SEL_RIGHT;
- addr_ippmw = CPPM_IPPMWDATA | CORE_SEL_RIGHT;
- addr_ippmcmd = CPPM_IPPMCMD | CORE_SEL_RIGHT;
- }
-
- rc = getscom(0, addr_ippmr, &(qppm_dpll_freq.value));
-
- if (rc)
- {
- MY_TRACE_ERR("getscom(CPPM_IPPMRDATA=0x%08x) failed w/rc=0x%08x",
- addr_ippmr, rc);
- pk_halt();
- //MY_PK_PANIC(SCOM_TROUBLE);
- }
-
- qppm_dpll_freq.fields.fmax =
- qppm_dpll_freq.fields.freq_mult =
- qppm_dpll_freq.fields.fmin = ULTRA_TURBO_FREQ_STEPS_PS - ps_local;
- rc = putscom(0, addr_ippmw, qppm_dpll_freq.value);
-
- if (rc)
- {
- MY_TRACE_ERR("putscom(CPPM_IPPMWDATA=0x%08x) failed w/rc=0x%08x",
- addr_ippmw, rc);
- pk_halt();
- //MY_PK_PANIC(SCOM_TROUBLE);
- }
-
- // Now write the DPLL_FREQ reg through the inter-PPM mechanism
- //
- cppm_ippmcmd.value = 0;
- cppm_ippmcmd.fields.qppm_reg = QPPM_DPLL_FREQ & 0x000000ff;
- cppm_ippmcmd.fields.qppm_rnw = 0; // Use CorePPM1
- rc = putscom(0, addr_ippmcmd, cppm_ippmcmd.value);
-
- if (rc)
- {
- MY_TRACE_ERR("putscom(CPPM_IPPMCMD=0x%08x) failed w/rc=0x%08x",
- addr_ippmcmd, rc);
- pk_halt();
- //MY_PK_PANIC(SCOM_TROUBLE);
- }
-
- //
- // Send an PIG Type4 ack back to PGPE
- //
-
- cb_to_pgpe_ack.value = 0;
- cb_to_pgpe_ack.fields.msg_id = MSGID_T4_ACK;
- cb_to_pgpe_ack.fields.msg_id_ref = ((cb_to_qcme_ps_bc_t)cb_from_pgpe_base.value).fields.msg_id;
- cb_to_pgpe_ack.fields.rc = rc_api;
-
- data_ppm_pig.value = 0;
- data_ppm_pig.fields.req_intr_payload = cb_to_pgpe_ack.value;
- data_ppm_pig.fields.req_intr_type = 4;
-
- // Send Ack back to PGPE to acknowledge receipt and processing
- // of the Pstate broadcast.
- rc = send_pig_packet(addr_ppm_pig, data_ppm_pig.value);
-
- if (rc)
- {
- MY_TRACE_ERR("send_pig_packet(addr=0x%08x) failed w/rc=0x%08x", addr_ppm_pig, rc);
- pk_halt();
- }
-
- break;
-
- case MSGID_DB0_ACK:
-
- MY_TRACE_DBG("Received an DB0 Ack");
-
- if (fsm_unacked_qcme_registration == 1)
- {
- fsm_unacked_qcme_registration--;
- }
- else
- {
- MY_TRACE_ERR("Code bug: fsm_unacked_qcme_registration (=%d) != 1",
- fsm_unacked_qcme_registration);
- pk_halt();
- }
-
- // FSM: Indicate QMGR master status and QMGR ready in CME FLAGS.
- out32(CME_LCL_FLAGS_OR, CME_FLAGS_QMGR_READY);
-
- break;
-
- default:
-
- MY_TRACE_ERR("Unsupported msg_id. Only MSGID_DB0_PS_BROADCAST supported.");
- pk_halt();
-
- break;
-
- } // End of switch()
-
- }
- else if (bPMCR)
- //-------------------------------------------//
- // Process PMCR //
- //-------------------------------------------//
- {
-
- MY_TRACE_DBG("IRQ_THIS=0x%02x, addr_pmcr=0x%08x, addr_ppm_pig=0x%08x",
- IRQ_THIS, addr_pmcr, addr_ppm_pig);
-
- // Read PMCRS
- rc = getscom(0, addr_pmcr, &data_pmcr);
-
- if (rc)
- {
- PK_TRACE("getscom(addr_pmcr%d=0x%08x) failed w/rc=0x%08x",
- thisCoreIdx, addr_pmcr, rc);
- pk_halt();
+ out64(CME_LCL_PMSRS1, pmsrData);
}
-#if DEV_DEBUG
- PK_TRACE("data_pmcr%d=0x%08x%08x",
- thisCoreIdx, (uint32_t)(data_pmcr >> 32), (uint32_t)data_pmcr);
-#endif
-
- // Bump/wrap the payload sequence number
- seqNum++;
- seqNum = seqNum - (seqNum / 4) * 4;
+ //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);
- //
- // Phase 1 PIG message
- //
-
- // Format Pstate phase 1 PIG message - Populate intr_type and payload fields
- //
- // 1) Copy the 10-bit PMCR(6:15) payload to PPMPIG(6:15).
- // 2) Mask off all other content.
- // 3) Indicate the sequence number in the payload field.
- // 4) Indicate the phase 1 (Type0) in the interrupt field.
- data_ppm_pig.value = data_pmcr & PIG_PAYLOAD_PSTATE_MASK;
- data_ppm_pig.value = data_ppm_pig.value | PIG_PAYLOAD_PSTATE_SEQ_INCR * seqNum;
- data_ppm_pig.fields.req_intr_type = 0;
+ pk_irq_vec_restore(&ctx);
+ }
+ }
+}
- // Send PIG phase 1 message, but only if no intr request is currently granted
- rc = send_pig_packet(addr_ppm_pig, data_ppm_pig.value);
+//
+//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.freq_mult = (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);
+}
- if (rc)
- {
- MY_TRACE_ERR("send_pig_packet(addr=0x%08x) failed w/rc=0x%08x", addr_ppm_pig, rc);
- pk_halt();
- }
+//
+//resclk_update
+//
+void resclk_update()
+{
+ uint64_t val;
+ uint8_t tidx, step;
+ int32_t i;
- //
- // Phase 2 PIG message
- //
-
- // Format Pstate phase 2 PIG message - Populate intr_type and payload fields
- //
- // 1) Copy the 10-bit PMCR(22:31) payload to PPMPIG(6:15).
- // 2) Mask off all other content.
- // 3) Indicate the sequence number in the payload field.
- // 4) Indicate the phase 2 (Type1) in the interrupt field.
- // in data_ppm_pig.
- data_ppm_pig.value = (data_pmcr << 16) & PIG_PAYLOAD_PSTATE_MASK;
- data_ppm_pig.value = data_ppm_pig.value | PIG_PAYLOAD_PSTATE_SEQ_INCR * seqNum;
- data_ppm_pig.fields.req_intr_type = 1;
-
- // Send PIG phase 2 message, but only if no intr request is currently granted
- rc = send_pig_packet(addr_ppm_pig, data_ppm_pig.value);
-
- if (rc)
- {
- MY_TRACE_ERR("send_pig_packet(addr=0x%08x) failed w/rc=0x%08x", addr_ppm_pig, rc);
- pk_halt();
- }
+ //get targetIndex from Table1(ControlIndex) by indexing with localPState
+ tidx = G_db_thread_data.resClkTblIdx;
-#if DEV_DEBUG
- // Read PPMPIG status
- rc = getscom(0, addr_ppm_pig, &data);
+ for (i = NUM_FREQ_REGIONS - 1; i >= 0; i--)
+ {
+ if (G_freq2idx[i].pstate > G_db_thread_data.localPS)
+ {
+ tidx = i;
+ break;
+ }
+ }
- if (rc)
- {
- PK_TRACE("getscom(addr_ppm_pig%d=0x%08x) failed w/rc=0x%08x",
- thisCoreIdx, addr_ppm_pig, rc);
- pk_halt();
- }
+ //walk Table2[Resonant Grids Control Data)
+ if (tidx > G_db_thread_data.resClkTblIdx)
+ {
+ step = 1;
+ }
+ else
+ {
+ step = -1;
+ }
- PK_TRACE("(After PIG phase 2): data_ppm_pig%d=0x%08x%08x",
- thisCoreIdx, (uint32_t)(data >> 32), (uint32_t)data);
+ 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;
+
+#ifndef SIMICS_ENVIRONMENT
+ //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
+ }
+}
- }
- else
- {
- PK_TRACE("Code bug.");
- PK_TRACE("Neither of the {PMCR,DB0}_C0/1 interrupts were selected.");
- pk_halt();
- }
+//
+//send_pig_packet
+//
+int send_pig_packet(uint64_t data, uint32_t coreMask)
+{
+ int rc = 0;
+ uint64_t data_tmp;
+ // First make sure no interrupt request is currently granted
+ do
+ {
+ // Read PPMPIG status
+ CME_GETSCOM(PPM_PIG, coreMask, CME_SCOM_EQ, data_tmp);
+ }
+ while (((ppm_pig_t)data_tmp).fields.intr_granted);
- // Restore the EIMR to the value it had when the IRQ handler was entered.
- // (Note that we've already cleared the EISR earlier.)
- //
- pk_irq_vec_restore(&ctx);
- /*
- pk_critical_section_enter(&ctx);
- if (g_eimr_stack_ctr>=0)
- {
- out64( STD_LCL_EIMR,
- ext_irq_vectors_cme[g_eimr_stack[g_eimr_stack_ctr]][IDX_MASK_VEC]);
- out64( STD_LCL_EIMR_CLR,
- g_eimr_override_stack[g_eimr_stack_ctr]);
- out64( STD_LCL_EIMR_OR,
- g_eimr_override);
- //CMO-temporarily commenting following three lines which asap should replace above line.
- // but if i do that, then i get a machine check in the timer_bh_handler (which is
- // a result of pk_delay kicked of way earlier than this code here!!) right after it
- // executes bctrl and jumps to an illegal instruction. Yeah, no make sense!!!
- // out64( STD_LCL_EIMR,
- // (ext_irq_vectors_cme[g_eimr_stack[g_eimr_stack_ctr]][IDX_MASK_VEC] &
- // ~g_eimr_override_stack[g_eimr_stack_ctr]) | g_eimr_override);
- // Restore the prty level tracker to the task that was interrupted, if any.
- g_current_prty_level = g_eimr_stack[g_eimr_stack_ctr];
- g_eimr_stack_ctr--;
- }
- else
- {
- MY_TRACE_ERR("Code bug: Messed up EIMR book keeping: g_eimr_stack_ctr=%d",
- g_eimr_stack_ctr);
- pk_halt();
- }
- pk_critical_section_exit(&ctx);
- */
+ // Send PIG packet
+ CME_PUTSCOM(PPM_PIG, coreMask, data);
- }
+ return rc;
}
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 ef8daeed..57313ebc 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
@@ -28,320 +28,42 @@
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------
-/// \file pstate.h
+/// \file p9_cme_pstate.h
/// \brief Shared and global definitions for pstate H codes.
-/// \owner Michael Olsen Email: cmolsen@us.ibm.com
+/// \owner Rahul Batra Email: rbatra@us.ibm.com
///
-void pmcr_db0_thread(void*);
+#include "pk.h"
+#include "p9_pstate_common.h"
+#include "gpehw_common.h"
-#define MAX_CORES 24
-#define MAX_QUADS 6
-#define MAX_CMES 12
-#define CORES_PER_QUAD (MAX_CORES/MAX_QUADS)
-#define CORES_PER_CME (MAX_CORES/MAX_CMES)
-#define CMES_PER_QUAD (MAX_CMES/MAX_QUADS)
+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);
-#define QUAD_SCOM_ADDR_MASK 0x07000000
-#define CME_SCOM_ADDR_MASK 0x00000C00
-#define QUAD_CME_SCOM_ADDR_MASK_CLR ~(QUAD_SCOM_ADDR_MASK|CME_SCOM_ADDR_MASK)
-
-#define QUAD_SCOM_ADDR_INCR (uint32_t)0x01000000
-#define CME_SCOM_ADDR_OFFSET (uint32_t)0x00000400
-#define CME_SCOM_ADDR_INCR (uint32_t)0x00000400
-#define CORE_SCOM_ADDR_OFFSET (uint32_t)0x20000000
-#define CORE_SCOM_ADDR_INCR (uint32_t)0x01000000
-#define CORE_SEL_LEFT (uint32_t)0x00800000
-#define CORE_SEL_RIGHT (uint32_t)0x00400000
-
-//#define TRUE 1
-//#define FALSE 0
-
-#define RIGHT_SHIFT_PTRN_0x8_32BIT (uint32_t)0x80000000
-#define RIGHT_SHIFT_PTRN_0xC_32BIT (uint32_t)0xC0000000
-#define RIGHT_SHIFT_PTRN_0xF_32BIT (uint32_t)0xF0000000
-#define RIGHT_SHIFT_PTRN_0x8_64BIT (uint64_t)0x8000000000000000
-
-//
-// HOMER variables updated by PGPE
-//
-extern uint32_t ULTRA_TURBO_FREQ_STEPS_PS;
-
-
-#define VEXT_SLEW_RATE_MVPERUS 0x0A0A // Trise=Tfall=10mv/us
-#define MAX_POLL_COUNT_AVS 10
-/*
-// We define four levels of TRACE outputs:
-// _INF: Trace level used for main informational events.
-// _DBG: Trace level used for expanded debugging.
-// _WARN: Trace level used when suspecious event happens.
-// _ERR: Trace level at time of an error that leads to a halt.
-#define MY_TRACE_INF(...) PK_TRACE("INF: "__VA_ARGS__);
-#ifdef DEV_DEBUG
- #define MY_TRACE_DBG(...) PK_TRACE("DBG: "__VA_ARGS__);
-#else
- #define MY_TRACE_DBG(...)
-#endif
-#define MY_TRACE_WARN(...) PK_TRACE("WARN: "__VA_ARGS__);
-#define MY_TRACE_ERR(...) PK_TRACE("ERR: "__VA_ARGS__);
-*/
-
-//
-// PIR defines
-//
-#define PIR_INSTANCE_EVEN_ODD_MASK (uint32_t)(0x00000001)
-#define PIR_INSTANCE_NUM_MASK (uint32_t)(0x0000001F)
-
-
-//
-// CME FLAGS defines
-//
-#define CME_FLAGS_STOP_READY (uint32_t)(0x80000000)
-#define CME_FLAGS_PMCR_READY (uint32_t)(0x40000000)
-#define CME_FLAGS_QMGR_READY (uint32_t)(0x20000000)
-#define CME_FLAGS_QMGR_MASTER (uint32_t)(0x10000000)
-#define CME_FLAGS_RCLK_READY (uint32_t)(0x08000000)
-#define CME_FLAGS_IVRM_READY (uint32_t)(0x04000000)
-#define CME_FLAGS_VDM_READY (uint32_t)(0x02000000)
-
-
-//
-// Pstate defines
-//
-enum PSTATE_REQUEST_MODE_VALUES // Partially supported in GA1
-{
- PS_REQ_MODE_DEFAULT = 0,
- PS_REQ_MODE_RELATIVE = 1,
- PS_REQ_MODE_QOS = 2, // Only mode supported in GA1
- PS_REQ_MODE_PERFORMANCE = 3,
- PS_REQ_MODE_LAST = 4
-};
-
-enum PSTATE_REQUEST_PRIORITY_VALUES // Not supported in GA1
-{
- PS_REQ_PRTY_LOW = 0,
- PS_REQ_PRTY_MEDIUM = 1,
- PS_REQ_PRTY_HIGH = 2,
- PS_REQ_PRTY_OVERRIDE = 3,
- PS_REQ_PRTY_LAST = 4
-};
-
-typedef union pmcr_pstate_request
-{
-
- uint32_t value;
- struct
- {
-#ifdef _BIG_ENDIAN
- uint32_t reserved1 : 6;
- uint32_t mode : 2; // Partialy supported in GA1
- uint32_t ps_upper : 8; // NOT supported in GA1
- uint32_t reserved2 : 6;
- uint32_t priority : 2; // NOT supported in GA1
- uint32_t ps_lower : 8; // Only Pstate supported in GA1
-#else
- uint32_t ps_lower : 8;
- uint32_t priority : 2;
- uint32_t reserved2 : 6;
- uint32_t ps_upper : 8;
- uint32_t mode : 2;
- uint32_t reserved1 : 6;
-#endif // _BIG_ENDIAN
- } fields;
-
-} pmcr_pstate_request_t;
-
-typedef struct pstate_actuation_results
-{
-
- uint32_t freq_quad_last[MAX_QUADS];
- uint32_t freq_quad_avg[MAX_QUADS];
- uint32_t freq_chip_last;
- uint32_t freq_chip_avg;
- uint32_t vdd_quad_last[MAX_QUADS];
- uint32_t vdd_quad_avg[MAX_QUADS];
- uint32_t vdd_chip_last;
- uint32_t vdd_chip_avg;
-
-} pstate_actuation_results_t;
-
-
-//
-// QCME<->PGPE API
-//
-
-enum MESSAGE_ID_DB0
-{
- MSGID_DB0_INVALID = 0,
- MSGID_DB0_RESUME = 1,
- MSGID_DB0_SUSPEND = 2,
- MSGID_DB0_RESET = 3,
- MSGID_DB0_PS_BROADCAST = 4,
- MSGID_DB0_ACK = 5
-};
-
-enum MESSAGE_ID_DB3
-{
- MSGID_DB3_INVALID = 0,
- MSGID_DB3_SAFE_MODE = 1,
- MSGID_DB3_PS_BROADCAST = 2,
- MSGID_DB3_ACK = 3
-};
-
-enum MESSAGE_ID_TYPE4
-{
- MSGID_T4_INVALID = 0,
- MSGID_T4_REGISTER_QCME = 1,
- MSGID_T4_ACK = 2
-};
-
-//-------------
-// Doorbell0
-//-------------
-
-// PGPE->QCME: cb_to_qcme_base
-// ------------------------------------
-// This CB to decode the msg_id.
-//
-typedef union comm_block_to_qcme_base
-{
- 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 // _BIG_ENDIAN
- } fields;
-} cb_to_qcme_base_t;
-
-// PGPE->QCME: cb_to_qcme_ps_bc
-// ------------------------------------
-// This CB is used by PGPE to broadcast Pstate requests.
-//
-typedef union comm_block_to_qcme_ps_bc
-{
- uint64_t value;
- struct
- {
-#ifdef _BIG_ENDIAN
- uint64_t msg_id : 8;
- uint64_t ps_global : 8;
- uint64_t ps_local : 8;
- uint64_t reserved : 40;
-#else
- uint64_t reserved : 40;
- uint64_t ps_local : 8;
- uint64_t ps_global : 8;
- uint64_t msg_id : 8;
-#endif // _BIG_ENDIAN
- } fields;
-} cb_to_qcme_ps_bc_t;
-
-// PGPE->QCME: cb_to_qcme_ack
-// ---------------------------
-// This CB is used by PGPE to acknowledge CME requests.
-//
-typedef union comm_block_to_qcme_ack
-{
- uint64_t value;
- struct
- {
-#ifdef _BIG_ENDIAN
- uint64_t msg_id : 8;
- uint64_t msg_id_ref : 8;
- uint64_t rc : 8;
- uint64_t reserved : 40;
-#else
- uint64_t reserved : 40;
- uint64_t rc : 8;
- uint64_t msg_id_ref : 8;
- uint64_t msg_id : 8;
-#endif // _BIG_ENDIAN
- } fields;
-} cb_to_qcme_ack_t;
-
-
-//--------------
-// Type4
-//--------------
-
-// QCME->PGPE: cb_to_pgpe_base
-// ----------------------------
-// Used by PGPE to decode the msg_id.
-//
-typedef union comm_block_to_pgpe_base
-{
- uint16_t value;
- struct
- {
-#ifdef _BIG_ENDIAN
- uint16_t do_not_use : 4;
- uint16_t msg_id : 3;
- uint16_t reserved : 9;
-#else
- uint16_t reserved : 9;
- uint16_t msg_id : 3;
- uint16_t do_not_use : 4;
-#endif // _BIG_ENDIAN
- } fields;
-} cb_to_pgpe_base_t;
-
-// QCME->PGPE: cb_to_pgpe_qcme
-// ----------------------------
-// Used by QCME to register itself with the PGPE.
-//
-typedef union comm_block_to_pgpe_qcme
+typedef struct
{
- uint16_t value;
- struct
- {
-#ifdef _BIG_ENDIAN
- uint16_t do_not_use : 4;
- uint16_t msg_id : 3;
- uint16_t reserved : 9;
-#else
- uint16_t reserved : 9;
- uint16_t msg_id : 3;
- uint16_t do_not_use : 4;
-#endif // _BIG_ENDIAN
- } fields;
-} cb_to_pgpe_qcme_t;
+ PkSemaphore sem[2];
+} CmePstateRecord;
-// QCME->PGPE: cb_to_pgpe_ack
-// ---------------------------
-// Used by QCME to acknowledge DB requests.
-//
-typedef union comm_block_to_pgpe_ack
+typedef struct
{
- uint16_t value;
- struct
- {
-#ifdef _BIG_ENDIAN
- uint16_t do_not_use : 4;
- uint16_t msg_id : 3;
- uint16_t msg_id_ref : 3; // Put msg_id from PGPE request
- uint16_t reserved : 3;
- uint16_t rc : 3;
-#else
- uint16_t rc : 3;
- uint16_t reserved : 3;
- uint16_t msg_id_ref : 3;
- uint16_t msg_id : 3;
- uint16_t do_not_use : 4;
-#endif // _BIG_ENDIAN
- } fields;
-} cb_to_pgpe_ack_t;
+ uint64_t seqNum;
+ uint32_t cmeFlags;
+ uint8_t coreGood[CORES_PER_EX];
+} cme_pstate_pmcr_data_t;
-//
-// Return Codes
-//
-enum API_RETURN_CODES
+typedef struct
{
- API_RC_INVALID = 0, // Don't use zero. Not reliable.
- API_RC_SUCCESS = 1,
- API_RC_FAILURE = 2
-};
+ uint8_t qmFlag;
+ uint8_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;
+} cme_pstate_db_data_t;
diff --git a/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk b/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk
index f4254d07..4a8b5ce6 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk
+++ b/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk
@@ -29,8 +29,10 @@ 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
+ utils/plat_ring_traverse.c
+
+PSTATE-C-SOURCES = pstate_cme/p9_cme_pstate.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/Makefile b/import/chips/p9/procedures/ppe_closed/pgpe/Makefile
index 298bceac..1a291ab7 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/Makefile
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/Makefile
@@ -30,8 +30,8 @@ ifndef BASE_SRCDIR
BASE_SRCDIR = $(abspath ./)
endif
-CME_OBJDIR = $(abspath ../cme/obj/)
-CME_SRCDIR = $(abspath ../cme/)
+#CME_OBJDIR = $(abspath ../cme/obj/)
+#CME_SRCDIR = $(abspath ../cme/)
PGPE_OBJDIR = $(BASE_OBJDIR)
PGPE_SRCDIR = $(BASE_SRCDIR)
@@ -41,32 +41,35 @@ endif
THASH = $(PPETRACEPP_DIR)/tracehash.pl
-CME_IMAGE_NAME = cme
+#CME_IMAGE_NAME = cme
GPE_IMAGE_NAME = pstate_gpe
+#NEEDED_IMAGES = \
+ # $(CME_OBJDIR)/$(CME_IMAGE_NAME)/$(CME_IMAGE_NAME).out \
+ $(PGPE_OBJDIR)/$(GPE_IMAGE_NAME)/$(GPE_IMAGE_NAME).out
NEEDED_IMAGES = \
- $(CME_OBJDIR)/$(CME_IMAGE_NAME)/$(CME_IMAGE_NAME).out \
$(PGPE_OBJDIR)/$(GPE_IMAGE_NAME)/$(GPE_IMAGE_NAME).out
+
#default is to build images
needed_images: $(NEEDED_IMAGES)
-run: $(NEEDED_IMAGES)
- $(SIMICS_WS)/simics \
- -e '$$cme_binary_to_load=$(CME_OBJDIR)/$(CME_IMAGE_NAME)/$(CME_IMAGE_NAME).out' \
- -e '$$gpe_binary_to_load=$(PGPE_OBJDIR)/$(GPE_IMAGE_NAME)/$(GPE_IMAGE_NAME).out' \
- modelsetup.simics
+#run: $(NEEDED_IMAGES)
+# $(SIMICS_WS)/simics \
+# -e '$$cme_binary_to_load=$(CME_OBJDIR)/$(CME_IMAGE_NAME)/$(CME_IMAGE_NAME).out' \
+# -e '$$gpe_binary_to_load=$(PGPE_OBJDIR)/$(GPE_IMAGE_NAME)/$(GPE_IMAGE_NAME).out' \
+# modelsetup.simics
#clean the obj directory
clean:
- rm -fr $(CME_OBJDIR)/$(CME_IMAGE_NAME)
+# rm -fr $(CME_OBJDIR)/$(CME_IMAGE_NAME)
rm -fr $(PGPE_OBJDIR)/$(GPE_IMAGE_NAME)
#make binary application images
-$(CME_OBJDIR)/$(CME_IMAGE_NAME)/$(CME_IMAGE_NAME).out:
- (cd $(CME_SRCDIR) && make && make fmode && make tracehash)
+#$(CME_OBJDIR)/$(CME_IMAGE_NAME)/$(CME_IMAGE_NAME).out:
+# (cd $(CME_SRCDIR) && make && make fmode && make tracehash)
$(PGPE_OBJDIR)/$(GPE_IMAGE_NAME)/$(GPE_IMAGE_NAME).out:
(cd $(PGPE_SRCDIR)/$(GPE_IMAGE_NAME) && make && make fmode && make tracehash)
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.c
index 909464b3..016b4613 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.c
@@ -37,7 +37,7 @@
#include "pk.h"
#include "avs_driver.h"
-#include "pstate.h"
+//#include "pstate.h"
//#################################################################################################
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.h
index 5060261a..a07b9792 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/avs_driver.h
@@ -25,9 +25,18 @@
//
// Setup and enable the O2S bridge on the AVS bus.
//
+
+#ifndef _AVS_DRIVER_H_
+#define _AVS_DRIVER_H_
+
+#define VEXT_SLEW_RATE_MVPERUS 0x0A0A // Trise=Tfall=10mv/us
+#define MAX_POLL_COUNT_AVS 10
+
void
external_voltage_control_init(uint32_t* vext_read_mv);
void
external_voltage_control_write(uint32_t vext_write_mv);
+
+#endif //_AVS_DRIVER_H_
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
new file mode 100644
index 00000000..7b5a21f2
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe.h
@@ -0,0 +1,67 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe.h $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2015,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 */
+///
+/// \file p9_pgpe.h
+/// \brief header of p9_cme_stop_enter_thread.c and p9_cme_stop_exit.c
+///
+
+#ifndef _P9_PGPE_H_
+#define _P9_PGPE_H_
+
+#include "pk.h"
+#include "ppe42.h"
+#include "ppe42_scom.h"
+
+#include "ppehw_common.h"
+#include "gpehw_common.h"
+#include "occhw_interrupts.h"
+
+#include "ocb_register_addresses.h"
+#include "cme_register_addresses.h"
+#include "ppm_register_addresses.h"
+#include "cppm_register_addresses.h"
+#include "qppm_register_addresses.h"
+
+#include "ocb_firmware_registers.h"
+#include "cme_firmware_registers.h"
+#include "ppm_firmware_registers.h"
+#include "cppm_firmware_registers.h"
+#include "qppm_firmware_registers.h"
+
+#include "p9_pgpe_irq.h"
+#include "p9_pstate_common.h"
+
+
+/// PGPE PState
+typedef struct
+{
+ PkSemaphore sem[1];
+} PgpePstateRecord;
+
+/// PGPE PState
+void p9_pgpe_pstate_pig_handler(void* arg, PkIrqId irq);
+void p9_pgpe_pstate_thread(void* arg);
+
+#endif //_P9_PGPE_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
new file mode 100644
index 00000000..6ab938dc
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.c
@@ -0,0 +1,199 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.c $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2015,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 */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file p9_pgpe_irq.c
+/// \brief Shared and global file for PGPE (GPE2) H-codes.
+///
+
+#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
+// as the index into the ext_irq_vectors_gpe[][] table.
+
+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_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_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_PRTY3_GPE2, IRQ_VEC_PRTY3_GPE2 } , /* 3: IDX_PRTY_LVL_TYPE1 */
+
+ { IRQ_VEC_PRTY4_GPE2, IRQ_VEC_PRTY4_GPE2 } /* 4: IDX_PRTY_LVL_DISABLED */
+
+ /* 0: IDX_PRTY_VEC 1: IDX_MASK_VEC */
+};
+
+/*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;
+
+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;
+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.
+//
+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 |
+ // (uint64_t)in32(OCB_OISR1);
+ //CMO-swap above lines comments when we've defined the HI PRTY interrupts correctly, i.e.
+ // right now they fire all the time because by default they are defined as LEVEL
+ // SENSITIVE and ACTIVE LOW.
+ bFound = FALSE;
+ iPrtyLvl = 0;
+
+ do
+ {
+ if ( ext_irq_vectors_gpe[iPrtyLvl][IDX_PRTY_VEC] & ext_irq_vector_pk )
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+ 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.
+ //
+ 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) );
+
+ }
+ else
+ {
+ MY_TRACE_ERR("A disabled IRQ fired");
+ MY_TRACE_ERR("ext_irq_vector_pk=0x%08x%08x", ext_irq_vector_pk);
+ 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.
+ //
+
+ 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]) );
+
+}
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
new file mode 100644
index 00000000..4f9e6eb1
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.h
@@ -0,0 +1,144 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_irq.h $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2015,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 */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2015
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file p9_pgpe_irq.h
+/// \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
+// in this file are:
+// - IRQ_VEC_PRTY(n>0)_GPE(x)
+// - 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_
+
+// We define four levels of TRACE outputs:
+// _INF: Trace level used for main informational events.
+// _DBG: Trace level used for expanded debugging.
+// _WARN: Trace level used when suspecious event happens.
+// _ERR: Trace level at time of an error that leads to a halt.
+#define MY_TRACE_INF(...) PK_TRACE("INF: "__VA_ARGS__);
+#ifdef DEV_DEBUG
+ #define MY_TRACE_DBG(...) PK_TRACE("DBG: "__VA_ARGS__);
+#else
+ #define MY_TRACE_DBG(...)
+#endif
+#define MY_TRACE_WARN(...) PK_TRACE("WARN: "__VA_ARGS__);
+#define MY_TRACE_ERR(...) PK_TRACE("ERR: "__VA_ARGS__);
+
+#define TRUE 1
+#define FALSE 0
+
+#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_DISABLED 4
+#define IDX_PRTY_VEC 0
+#define IDX_MASK_VEC 1
+#define NUM_EXT_IRQ_PRTY_LEVELS (uint8_t)(5)
+extern const uint64_t ext_irq_vectors_gpe[NUM_EXT_IRQ_PRTY_LEVELS][2];
+
+#define IRQ_VEC_PRTY0_GPE (uint64_t)(0xFFD1690000000000) // Non-task hi-prty IRQs
+// Shared between all instances
+#define IRQ_VEC_PRTY1_GPE2 (uint64_t)(0x0020000000000000) // 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)(0x000E96EFFFFDBFFF) // 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!
+
+#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;*/
+
+extern uint8_t g_current_prty_level;
+extern uint8_t g_oimr_stack[NUM_EXT_IRQ_PRTY_LEVELS];
+extern int g_oimr_stack_ctr;
+extern uint64_t g_oimr_override_stack[NUM_EXT_IRQ_PRTY_LEVELS];
+extern uint64_t g_oimr_override;
+
+
+/// Restore a vector of interrupts by overwriting OIMR.
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_vec_restore( PkMachineContext* context)
+{
+ pk_critical_section_enter(context);
+
+ if (g_oimr_stack_ctr >= 0)
+ {
+ out32( OCB_OIMR0_CLR, (uint32_t)((IRQ_VEC_ALL_OUR_IRQS |
+ g_oimr_override_stack[g_oimr_stack_ctr]) >> 32));
+ out32( OCB_OIMR1_CLR, (uint32_t)(IRQ_VEC_ALL_OUR_IRQS |
+ g_oimr_override_stack[g_oimr_stack_ctr]));
+ out32( OCB_OIMR0_OR,
+ (uint32_t)((ext_irq_vectors_gpe[g_oimr_stack[g_oimr_stack_ctr]][IDX_MASK_VEC] |
+ g_oimr_override) >> 32));
+ out32( OCB_OIMR1_OR,
+ (uint32_t)(ext_irq_vectors_gpe[g_oimr_stack[g_oimr_stack_ctr]][IDX_MASK_VEC] |
+ g_oimr_override));
+ // Restore the prty level tracker to the task that was interrupted, if any.
+ g_current_prty_level = g_oimr_stack[g_oimr_stack_ctr];
+ g_oimr_stack_ctr--;
+ }
+ else
+ {
+ PK_TRACE("ERR: Code bug: Messed up OIMR book keeping: g_oimr_stack_ctr=%d",
+ g_oimr_stack_ctr);
+ pk_halt();
+ }
+
+ pk_critical_section_exit(context);
+}
+
+#endif // _P9_PGPE_IRQ_H_
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
new file mode 100644
index 00000000..865edf3c
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_main.c
@@ -0,0 +1,142 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_main.c $ */
+/* */
+/* OpenPOWER HCODE Project */
+/* */
+/* COPYRIGHT 2015,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"
+
+PgpePstateRecord G_pgpe_pstate_record;
+
+EXTERNAL_IRQ_TABLE_START
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_DEBUGGER
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_TRACE_TRIGGER
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_OCC_ERROR
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PBA_ERROR
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_SRT_ERROR
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_GPE0_HALT
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_GPE1_HALT
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_GPE2_HALT
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_GPE3_HALT
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PPC405_HALT
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_OCB_ERROR
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_SPIPSS_ERROR
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_CHECK_STOP_PPC405
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_CHECK_STOP_GPE0
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_CHECK_STOP_GPE1
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_CHECK_STOP_GPE2
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_CHECK_STOP_GPE3
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_OCC_MALF_ALERT
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_ADU_MALF_ALERT
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_EXTERNAL_TRAP
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IVRM_PVREF_ERROR
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_OCC_TIMER0
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_OCC_TIMER1
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_AVS_SLAVE0
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_AVS_SLAVE1
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI0_HI_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI1_HI_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI2_HI_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI3_HI_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI4_HI_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_ADCFSM_ONGOING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_RESERVED_31
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PBAX_OCC_SEND
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PBAX_OCC_PUSH0
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PBAX_OCC_PUSH1
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PBA_BCDE_ATTN
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PBA_BCUE_ATTN
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_STRM0_PULL
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_STRM0_PUSH
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_STRM1_PULL
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_STRM1_PUSH
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_STRM2_PULL
+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])
+//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
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_PCB_INTR_TYPE4_PENDING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_PCB_INTR_TYPE5_PENDING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_PCB_INTR_TYPE6_PENDING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_PCB_INTR_TYPE7_PENDING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_O2S_0A_ONGOING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_O2S_0B_ONGOING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_O2S_1A_ONGOING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PMC_O2S_1B_ONGOING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_PSSBRIDGE_ONGOING
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI0_LO_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI1_LO_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI2_LO_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI3_LO_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_IPI4_LO_PRIORITY
+IRQ_HANDLER_DEFAULT //OCCHW_IRQ_RESERVED_63
+EXTERNAL_IRQ_TABLE_END
+
+#define KERNEL_STACK_SIZE 512
+#define THREAD_STACK_SIZE 512
+
+#define PGPE_THREAD_PRIORITY_PSTATE 1
+
+uint8_t G_kernel_stack[KERNEL_STACK_SIZE];
+
+uint8_t G_p9_pgpe_pstate_thread_stack[THREAD_STACK_SIZE];
+
+PkThread G_p9_pgpe_pstate_thread;
+
+void __eabi()
+{
+}
+
+int
+main(int argc, char** argv)
+{
+ // 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_stop_enter_thread
+ pk_thread_create(&G_p9_pgpe_pstate_thread,
+ (PkThreadRoutine)p9_pgpe_pstate_thread,
+ (void*)NULL,
+ (PkAddress)G_p9_pgpe_pstate_thread_stack,
+ (size_t)THREAD_STACK_SIZE,
+ (PkThreadPriority)PGPE_THREAD_PRIORITY_PSTATE);
+
+ PK_TRACE_BIN("G_p9_pgpe_pstate_thread",
+ &G_p9_pgpe_pstate_thread,
+ sizeof(G_p9_pgpe_pstate_thread));
+
+ // Make G_p9_sgpe_stop_exit_thread runnable
+ pk_thread_resume(&G_p9_pgpe_pstate_thread);
+
+ // Start running the highest priority thread.
+ // This function never returns
+ pk_start_threads();
+
+ return 0;
+}
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
new file mode 100644
index 00000000..b28a9dfe
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.c
@@ -0,0 +1,663 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_pstate.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_pstate_vpd.h" //\todo Temporary
+#include "p9_pstate_common.h"
+#include "p9_pgpe.h"
+#include "avs_driver.h"
+
+#define EVID_SLOPE_FP_SHIFT 13
+#define CCSR_CORE_CONFIG_MASK 0xC0000000
+
+enum quadManager
+{
+ QUAD_MANAGER_NONE = -1,
+ QUAD_MANAGER_CME0 = 0,
+ QUAD_MANAGER_CME1 = 1
+};
+
+//Data derived from VPD(PPB)
+uint16_t G_FVSlopes[VPD_PV_POINTS - 1];
+uint16_t G_invFVSlopes[VPD_PV_POINTS - 1];
+
+//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];
+uint8_t G_coreConf[MAX_CORES];
+extern PgpePstateRecord G_pgpe_pstate_record;
+extern global_pstate_table_t G_gpst;
+
+//
+//Function Prototypes
+//
+void p9_pgpe_pstate_init_derived_data();
+void p9_pgpe_pstate_get_config();
+uint32_t p9_pgpe_pstate_get_evid_from_pstate(uint8_t pstate);
+uint8_t p9_pgpe_pstate_get_pstate_from_evid(uint16_t evid);
+void p9_pgpe_pstate_update_ext_volt();
+void p9_pgpe_pstate_freq_update();
+
+//
+//PIG Interrupt Handler
+//
+void p9_pgpe_pstate_pig_handler(void* arg, PkIrqId irq)
+{
+ //Read OCC_FLAG[PGPE_STARTNOTSTOP]]
+ uint32_t occFlag = in32(OCB_OCCFLG);
+
+ if (occFlag & BIT32(0))
+ {
+ pk_semaphore_post((PkSemaphore*)arg);
+ }
+
+}
+
+//
+//PState Thread
+//
+void p9_pgpe_pstate_thread(void* arg)
+{
+ 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;
+
+ //Initialization
+
+ //todo Read this data from HOMER/PPMR. RTC 159902
+ p9_pstate_vpd_init();
+
+ //\todo Set initial eVid, Global PState, Local PState, Max/Mins PStateClip for PGPE. RTC. 159900
+ psClipMax = 0;
+ psClipMin = 140;
+ coresPendPSReq = 0;
+ G_eVidCurr = G_gpst.infPT[POWERSAVE].evid;
+ G_eVidNext = G_gpst.infPT[POWERSAVE].evid;
+ G_globalCurrPS = G_globalNextPS = G_gpst.infPT[POWERSAVE].pstate;
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ G_localPSCurr[q] = G_gpst.infPT[POWERSAVE].pstate;
+ G_localPSNext[q] = G_gpst.infPT[POWERSAVE].pstate;
+ G_localPSTgt[q] = G_gpst.infPT[POWERSAVE].pstate;
+ G_quadPendPSReq[q] = 0;
+ }
+
+ for (c = 0; c < MAX_CORES; c++)
+ {
+ G_coresPendPSReqData[c] = G_gpst.infPT[POWERSAVE].pstate;
+ }
+
+ //Initialization
+ external_voltage_control_init(&G_eVidCurr);
+ G_eVidCurr = G_gpst.infPT[POWERSAVE].evid; //\todo RTC 159900. Remove this
+ p9_pgpe_pstate_init_derived_data();
+ 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);
+
+ //Set OCC_FLAG[PGPE_ACTIVE]
+ out32(OCB_OCCFLG_OR, BIT32(4));
+#if EPM_P9_TUNING
+ asm volatile ("tw 0, 31, 0");
+#endif
+
+ //Thread Loop
+ while (1)
+ {
+ //pend on semaphore
+ pk_semaphore_pend(&(G_pgpe_pstate_record.sem[0]), PK_WAIT_FOREVER);
+
+ done = 0;
+
+ while (done == 0)
+ {
+ //Snapshot
+ coresPendPSReq = in32(OCB_OPIT1PRA);
+
+ //Make sure clips aren't below or above VPD points
+ if (psClipMax < G_gpst.infPT[ULTRA].pstate)
+ {
+ effPSClipMax = G_gpst.infPT[ULTRA].pstate;
+ }
+ else
+ {
+ effPSClipMax = psClipMax;
+ }
+
+ if (psClipMin > G_gpst.infPT[POWERSAVE].pstate)
+ {
+ effPSClipMin = G_gpst.infPT[POWERSAVE].pstate;
+ }
+ else
+ {
+ effPSClipMin = psClipMin;
+ }
+
+ 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_type_a_core_n;
+ uint16_t op1 = opit1cn.fields.pcb_intr_type_a_core_n;
+
+ //make sure seq number matches for both phases
+ //otherwise, ignore the request
+ if (((op0 >> 10) && 0x3) ==
+ ((op1 >> 10) && 0x3))
+ {
+ //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
+ }
+ }
+ }
+
+ //Local PStates
+ 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_gpst.infPT[POWERSAVE].pstate;
+
+ for (c = (q * CORES_PER_QUAD); c < (q + 1)*CORES_PER_QUAD; c++)
+ {
+ if (G_coreConf[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;
+ }
+ }
+
+ //Global PState
+ G_globalPSTgt = G_gpst.infPT[POWERSAVE].pstate;
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ if ((G_quadManagerCME[q] != QUAD_MANAGER_NONE))
+ {
+ if (G_globalPSTgt > G_localPSTgt[q])
+ {
+ G_globalPSTgt = G_localPSTgt[q];
+ }
+ }
+ }
+
+
+#if EPM_P9_TUNING
+ asm volatile ("tw 0, 31, 0");
+#endif
+
+ //Determine targetVoltage
+ G_tgtEVid = p9_pgpe_pstate_get_evid_from_pstate(G_globalPSTgt);
+
+ //Higher number PState
+ if (((int16_t)(G_globalPSTgt) - (int16_t)(G_globalCurrPS)) > 0)
+ {
+ if ((G_eVidCurr - G_tgtEVid) <= G_gpst.evid_step_size)
+ {
+ 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_gpst.evid_step_size;
+ G_globalNextPS = p9_pgpe_pstate_get_pstate_from_evid(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_freq_update();
+ p9_pgpe_pstate_update_ext_volt();
+ }
+ //Lower number PState
+ else if (((int16_t)(G_globalPSTgt) - (int16_t)(G_globalCurrPS)) < 0)
+ {
+ if ((G_tgtEVid - G_eVidCurr) <= G_gpst.evid_step_size)
+ {
+ 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_gpst.evid_step_size;
+ G_globalNextPS = p9_pgpe_pstate_get_pstate_from_evid(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();
+ }
+ else
+ {
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ G_localPSNext[q] = G_localPSTgt[q];
+ }
+
+ p9_pgpe_pstate_freq_update();
+ done = 1;
+ }
+ }
+
+ pk_irq_vec_restore(&ctx);//Restore interrupts
+ }//Thread Loop
+}
+
+//
+//init_vpd_derived_data
+//
+void p9_pgpe_pstate_init_derived_data()
+{
+ int32_t i;
+ uint32_t eVidFP[VPD_PV_POINTS];
+
+ //convert to fixed-point number
+ for (i = 0; i < VPD_PV_POINTS; i++)
+ {
+ eVidFP[i] = (G_gpst.infPT[i].evid << EVID_SLOPE_FP_SHIFT);
+ }
+
+ //PState(Frequency) on y-axis, Voltage is on x-axis for VF curve
+ //Interpolation formula: (y-y0)/(x-x0) = (y1-y0)/(x1-x0)
+ //m = (x1-x0)/(y1-y0), then use this to calculate voltage, x = (y-y0)*m + x0
+ //1/m = (y1-y0)/(x1-x0) here, then use this to calculate pstate(frequency), y = (x-x0)*m + y0
+ //Region 0 is b/w POWERSAVE and NOMINAL
+ //Region 1 is b/w NOMINAL and TURBO
+ //Region 2 is between TURBO and ULTRA_TURBO
+ //
+ //Inflection Point 3 is ULTRA_TURBO
+ //Inflection Point 2 is TURBO
+ //Inflection Point 1 is NOMINAL
+ //Inflection Point 0 is POWERSAVE
+ //
+ for (i = 0; i < VPD_PV_POINTS - 1; i++)
+ {
+ //Note: Since PState number decrease with frequency,
+ //we flip the sign(add a minus)
+ uint32_t tmp = (uint32_t)(eVidFP[i + 1] - eVidFP[i]) /
+ (uint32_t)(-G_gpst.infPT[i + 1].pstate + G_gpst.infPT[i].pstate);
+ G_FVSlopes[i] = tmp;
+
+ tmp = (uint32_t)((-G_gpst.infPT[i + 1].pstate + G_gpst.infPT[i].pstate) << EVID_SLOPE_FP_SHIFT)
+ / (uint32_t) (G_gpst.infPT[i + 1].evid - G_gpst.infPT[i].evid);
+ G_invFVSlopes[i] = tmp;
+ }
+}
+
+//
+//p9_pgpe_pstate_get_evid_from_pstate
+//
+uint32_t p9_pgpe_pstate_get_evid_from_pstate(uint8_t pstate)
+{
+ uint32_t ret_evid;
+
+ //Interpolate voltage based on the region PState falls under
+ if (pstate > G_gpst.infPT[ULTRA].pstate
+ && pstate < G_gpst.infPT[TURBO].pstate)
+ {
+ ret_evid = (((G_FVSlopes[REGION_TURBO_ULTRA]) *
+ (-pstate + G_gpst.infPT[TURBO].pstate)) >> EVID_SLOPE_FP_SHIFT)
+ + G_gpst.infPT[TURBO].evid;
+ }
+ else if (pstate > G_gpst.infPT[TURBO].pstate
+ && pstate < G_gpst.infPT[NOMINAL].pstate)
+ {
+ ret_evid = (((G_FVSlopes[REGION_NOMINAL_TURBO]) *
+ (-pstate + G_gpst.infPT[NOMINAL].pstate)) >> EVID_SLOPE_FP_SHIFT)
+ + G_gpst.infPT[NOMINAL].evid;
+ }
+ else if (pstate > G_gpst.infPT[NOMINAL].pstate
+ && pstate < G_gpst.infPT[POWERSAVE].pstate)
+ {
+ ret_evid = (((G_FVSlopes[REGION_POWERSAVE_NOMINAL]) *
+ (- pstate + G_gpst.infPT[POWERSAVE].pstate)) >> EVID_SLOPE_FP_SHIFT)
+ + G_gpst.infPT[POWERSAVE].evid;
+ }
+ else
+ {
+ if (pstate == G_gpst.infPT[ULTRA].pstate)
+ {
+ ret_evid = G_gpst.infPT[ULTRA].evid;
+ }
+ else if (pstate == G_gpst.infPT[TURBO].pstate)
+ {
+ ret_evid = G_gpst.infPT[TURBO].evid;
+ }
+ else if (pstate == G_gpst.infPT[NOMINAL].pstate)
+ {
+ ret_evid = G_gpst.infPT[NOMINAL].evid;
+ }
+ else if (pstate == G_gpst.infPT[POWERSAVE].pstate)
+ {
+ ret_evid = G_gpst.infPT[POWERSAVE].evid;
+ }
+ else
+ {
+ pk_halt();
+ }
+ }
+
+ return (ret_evid);
+}
+
+
+//
+//p9_pgpe_pstate_get_pstate_from_evid
+//
+uint8_t p9_pgpe_pstate_get_pstate_from_evid(uint16_t evid)
+{
+ uint32_t ret_ps;
+
+ //Interpolate pstate based on the region voltage falls under
+ if (evid < G_gpst.infPT[ULTRA].evid
+ && evid > G_gpst.infPT[TURBO].evid)
+ {
+ ret_ps = -(((G_invFVSlopes[REGION_TURBO_ULTRA]) *
+ (evid - G_gpst.infPT[TURBO].evid)) >> EVID_SLOPE_FP_SHIFT)
+ + G_gpst.infPT[TURBO].pstate;
+ }
+ else if (evid < G_gpst.infPT[TURBO].evid
+ && evid > G_gpst.infPT[NOMINAL].evid)
+ {
+ ret_ps = -(((G_invFVSlopes[REGION_NOMINAL_TURBO]) *
+ (evid - G_gpst.infPT[NOMINAL].evid)) >> EVID_SLOPE_FP_SHIFT)
+ + G_gpst.infPT[NOMINAL].pstate;
+ }
+ else if (evid < G_gpst.infPT[NOMINAL].evid
+ && evid > G_gpst.infPT[POWERSAVE].evid)
+ {
+ ret_ps = -(((G_invFVSlopes[REGION_POWERSAVE_NOMINAL]) *
+ (evid - G_gpst.infPT[POWERSAVE].evid)) >> EVID_SLOPE_FP_SHIFT)
+ + G_gpst.infPT[POWERSAVE].pstate;
+ }
+ else
+ {
+ if (evid == G_gpst.infPT[ULTRA].evid)
+ {
+ ret_ps = G_gpst.infPT[ULTRA].pstate;
+ }
+ else if (evid == G_gpst.infPT[TURBO].evid)
+ {
+ ret_ps = G_gpst.infPT[TURBO].pstate;
+ }
+ else if (evid == G_gpst.infPT[NOMINAL].evid)
+ {
+ ret_ps = G_gpst.infPT[NOMINAL].pstate;
+ }
+ else if (evid == G_gpst.infPT[POWERSAVE].evid)
+ {
+ ret_ps = G_gpst.infPT[POWERSAVE].pstate;
+ }
+ else
+ {
+ pk_halt();
+ }
+ }
+
+ return ret_ps;
+}
+
+uint8_t p9_pgpe_pstate_get_evid_region(uint32_t evid)
+{
+ if (evid > G_gpst.infPT[TURBO].evid)
+ {
+ return REGION_TURBO_ULTRA;
+ }
+ else if (evid < G_gpst.infPT[NOMINAL].evid)
+ {
+ return REGION_POWERSAVE_NOMINAL;
+ }
+ else
+ {
+ return REGION_NOMINAL_TURBO;
+ }
+}
+
+//
+//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];
+ 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;
+ }
+ }
+
+ //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 & (0x80000000 >> c))
+ {
+ 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;
+ }
+ }
+ }
+
+ //Update Current Global and Local PState
+ G_globalCurrPS = G_globalNextPS;
+
+ for (q = 0; q < MAX_QUADS; q++)
+ {
+ G_localPSCurr[q] = G_localPSNext[q];
+ }
+}
+
+//
+//Determine which CMEs are quad manager
+//
+void p9_pgpe_pstate_get_config()
+{
+ int32_t q, c;
+ ocb_ccsr_t ccsr;
+ ccsr.value = in32(OCB_CCSR);
+
+ for (c = 0; c < MAX_CORES; c++)
+ {
+ if (ccsr.value & (0x80000000 >> c))
+ {
+ G_coreConf[c] = 1;
+ }
+ else
+ {
+ G_coreConf[c] = 0;
+ }
+ }
+
+ 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;
+ }
+ }
+}
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 ea182c15..aefd2684 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
@@ -33,8 +33,37 @@
/// \file pk_app_cfg.h
/// \brief Application specific overrides go here.
///
-#include "occ_app_cfg.h"
-#include "global_app_cfg.h"
+
+// --------------------
+#define EPM_P9_TUNING 1
+#define SIMICS_TUNING 1
+#define DEV_DEBUG 1
+#define PK_TRACE_TIMER_OUTPUT 0
+
+// Force CME and GPE tasks to use the unified interrupt handler.
+#define UNIFIED_IRQ_HANDLER_GPE
+
+// This application will use the external timebase register
+// (comment this line out to use the decrementer as timebase)
+#define APPCFG_USE_EXT_TIMEBASE
+
+
+// If we are using the external timebase then assume
+// a frequency of 37.5Mhz. Otherwise, the default is to use
+// the decrementer as a timebase and assume a frequency of
+// 600MHz
+// In product code, this value will be IPL-time configurable.
+#ifdef APPCFG_USE_EXT_TIMEBASE
+ #define PPE_TIMEBASE_HZ 37500000
+#else
+ #define PPE_TIMEBASE_HZ 600000000
+#endif /* APPCFG_USE_EXT_TIMEBASE */
+
+// --------------------
+
+// GPE2 is the PGPE and is the route owner for now.
+// (Change this to #3 when pulling in SGPE)
+#define OCCHW_IRQ_ROUTE_OWNER 2
/// The Instance ID of the OCC processor that this application is intended to run on
///// 0-3 -> GPE, 4 -> 405
@@ -60,6 +89,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_TYPE4_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 f19d3907..212a8bde 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
@@ -30,7 +30,7 @@ EKB_BUILD = 1
## Set _TARGET = PPC2PPE to use the 405 compiler with PPE backend or
# set _TARGET = PPE to use the new native compiler
-$(IMAGE)_TARGET=PPC2PPE
+$(IMAGE)_TARGET=PPE
## PPE_TYPE can be std or gpe
_PPE_TYPE=gpe
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 414acd71..ca6f0a31 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
@@ -22,7 +22,7 @@
# permissions and limitations under the License.
#
# IBM_PROLOG_END_TAG
-TOP-C-SOURCES = pstate_gpe.c gpe2_irq_common.c pk_app_irq_table.c avs_driver.c
+TOP-C-SOURCES = p9_pgpe_pstate.c p9_pgpe_main.c p9_pgpe_irq.c avs_driver.c p9_pstate_vpd.c
TOP-S-SOURCES =
TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-S-SOURCES:.S=.o)
OpenPOWER on IntegriCloud