summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--import/chips/p9/common/pmlib/include/cmehw_interrupts.h23
-rw-r--r--import/chips/p9/common/pmlib/include/gpehw_common.h4
-rw-r--r--import/chips/p9/common/pmlib/include/p9_stop_common.h6
-rw-r--r--import/chips/p9/common/pmlib/include/registers/cme_register_addresses.h64
-rw-r--r--import/chips/p9/common/pmlib/include/registers/ppm_firmware_registers.h4
-rw-r--r--import/chips/p9/procedures/ppe/pk/gpe/gpe_common.h19
-rw-r--r--import/chips/p9/procedures/ppe/pk/gpe/gpe_irq.h48
-rw-r--r--import/chips/p9/procedures/ppe/pk/std/std_common.h10
-rw-r--r--import/chips/p9/procedures/ppe/pk/std/std_irq.h27
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/link.cmd121
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c183
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h136
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c229
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pk_app_cfg.h85
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pk_app_irq_table.c92
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.c750
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.h347
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop.h120
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_enter_marks.h44
-rwxr-xr-ximport/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c453
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c214
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit_marks.h94
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_irq_handlers.c44
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_chiplet_reset.c54
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_poweron.c37
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_startclocks.c78
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/topfiles.mk51
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_arrayinit.c4
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_init.c2
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_reset.c39
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_dpll_setup.c74
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_l2_startclocks.c27
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_occ_runtime_scom.c2
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_poweron.c49
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_ras_runtime_scom.c2
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scomcust.c2
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scominit.c2
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_startclocks.c140
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h112
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_enter_marks.h6
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c586
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit.c139
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit_marks.h94
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c201
-rw-r--r--import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/pk_app_cfg.h2
45 files changed, 3571 insertions, 1249 deletions
diff --git a/import/chips/p9/common/pmlib/include/cmehw_interrupts.h b/import/chips/p9/common/pmlib/include/cmehw_interrupts.h
index 738d9269..2b96d961 100644
--- a/import/chips/p9/common/pmlib/include/cmehw_interrupts.h
+++ b/import/chips/p9/common/pmlib/include/cmehw_interrupts.h
@@ -284,27 +284,4 @@
STD_IRQ_MASK64(CMEHW_IRQ_RESERVED_63))
*/
-////////////////////////////////////////////////////////////////////////////
-// Interrupt Mask Vector
-////////////////////////////////////////////////////////////////////////////
-
-// First, it should always be true to mask the given interrupt and every
-// interrupts has larger irq id number than the given one. Then if the given
-// interrupt belongs to a group of interrupts with same priority and the given
-// one is not the first one in the group(in which case it will automatically
-// work by first rule along), then an override bit mask can be used to mask out
-// every one else in the group above the given one, or used for special cases.
-#define CME_IRQ_MASK_VECTOR(irq) ((0xffffffffffffffffull << (irq)) >> (irq))
-#define CME_IRQ_MASK_VECTOR_AND(irq, amask) (CME_IRQ_MASK_VECTOR(irq) & amask)
-#define CME_IRQ_MASK_VECTOR_OR(irq, omask) (CME_IRQ_MASK_VECTOR(irq) | omask)
-
-#define CME_IRQ_MASK_DB3 CME_IRQ_MASK_VECTOR(CMEHW_IRQ_DOORBELL3_C0)
-#define CME_IRQ_MASK_WAKE CME_IRQ_MASK_VECTOR(CMEHW_IRQ_PC_INTR_PENDING_C0)
-#define CME_IRQ_MASK_DB2 CME_IRQ_MASK_VECTOR(CMEHW_IRQ_DOORBELL2_C0)
-#define CME_IRQ_MASK_STOP CME_IRQ_MASK_VECTOR(CMEHW_IRQ_PC_PM_STATE_ACTIVE_C0)
-#define CME_IRQ_MASK_DB0 CME_IRQ_MASK_VECTOR(CMEHW_IRQ_PMCR_UPDATE_C0)
-#define CME_IRQ_MASK_DB1 CME_IRQ_MASK_VECTOR(CMEHW_IRQ_DOORBELL1_C0)
-
-
-
#endif /* __CMEHW_INTERRUPTS_H__ */
diff --git a/import/chips/p9/common/pmlib/include/gpehw_common.h b/import/chips/p9/common/pmlib/include/gpehw_common.h
index 41c4eb93..8825d1b3 100644
--- a/import/chips/p9/common/pmlib/include/gpehw_common.h
+++ b/import/chips/p9/common/pmlib/include/gpehw_common.h
@@ -75,8 +75,8 @@ enum GPE_SCOM_ADDRESS_PARAMETERS
EX0_ADDR_OFFSET = 0x00000800,
EX1_ADDR_OFFSET = 0x00000C00,
CME_ADDR_BASE = 0x10012000,
- CME0_ADDR_OFFSET = 0x00000400,
- CME1_ADDR_OFFSET = 0x00000800
+ CME0_ADDR_OFFSET = 0x00000000,
+ CME1_ADDR_OFFSET = 0x00000400
};
diff --git a/import/chips/p9/common/pmlib/include/p9_stop_common.h b/import/chips/p9/common/pmlib/include/p9_stop_common.h
index 21e07aeb..9fac87f8 100644
--- a/import/chips/p9/common/pmlib/include/p9_stop_common.h
+++ b/import/chips/p9/common/pmlib/include/p9_stop_common.h
@@ -26,8 +26,8 @@
/// Init Vectors for Register Setup
enum P9_HCD_COMMON_INIT_VECTORS
{
- // (0)CHIPLET_ENABLE
// (1)PCB_EP_RESET
+ // (2)CLK_ASYNC_RESET
// (3)PLL_TEST_EN
// (4)PLLRST
// (5)PLLBYP
@@ -35,7 +35,9 @@ enum P9_HCD_COMMON_INIT_VECTORS
// (13)VITL_MPW2
// (14)VITL_MPW3
// (18)FENCE_EN
- NET_CTRL0_INIT_VECTOR = (BIT64(0) | BIT64(1) | BITS64(3, 3) | BITS64(12, 3) | BIT64(18)),
+ // (22)FUNC_CLKSEL
+ // (26)LVLTRANS_FENCE
+ NET_CTRL0_INIT_VECTOR = (BITS64(1, 5) | BITS64(3, 3) | BIT64(18) | BIT64(22) | BIT64(26)),
HANG_PULSE1_INIT_VECTOR = BIT64(5)
};
diff --git a/import/chips/p9/common/pmlib/include/registers/cme_register_addresses.h b/import/chips/p9/common/pmlib/include/registers/cme_register_addresses.h
index f0c16fe3..93b50634 100644
--- a/import/chips/p9/common/pmlib/include/registers/cme_register_addresses.h
+++ b/import/chips/p9/common/pmlib/include/registers/cme_register_addresses.h
@@ -55,21 +55,21 @@
#define CME_SCOM_CSAR 0x1001200d
#define CME_SCOM_CSDR 0x1001200e
#define CME_SCOM_BCECSR 0x1001200f
-#define CME_SCOM_BCEBAR0 0x10012010
-#define CME_SCOM_BCEBAR1 0x10012011
-#define CME_SCOM_QFMR 0x10012012
-#define CME_SCOM_AFSR 0x10012013
-#define CME_SCOM_AFTR 0x10012014
-#define CME_SCOM_VTSR0 0x10012015
-#define CME_SCOM_VTSR1 0x10012016
-#define CME_SCOM_VDSR 0x10012017
-#define CME_SCOM_EIIR 0x10012019
-#define CME_SCOM_FWMR 0x1001201a
-#define CME_SCOM_FWMR_CLR 0x1001201b
-#define CME_SCOM_FWMR_OR 0x1001201c
-#define CME_SCOM_SICR 0x1001201d
-#define CME_SCOM_SICR_CLR 0x1001201e
-#define CME_SCOM_SICR_OR 0x1001201f
+#define CME_SCOM_BCEBAR0 0x10012030
+#define CME_SCOM_BCEBAR1 0x10012031
+#define CME_SCOM_QFMR 0x10012032
+#define CME_SCOM_AFSR 0x10012033
+#define CME_SCOM_AFTR 0x10012034
+#define CME_SCOM_VTSR0 0x10012035
+#define CME_SCOM_VTSR1 0x10012036
+#define CME_SCOM_VDSR 0x10012037
+#define CME_SCOM_EIIR 0x10012039
+#define CME_SCOM_FWMR 0x1001203a
+#define CME_SCOM_FWMR_CLR 0x1001203b
+#define CME_SCOM_FWMR_OR 0x1001203c
+#define CME_SCOM_SICR 0x1001203d
+#define CME_SCOM_SICR_CLR 0x1001203e
+#define CME_SCOM_SICR_OR 0x1001203f
#define CME_SCOM_FLAGS 0x10012020
#define CME_SCOM_FLAGS_CLR 0x10012021
#define CME_SCOM_FLAGS_OR 0x10012022
@@ -83,22 +83,22 @@
#define CME_SCOM_EINR 0x1001202a
#define CME_SCOM_SISR 0x1001202b
#define CME_SCOM_ICRR 0x1001202c
-#define CME_SCOM_XIXCR 0x10012030
-#define CME_SCOM_XIRAMRA 0x10012031
-#define CME_SCOM_XIRAMGA 0x10012032
-#define CME_SCOM_XIRAMDBG 0x10012033
-#define CME_SCOM_XIRAMEDR 0x10012034
-#define CME_SCOM_XIDBGPRO 0x10012035
-#define CME_SCOM_XISIB 0x10012036
-#define CME_SCOM_XIMEM 0x10012037
-#define CME_SCOM_CMEXISGB 0x10012038
-#define CME_SCOM_XIICAC 0x10012039
-#define CME_SCOM_XIPCBQ0 0x1001203a
-#define CME_SCOM_XIPCBQ1 0x1001203b
-#define CME_SCOM_XIPCBMD0 0x1001203c
-#define CME_SCOM_XIPCBMD1 0x1001203d
-#define CME_SCOM_XIPCBMI0 0x1001203e
-#define CME_SCOM_XIPCBMI1 0x1001203f
+#define CME_SCOM_XIXCR 0x10012010
+#define CME_SCOM_XIRAMRA 0x10012011
+#define CME_SCOM_XIRAMGA 0x10012012
+#define CME_SCOM_XIRAMDBG 0x10012013
+#define CME_SCOM_XIRAMEDR 0x10012014
+#define CME_SCOM_XIDBGPRO 0x10012015
+#define CME_SCOM_XISIB 0x10012016
+#define CME_SCOM_XIMEM 0x10012017
+#define CME_SCOM_CMEXISGB 0x10012018
+#define CME_SCOM_XIICAC 0x10012019
+#define CME_SCOM_XIPCBQ0 0x1001201a
+#define CME_SCOM_XIPCBQ1 0x1001201b
+#define CME_SCOM_XIPCBMD0 0x1001201c
+#define CME_SCOM_XIPCBMD1 0x1001201d
+#define CME_SCOM_XIPCBMI0 0x1001201e
+#define CME_SCOM_XIPCBMI1 0x1001201f
#define CME_SCOM_PMSRS0 0x10012040
#define CME_SCOM_PMSRS1 0x10012041
#define CME_SCOM_PMCRS0 0x10012042
@@ -134,6 +134,8 @@
#define CME_LCL_AFSR 0xc0000160
#define CME_LCL_AFTR 0xc0000180
#define CME_LCL_LMCR 0xc00001a0
+#define CME_LCL_LMCR_OR 0xc00001b0
+#define CME_LCL_LMCR_CLR 0xc00001b8
#define CME_LCL_BCECSR 0xc00001f0
#define CME_LCL_PMSRS0 0xc0000200
#define CME_LCL_PMSRS1 0xc0000220
diff --git a/import/chips/p9/common/pmlib/include/registers/ppm_firmware_registers.h b/import/chips/p9/common/pmlib/include/registers/ppm_firmware_registers.h
index 902f36fc..0c287b93 100644
--- a/import/chips/p9/common/pmlib/include/registers/ppm_firmware_registers.h
+++ b/import/chips/p9/common/pmlib/include/registers/ppm_firmware_registers.h
@@ -345,8 +345,8 @@ typedef union ppm_sshsrc
{
#ifdef _BIG_ENDIAN
uint64_t stop_gated : 1;
- uint64_t stop_transition : 2;
uint64_t special_wkup_done : 1;
+ uint64_t stop_transition : 2;
uint64_t req_stop_level : 4;
uint64_t act_stop_level : 4;
uint64_t req_write_enable : 1;
@@ -358,8 +358,8 @@ typedef union ppm_sshsrc
uint64_t req_write_enable : 1;
uint64_t act_stop_level : 4;
uint64_t req_stop_level : 4;
- uint64_t special_wkup_done : 1;
uint64_t stop_transition : 2;
+ uint64_t special_wkup_done : 1;
uint64_t stop_gated : 1;
#endif // _BIG_ENDIAN
} fields;
diff --git a/import/chips/p9/procedures/ppe/pk/gpe/gpe_common.h b/import/chips/p9/procedures/ppe/pk/gpe/gpe_common.h
index 9e982663..07a7cc7c 100644
--- a/import/chips/p9/procedures/ppe/pk/gpe/gpe_common.h
+++ b/import/chips/p9/procedures/ppe/pk/gpe/gpe_common.h
@@ -49,8 +49,10 @@
/// Each GPE instance has it's own interrupt status register these macros
/// are added for convenience in accessing the correct register
-#define GPE_GISR0(instance_id) (OCB_G0ISR0 + (instance_id * 8))
-#define GPE_GISR1(instance_id) (OCB_G0ISR1 + (instance_id * 8))
+#ifndef UNIFIED_IRQ_HANDLER_GPE
+ #define GPE_GISR0(instance_id) (OCB_G0ISR0 + (instance_id * 8))
+ #define GPE_GISR1(instance_id) (OCB_G0ISR1 + (instance_id * 8))
+#endif
#ifdef __ASSEMBLER__
// *INDENT-OFF*
@@ -63,16 +65,28 @@
///
/// r1, r2, r3, and r13 must not be modified. All other registers may be used.
///
+/// The pk_unified_irq_prty_mask_handler routine MUST return the task priority
+/// interrupt vector in d5.
+///
.macro hwmacro_get_ext_irq
+#ifdef UNIFIED_IRQ_HANDLER_GPE
+ // Unified approach.
+ _liw r5, pk_unified_irq_prty_mask_handler
+ mtlr r5
+ blrl // On return, d5 contains task prty irq vec.
+#else
_lwzi %r5, %r5, GPE_GISR0(APPCFG_OCC_INSTANCE_ID)
+#endif
cntlzw %r4, %r5
cmpwible %r4, 31, call_external_irq_handler #branch if irq is lt or eq to 31
## No IRQ pending in interrupt set 0. Try set 1.
## Note: irq # will be 64 (EXTERNAL_IRQS) if no bits were set in either register
+#ifndef UNIFIED_IRQ_HANDLER_GPE
_lwzi %r6, %r6, GPE_GISR1(APPCFG_OCC_INSTANCE_ID)
+#endif
cntlzw %r4, %r6
addi %r4, %r4, 32
@@ -85,6 +99,7 @@
.macro .hwmacro_irq_cfg_bitmaps
.occhw_irq_cfg_bitmaps
.endm
+
// *INDENT-ON*
#endif /* __ASSEMBLER__ */
diff --git a/import/chips/p9/procedures/ppe/pk/gpe/gpe_irq.h b/import/chips/p9/procedures/ppe/pk/gpe/gpe_irq.h
index ad590bf7..4e6a652f 100644
--- a/import/chips/p9/procedures/ppe/pk/gpe/gpe_irq.h
+++ b/import/chips/p9/procedures/ppe/pk/gpe/gpe_irq.h
@@ -63,6 +63,31 @@ pk_irq_enable(PkIrqId irq)
}
+/// Enable a vector of interrupts by clearing the mask bits.
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_vec_enable(uint64_t irq_vec_mask)
+{
+ out32(OCB_OIMR0_CLR, (uint32_t)(irq_vec_mask >> 32));
+ out32(OCB_OIMR1_CLR, (uint32_t)irq_vec_mask);
+}
+
+
+/// Restore a vector of interrupts by overwriting OIMR.
+
+/*
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_vec_restore( PkMachineContext *context, uint64_t irq_vec_mask)
+{
+ pk_critical_section_enter(context);
+ out64( OCB_OIMR, irq_vec_mask);
+ pk_critical_section_exit(context);
+}
+*/
+
+
/// Disable an interrupt by setting the mask bit.
UNLESS__PPE42_IRQ_CORE_C__(extern)
@@ -73,6 +98,17 @@ pk_irq_disable(PkIrqId irq)
}
+/// Disable a vector of interrupts by setting the mask bits.
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_vec_disable(uint64_t irq_vec_mask)
+{
+ out32(OCB_OIMR0_OR, (uint32_t)(irq_vec_mask >> 32));
+ out32(OCB_OIMR1_OR, (uint32_t)irq_vec_mask);
+}
+
+
/// Clear interrupt status with an CLR mask. Only meaningful for
/// edge-triggered interrupts.
@@ -84,6 +120,18 @@ pk_irq_status_clear(PkIrqId irq)
}
+/// Clear a vector of interrupts status with an CLR mask. Only meaningful for
+/// edge-triggered interrupts.
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_vec_status_clear(uint64_t irq_vec_mask)
+{
+ out32(OCB_OISR0_CLR, (uint32_t)(irq_vec_mask >> 32));
+ out32(OCB_OISR1_CLR, (uint32_t)irq_vec_mask);
+}
+
+
/// Get IRQ status as a 0 or non-0 integer
UNLESS__PPE42_IRQ_CORE_C__(extern)
diff --git a/import/chips/p9/procedures/ppe/pk/std/std_common.h b/import/chips/p9/procedures/ppe/pk/std/std_common.h
index db43ad3c..b9f330bc 100644
--- a/import/chips/p9/procedures/ppe/pk/std/std_common.h
+++ b/import/chips/p9/procedures/ppe/pk/std/std_common.h
@@ -54,9 +54,19 @@
///
/// r1, r2, r3, and r13 must not be modified. All other registers may be used.
///
+/// The pk_unified_irq_prty_mask_handler routine MUST return the task priority
+/// interrupt vector in d5.
+///
.macro hwmacro_get_ext_irq
+#ifdef UNIFIED_IRQ_HANDLER_CME
+ // Unified approach.
+ _liw r5, pk_unified_irq_prty_mask_handler
+ mtlr r5
+ blrl // On return, d5 contains task prty irq vec.
+#else
_lvdg d5, STD_LCL_EISTR #load the 64bit interrupt status into d5
+#endif
cntlzw r4, r5
cmpwible r4, 31, call_external_irq_handler #branch if irq is lt or eq to 31
diff --git a/import/chips/p9/procedures/ppe/pk/std/std_irq.h b/import/chips/p9/procedures/ppe/pk/std/std_irq.h
index cde5ce6e..146653ff 100644
--- a/import/chips/p9/procedures/ppe/pk/std/std_irq.h
+++ b/import/chips/p9/procedures/ppe/pk/std/std_irq.h
@@ -59,6 +59,14 @@ pk_irq_enable(PkIrqId irq)
out64(STD_LCL_EIMR_CLR, STD_IRQ_MASK64(irq));
}
+/// Enable a vector of interrupts by clearing the mask bits.
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_vec_enable(uint64_t irq_vec_mask)
+{
+ out64(STD_LCL_EIMR_CLR, irq_vec_mask);
+}
/// Disable an interrupt by setting the mask bit.
@@ -69,6 +77,15 @@ pk_irq_disable(PkIrqId irq)
out64(STD_LCL_EIMR_OR, STD_IRQ_MASK64(irq));
}
+/// Disable a vector of interrupts by setting the mask bits.
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_vec_disable(uint64_t irq_vec_mask)
+{
+ out64(STD_LCL_EIMR_OR, irq_vec_mask);
+}
+
/// Clear interrupt status with an CLR mask. Only meaningful for
/// edge-triggered interrupts.
@@ -81,6 +98,16 @@ pk_irq_status_clear(PkIrqId irq)
}
+/// Clear a vector of interrupts status with an CLR mask. Only meaningful for
+/// edge-triggered interrupts.
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_vec_status_clear(uint64_t irq_vec_mask)
+{
+ out64(STD_LCL_EISR_CLR, irq_vec_mask);
+}
+
/// Get IRQ status as a 0 or non-0 integer
UNLESS__PPE42_IRQ_CORE_C__(extern)
diff --git a/import/chips/p9/procedures/ppe_closed/cme/link.cmd b/import/chips/p9/procedures/ppe_closed/cme/link.cmd
new file mode 100644
index 00000000..10436196
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/link.cmd
@@ -0,0 +1,121 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/link.cmd $ */
+/* */
+/* 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 */
+
+// Need to do this so that elf32-powerpc is not modified!
+#undef powerpc
+
+#ifndef INITIAL_STACK_SIZE
+#define INITIAL_STACK_SIZE 256
+#endif
+
+OUTPUT_FORMAT(elf32-powerpc);
+
+#define SRAM_START 0xffff8000
+#define SRAM_LENGTH 0x8000
+#define PPE_DEBUG_PTRS_OFFSET 0x180
+
+MEMORY
+{
+ sram : ORIGIN = SRAM_START, LENGTH = SRAM_LENGTH
+}
+
+// This symbol is only needed by external debug tools, so add this command
+// to ensure that table is pulled in by the linker even though PPE code
+// never references it.
+EXTERN(pk_debug_ptrs);
+
+SECTIONS
+{
+ . = SRAM_START;
+
+ . = ALIGN(512);
+
+ _VECTOR_START = .;
+
+ .vectors _VECTOR_START : { *(.vectors) } > sram
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Debug Pointers Table
+ //
+ // We want the debug pointers table to always appear at
+ // PPE_DEBUG_PTRS_OFFSET from the IVPR address.
+ ///////////////////////////////////////////////////////////////////////////
+
+ _DEBUG_PTRS_START = _VECTOR_START + PPE_DEBUG_PTRS_OFFSET;
+ .debug_ptrs _DEBUG_PTRS_START : { *(.debug_ptrs) } > sram
+
+ ////////////////////////////////
+ // All non-vector code goes here
+ ////////////////////////////////
+ .text : { *(.text) } > sram
+
+ ////////////////////////////////
+ // Read-only Data
+ ////////////////////////////////
+
+ . = ALIGN(8);
+ _RODATA_SECTION_BASE = .;
+
+ // SDA2 constant sections .sdata2 and .sbss2 must be adjacent to each
+ // other. Our SDATA sections are small so we'll use strictly positive
+ // offsets.
+
+ _SDA2_BASE_ = .;
+ .sdata2 . : { *(.sdata2*) } > sram
+ .sbss2 . : { *(.sbss2*) } > sram
+
+ // Other read-only data.
+
+ .rodata . : { *(.rodata*) *(.got2) } > sram
+
+ _RODATA_SECTION_SIZE = . - _RODATA_SECTION_BASE;
+
+ ////////////////////////////////
+ // Read-write Data
+ ////////////////////////////////
+
+ . = ALIGN(8);
+ _DATA_SECTION_BASE = .;
+
+ // SDA sections .sdata and .sbss must be adjacent to each
+ // other. Our SDATA sections are small so we'll use strictly positive
+ // offsets.
+
+ _SDA_BASE_ = .;
+ .sdata . : { *(.sdata*) } > sram
+ .sbss . : { *(.sbss*) } > sram
+
+ // Other read-write data
+ // It's not clear why boot.S is generating empty .glink,.iplt
+
+ .rela . : { *(.rela*) } > sram
+ .rwdata . : { *(.data*) *(.bss*) } > sram
+// .iplt . : { *(.iplt) } > sram
+
+ _PK_INITIAL_STACK_LIMIT = .;
+ . = . + INITIAL_STACK_SIZE;
+ _PK_INITIAL_STACK = . - 1;
+
+}
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
new file mode 100644
index 00000000..92512c7e
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.c
@@ -0,0 +1,183 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/p9_cme_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 cme_irq_common.c
+/// \brief Shared and global file for CME H-codes.
+/// \owner Michael Olsen Email: cmolsen@us.ibm.com
+/// \owner David Du Email: daviddu@us.ibm.com
+///
+
+#include "pk.h"
+#include "p9_cme_irq.h"
+
+//-------------------------------------------------------------------//
+// DO NOT modify this file unless you're the owner //
+//-------------------------------------------------------------------//
+
+// Notes:
+// The following two lists,
+// ext_irq_vectors_cme[][] 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_cme[][] table.
+
+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_PRTY5_CME |
+ //IRQ_VEC_PRTY4_CME |
+ IRQ_VEC_PRTY3_CME |
+ IRQ_VEC_PRTY2_CME |
+ IRQ_VEC_PRTY1_CME |
+ IRQ_VEC_PRTY0_CME
+ },
+ {
+ IRQ_VEC_PRTY1_CME,
+ IRQ_VEC_PRTY6_CME | /* 1: IDX_PRTY_LVL_BCE_DB3 */
+ IRQ_VEC_PRTY5_CME |
+ //IRQ_VEC_PRTY4_CME |
+ IRQ_VEC_PRTY3_CME |
+ IRQ_VEC_PRTY2_CME |
+ IRQ_VEC_PRTY1_CME
+ },
+ {
+ IRQ_VEC_PRTY2_CME,
+ IRQ_VEC_PRTY6_CME | /* 2: IDX_PRTY_LVL_WAKE_DB2 */
+ IRQ_VEC_PRTY5_CME |
+ //IRQ_VEC_PRTY4_CME |
+ IRQ_VEC_PRTY3_CME |
+ IRQ_VEC_PRTY2_CME
+ },
+ {
+ IRQ_VEC_PRTY3_CME,
+ IRQ_VEC_PRTY6_CME | /* 3: IDX_PRTY_LVL_STOP */
+ 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_PRTY5_CME //|
+ //IRQ_VEC_PRTY4_CME
+ },
+ {
+ IRQ_VEC_PRTY5_CME,
+ IRQ_VEC_PRTY6_CME | /* 5: IDX_PRTY_LVL_PMCR_DB0 */
+ IRQ_VEC_PRTY5_CME
+ },
+ {
+ IRQ_VEC_PRTY6_CME,
+ IRQ_VEC_PRTY6_CME /* 6: IDX_PRTY_LVL_DISABLED */
+ }
+};
+
+uint8_t g_current_prty_level = NUM_EXT_IRQ_PRTY_LEVELS - 1;
+uint8_t g_eimr_stack[NUM_EXT_IRQ_PRTY_LEVELS];
+int g_eimr_stack_ctr = -1;
+uint64_t g_eimr_override_stack[NUM_EXT_IRQ_PRTY_LEVELS];
+uint64_t g_eimr_override = 0x0000000000000000;
+
+// 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 = in64(STD_LCL_EISTR);
+ bFound = FALSE;
+ iPrtyLvl = 0;
+
+ do
+ {
+ if (ext_irq_vectors_cme[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 EIMR 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_eimr_stack_ctr < NUM_EXT_IRQ_PRTY_LEVELS)
+ {
+ // Make a note of present prty level and
+ // then update tracker to new prty level.
+ g_eimr_stack[g_eimr_stack_ctr] = g_current_prty_level;
+ g_current_prty_level = iPrtyLvl; // Update prty level tracker.
+ g_eimr_override_stack[g_eimr_stack_ctr] = g_eimr_override;
+ }
+ else
+ {
+ MY_TRACE_ERR("Code bug: EIMR S/R stack counter=%d >= max=%d.",
+ g_eimr_stack_ctr, NUM_EXT_IRQ_PRTY_LEVELS);
+ pk_halt();
+ }
+
+ // 3. Write the new mask for this priority level.
+ out64(STD_LCL_EIMR, ext_irq_vectors_cme[iPrtyLvl][IDX_MASK_VEC] |
+ g_eimr_override);
+
+ }
+ else
+ {
+ MY_TRACE_ERR("A disabled IRQ fired");
+ MY_TRACE_ERR("ext_irq_vector_pk=0x%08x%08x", ext_irq_vector_pk);
+#if !EPM_P9_TUNING
+ pk_halt();
+#endif
+ }
+
+
+ // 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");
+
+ l_vecL = 0;
+ asm volatile ("lvd %[data], 0(%[addr]) \n" \
+ : [data]"=r"(l_vecH) \
+ : [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
new file mode 100644
index 00000000..e811e1d6
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_irq.h
@@ -0,0 +1,136 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/p9_cme_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. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file p9_cme_irq_common.h
+/// \brief Shared and global definitions for CME H-codes.
+/// \owner Michael Olsen Email: cmolsen@us.ibm.com
+/// \owner David Du Email: daviddu@us.ibm.com
+
+//-------------------------------------------------------------------//
+// 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)_CME(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 cme_irq_common.c
+
+// 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
+
+// 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)
+extern const uint64_t ext_irq_vectors_cme[NUM_EXT_IRQ_PRTY_LEVELS][2];
+
+// Group0: Non-task hi-prty IRQs
+#define IRQ_VEC_PRTY0_CME (uint64_t)(0xFE00000000000000)
+// Group1: DB3 + BCE
+#define IRQ_VEC_PRTY1_CME (uint64_t)(0x00F0000000000000)
+// Group2: DB2 + WAKEUP
+#define IRQ_VEC_PRTY2_CME (uint64_t)(0x000FF00000000000)
+// Group3: STOP
+#define IRQ_VEC_PRTY3_CME (uint64_t)(0x00000C0000000000)
+// 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)(0x010003FFC33FFFFF)
+
+// This should be 0xFFFFFFFFFFFFFFFF
+#define IRQ_VEC_PRTY_CHECK ( IRQ_VEC_PRTY0_CME | \
+ IRQ_VEC_PRTY1_CME | \
+ IRQ_VEC_PRTY2_CME | \
+ IRQ_VEC_PRTY3_CME | \
+ IRQ_VEC_PRTY4_CME | \
+ IRQ_VEC_PRTY5_CME | \
+ IRQ_VEC_PRTY6_CME )
+
+extern uint8_t g_current_prty_level;
+extern uint8_t g_eimr_stack[NUM_EXT_IRQ_PRTY_LEVELS];
+extern int g_eimr_stack_ctr;
+extern uint64_t g_eimr_override_stack[NUM_EXT_IRQ_PRTY_LEVELS];
+extern uint64_t g_eimr_override;
+
+/// Restore a vector of interrupts by overwriting EIMR.
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_vec_restore(PkMachineContext* context)
+{
+ pk_critical_section_enter(context);
+
+ 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);
+ // 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
+ {
+ PK_TRACE("Code bug: Messed up EIMR book keeping: g_eimr_stack_ctr=%d",
+ g_eimr_stack_ctr);
+ pk_halt();
+ }
+
+ pk_critical_section_exit(context);
+}
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
new file mode 100644
index 00000000..77333c2e
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/p9_cme_main.c
@@ -0,0 +1,229 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/p9_cme_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_cme_irq.h"
+
+// CME Pstate Header and Structure
+#include "p9_cme_pstate.h"
+
+// CME Stop Header and Structure
+#include "p9_cme_stop.h"
+CmeStopRecord G_cme_stop_record = {0};
+
+// CME Interrupt Handler Table
+EXTERNAL_IRQ_TABLE_START
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DEBUGGER
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DEBUG_TRIGGER
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_QUAD_CHECKSTOP
+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_DEFAULT //CMEHW_IRQ_BCE_BUSY_HIGH
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_BCE_TIMEOUT
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL3_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL3_C1
+IRQ_HANDLER(p9_cme_stop_event_handler, (void*) & (G_cme_stop_record.sem[1]))
+//CMEHW_IRQ_PC_INTR_PENDING_C0
+IRQ_HANDLER(p9_cme_stop_event_handler, (void*) & (G_cme_stop_record.sem[1]))
+//CMEHW_IRQ_PC_INTR_PENDING_C1
+IRQ_HANDLER(p9_cme_stop_event_handler, (void*) & (G_cme_stop_record.sem[1]))
+//CMEHW_IRQ_REG_WAKEUP_C0
+IRQ_HANDLER(p9_cme_stop_event_handler, (void*) & (G_cme_stop_record.sem[1]))
+//CMEHW_IRQ_REG_WAKEUP_C1
+IRQ_HANDLER(p9_cme_stop_event_handler, (void*) & (G_cme_stop_record.sem[1]))
+//CMEHW_IRQ_SPECIAL_WAKEUP_C0
+IRQ_HANDLER(p9_cme_stop_event_handler, (void*) & (G_cme_stop_record.sem[1]))
+//CMEHW_IRQ_SPECIAL_WAKEUP_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL2_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL2_C1
+IRQ_HANDLER(p9_cme_stop_event_handler, (void*) & (G_cme_stop_record.sem[0]))
+//CMEHW_IRQ_PC_PM_STATE_ACTIVE_C0
+IRQ_HANDLER(p9_cme_stop_event_handler, (void*) & (G_cme_stop_record.sem[0]))
+//CMEHW_IRQ_PC_PM_STATE_ACTIVE_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_L2_PURGE_DONE
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_NCU_PURGE_DONE
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_CHTM_PURGE_DONE_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_CHTM_PURGE_DONE_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_BCE_BUSY_LOW
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_FINAL_VDM_DATA0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_FINAL_VDM_DATA1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_COMM_RECVD
+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_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
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PECE_INTR_DISABLED_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_44
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_45
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_46
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_47
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_48
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_49
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_50
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_51
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_52
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_53
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_54
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_55
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_56
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_57
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_58
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_59
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_60
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_61
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_62
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_63
+EXTERNAL_IRQ_TABLE_END
+
+#define KERNEL_STACK_SIZE 256
+#define THREAD_STACK_SIZE 256
+
+#define CME_THREAD_PRIORITY_STOP_EXIT 1
+#define CME_THREAD_PRIORITY_STOP_ENTRY 2
+#define CME_THREAD_PRIORITY_PSTATE_PMCR 3
+
+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];
+
+PkThread G_p9_cme_stop_enter_thread;
+PkThread G_p9_cme_stop_exit_thread;
+PkThread G_p9_cme_pmcr_db0_thread;
+
+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);
+
+ PK_TRACE("Kernel init completed");
+
+ // Unified interrupt handler checks
+ if (IDX_PRTY_LVL_DISABLED != (NUM_EXT_IRQ_PRTY_LEVELS - 1))
+ {
+ MY_TRACE_ERR("Code bug: IDX_PRTY_LVL_DISABLED(=%d)!=NUM_EXT_IRQ_PRTY_LEVELS(=%d)-1",
+ IDX_PRTY_LVL_DISABLED, NUM_EXT_IRQ_PRTY_LEVELS);
+ pk_halt();
+ }
+
+ if (IRQ_VEC_PRTY_CHECK != 0xFFFFFFFFFFFFFFFF)
+ {
+ MY_TRACE_ERR("Code bug: IRQ_VEC_PRTY_CHECK=0x%08x%08x should be all ones",
+ IRQ_VEC_PRTY_CHECK);
+ pk_halt();
+ }
+
+ //CMO-Temporary setting
+ // Setup up CME_LCL_FLAGS to indicate whether
+ // this CME is QMGR master or slave.
+ // Rules:
+ // - If even CME then set FLAGS(3)=1. Otherwise =0.
+ // - Whether in CME or Simics or HW,
+ // the assumption here is that the even CME in
+ // a configured Quad is always configured.
+ uint32_t l_pir;
+ asm volatile ("mfpir %[data] \n" : [data]"=r"(l_pir) );
+
+ if ( l_pir & PIR_INSTANCE_EVEN_ODD_MASK )
+ {
+ // Odd: Set slave status
+ out32(CME_LCL_FLAGS_CLR, CME_FLAGS_QMGR_MASTER);
+ }
+ else
+ {
+ // Even: Set master status
+ out32(CME_LCL_FLAGS_OR, CME_FLAGS_QMGR_MASTER);
+ }
+
+ // 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,
+ (void*)NULL,
+ (PkAddress)G_p9_cme_stop_exit_thread_stack,
+ (size_t)THREAD_STACK_SIZE,
+ (PkThreadPriority)CME_THREAD_PRIORITY_STOP_EXIT);
+
+ PK_TRACE_BIN("G_p9_cme_stop_exit_thread",
+ &G_p9_cme_stop_exit_thread,
+ sizeof(G_p9_cme_stop_exit_thread));
+
+ // Initialize the thread control block for G_p9_cme_stop_enter_thread
+ pk_thread_create(&G_p9_cme_stop_enter_thread,
+ (PkThreadRoutine)p9_cme_stop_enter_thread,
+ (void*)NULL,
+ (PkAddress)G_p9_cme_stop_enter_thread_stack,
+ (size_t)THREAD_STACK_SIZE,
+ (PkThreadPriority)CME_THREAD_PRIORITY_STOP_ENTRY);
+
+ PK_TRACE_BIN("G_p9_cme_stop_enter_thread",
+ &G_p9_cme_stop_enter_thread,
+ 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,
+ (void*)NULL,
+ (PkAddress)G_p9_cme_pmcr_db0_thread_stack,
+ (size_t)THREAD_STACK_SIZE,
+ (PkThreadPriority)IDX_PRTY_LVL_PMCR_DB0);
+
+ PK_TRACE_BIN("G_p9_cme_pmcr_db0_thread",
+ &G_p9_cme_pmcr_db0_thread,
+ sizeof(G_p9_cme_pmcr_db0_thread));
+
+ // Make G_p9_cme_stop_exit_thread runnable
+ pk_thread_resume(&G_p9_cme_stop_exit_thread);
+
+ // Make G_p9_cme_stop_enter_thread runnable
+ 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_TRACE("Launching threads");
+
+ // Start running the highest priority thread.
+ // This function never returns
+ pk_start_threads();
+
+ return 0;
+}
diff --git a/import/chips/p9/procedures/ppe_closed/cme/pk_app_cfg.h b/import/chips/p9/procedures/ppe_closed/cme/pk_app_cfg.h
new file mode 100644
index 00000000..0bb06884
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/pk_app_cfg.h
@@ -0,0 +1,85 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/pk_app_cfg.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 */
+#ifndef __PK_APP_CFG_H__
+#define __PK_APP_CFG_H__
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pk_app_cfg.h
+/// \brief Application specific overrides go here.
+///
+
+#define EPM_P9_LEVEL 1
+#define STOP_PRIME 0
+#define SKIP_ABORT 0
+#define SKIP_L2_PURGE_ABORT 0
+#define SKIP_ENTRY_CATCHUP 0
+#define SKIP_EXIT_CATCHUP 1
+#define SKIP_SCAN0 0
+#define SKIP_INITF 0
+#define SKIP_ARY_INIT 0
+#define SKIP_SELF_RESTORE 0
+
+// --------------------
+
+#define EPM_P9_TUNING 1
+#define SIMICS_TUNING 1
+#define DEV_DEBUG 1
+#define USE_SIMICS_IO 0
+#define PK_TRACE_TIMER_OUTPUT 0
+
+// --------------------
+
+// Force CME and GPE tasks to use the unified interrupt handler.
+#define UNIFIED_IRQ_HANDLER_CME
+
+// 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 */
+
+// --------------------
+
+/// This file provides architecture-specific symbol names for each interrupt
+#include "cmehw_interrupts.h"
+
+/// This application will statically initialize it's external interrupt table
+/// using the table defined in pk_app_irq_table.c.
+#define STATIC_IRQ_TABLE
+
+#endif /*__PK_APP_CFG_H__*/
diff --git a/import/chips/p9/procedures/ppe_closed/cme/pk_app_irq_table.c b/import/chips/p9/procedures/ppe_closed/cme/pk_app_irq_table.c
new file mode 100644
index 00000000..8710a91a
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/pk_app_irq_table.c
@@ -0,0 +1,92 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/pk_app_irq_table.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"
+
+EXTERNAL_IRQ_TABLE_START
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DEBUGGER
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DEBUG_TRIGGER
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_QUAD_CHECKSTOP
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_3
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_OCC_HEARTBEAT_LOST
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_CORE_CHECKSTOP
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_BCE_BUSY_HIGH
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_7
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL3_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL3_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PC_INTR_PENDING_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PC_INTR_PENDING_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_REG_WAKEUP_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_REG_WAKEUP_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPECIAL_WAKEUP_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPECIAL_WAKEUP_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_16
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_17
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL2_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL2_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PC_PM_STATE_ACTIVE_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PC_PM_STATE_ACTIVE_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_L2_PURGE_DONE
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_NCU_PURGE_DONE
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_CHTM_PURGE_DONE_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_CHTM_PURGE_DONE_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_BCE_BUSY_LOW
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_27
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_SPARE_28
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_COMM_RECVD
+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_DEFAULT //CMEHW_IRQ_DOORBELL1_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_DOORBELL1_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PECE_INTR_DISABLED_C0
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_PECE_INTR_DISABLED_C1
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_44
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_45
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_46
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_47
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_48
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_49
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_50
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_51
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_52
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_53
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_54
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_55
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_56
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_57
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_58
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_59
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_60
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_61
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_62
+IRQ_HANDLER_DEFAULT //CMEHW_IRQ_RESERVED_63
+EXTERNAL_IRQ_TABLE_END
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
new file mode 100644
index 00000000..ed33dfa9
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.c
@@ -0,0 +1,750 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.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 pstate_cme.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.
+///
+///
+
+#include "pk.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 "qppm_firmware_registers.h"
+#include "ppe42_scom.h"
+#include "p9_cme_irq.h"
+#include "p9_cme_pstate.h"
+
+//
+// HOMER variables updated by PGPE
+//
+uint32_t ULTRA_TURBO_FREQ_STEPS_PS;
+
+#define PIG_PAYLOAD_MASK 0x0fff000000000000
+#define PIG_INTR_FIELD_MASK 0x7000000000000000
+#define PIG_INTR_GRANTED_MASK 0x0000000080000000
+
+// Type1 specific defines
+#define PIG_PAYLOAD_PSTATE_MASK 0x03ff000000000000
+#define PIG_PAYLOAD_PSTATE_SEQ_INCR 0x0400000000000000 // Seq increment value
+
+
+int
+register_qcme_with_pgpe(void);
+
+
+void
+unified_irq_task_handler(void* arg, PkIrqId irq)
+{
+ pk_semaphore_post((PkSemaphore*)arg);
+}
+
+
+void
+unified_irq_nontask_handler(void* arg, PkIrqId irq)
+{
+ MY_TRACE_ERR("Got an non-task IRQ=%d", irq);
+ pk_halt();
+}
+
+
+int
+send_pig_packet(uint32_t addr, uint64_t data)
+{
+ int rc = 0;
+ uint64_t data_tmp;
+
+ // First make sure no interrupt request is currently granted
+ do
+ {
+ // 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();
+ }
+ }
+ while (((ppm_pig_t)data_tmp).fields.intr_granted);
+
+ // Send PIG packet
+ rc = putscom(0, addr, data);
+
+ if (rc)
+ {
+ MY_TRACE_ERR("putscom(addr=0x%08x) failed w/rc=0x%08x", addr, rc);
+ pk_halt();
+ }
+
+ return rc;
+}
+
+
+void
+pmcr_db0_thread(void* arg)
+{
+ int rc = 0, rc_api = API_RC_SUCCESS;
+ uint8_t bDB0 = FALSE, bPMCR = FALSE;
+ 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 );
+
+ 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 );
+
+ if (rc)
+ {
+ PK_TRACE("pk_irq_handler_set(%d) failed w/rc=0x%08x", irqPrty, rc);
+ pk_halt();
+ }
+ }
+
+ }
+
+
+ //
+ // 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);
+
+
+ //------------------------------------------------------------------------------//
+ // Determine QMGR status and register as QMGR, ie QCME, if CME is QMGR master //
+ //------------------------------------------------------------------------------//
+
+ // First determine if this CME is a QMRG master, i.e. QCME
+ //
+ bQcmeRegister = FALSE;
+
+ asm volatile ("mfpir %[data] \n" : [data]"=r"(l_pir) );
+
+ thisCmeInstance = (uint8_t)(l_pir & PIR_INSTANCE_NUM_MASK);
+
+ rc = getscom( 0, CME_LCL_FLAGS, &data );
+ data32 = (uint32_t)(data >> 32);
+
+ 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 ( l_pir & PIR_INSTANCE_EVEN_ODD_MASK ) // Sanity test that bit31==1 and thus this CME is odd.
+ {
+ bQcmeRegister = FALSE;
+ MY_TRACE_DBG("This [odd] CME#%d is the QMGR slave", thisCmeInstance);
+ }
+ 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();
+ }
+ }
+
+ // 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)
+ {
+ // 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();
+ }
+
+ // Update the unacked registration tracker
+ if (!fsm_unacked_qcme_registration)
+ {
+ fsm_unacked_qcme_registration++;
+ }
+ else
+ {
+ MY_TRACE_ERR("Code bug: fsm_unacked_qcme_registration (=%d) > 0",
+ fsm_unacked_qcme_registration);
+ pk_halt();
+ }
+ }
+
+
+ //
+ // 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);
+
+
+ while(1)
+ {
+
+ // Go to sleep
+ pk_semaphore_pend(&sem, PK_WAIT_FOREVER);
+
+
+ //
+ // 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.
+ //
+
+ do
+ {
+ bDB0 = bPMCR = FALSE;
+
+ statusIrqDb0C0 = pk_irq_status_get(CMEHW_IRQ_DOORBELL0_C0);
+ statusIrqDb0C1 = pk_irq_status_get(CMEHW_IRQ_DOORBELL0_C1);
+
+ if (statusIrqDb0C0 && statusIrqDb0C1)
+ {
+ // Both fired (We do NOT support this.)
+ PK_TRACE("Code bug: Both DB0s fired. Probably PGPE problem.");
+ pk_halt();
+ }
+ else if (statusIrqDb0C0)
+ {
+ 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;
+ }
+ else if (statusIrqDb0C1)
+ {
+ 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;
+ }
+ else
+ {
+ statusIrqPmcrC0 = pk_irq_status_get(CMEHW_IRQ_PMCR_UPDATE_C0);
+ statusIrqPmcrC1 = pk_irq_status_get(CMEHW_IRQ_PMCR_UPDATE_C1);
+
+ if (statusIrqPmcrC0 && statusIrqPmcrC1)
+ {
+ // Both fired (We support this.)
+ thisCoreIdx = nextCoreIdx;
+ nextCoreIdx++;
+ nextCoreIdx = nextCoreIdx - (nextCoreIdx >> 1) * 2;
+
+ if (thisCoreIdx != 0 && thisCoreIdx != 1)
+ {
+ PK_TRACE("Code bug: Illegal value of thisCoreIdx (=%d).", thisCoreIdx);
+ pk_halt();
+ }
+ }
+ 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;
+ }
+ }
+ }
+ 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);
+
+ // Get the payload from DB0
+ rc = getscom(0, addr_db0, &cb_from_pgpe_base.value);
+
+ if (rc)
+ {
+ 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();
+ }
+
+//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)
+ {
+
+ 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();
+ }
+
+#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;
+
+ //
+ // 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;
+
+ // 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);
+
+ if (rc)
+ {
+ MY_TRACE_ERR("send_pig_packet(addr=0x%08x) failed w/rc=0x%08x", addr_ppm_pig, rc);
+ pk_halt();
+ }
+
+ //
+ // 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();
+ }
+
+#if DEV_DEBUG
+ // Read PPMPIG status
+ rc = getscom(0, addr_ppm_pig, &data);
+
+ if (rc)
+ {
+ PK_TRACE("getscom(addr_ppm_pig%d=0x%08x) failed w/rc=0x%08x",
+ thisCoreIdx, addr_ppm_pig, rc);
+ pk_halt();
+ }
+
+ PK_TRACE("(After PIG phase 2): data_ppm_pig%d=0x%08x%08x",
+ thisCoreIdx, (uint32_t)(data >> 32), (uint32_t)data);
+#endif
+
+ }
+ else
+ {
+ PK_TRACE("Code bug.");
+ PK_TRACE("Neither of the {PMCR,DB0}_C0/1 interrupts were selected.");
+ pk_halt();
+ }
+
+
+ // 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);
+ */
+
+ }
+}
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
new file mode 100644
index 00000000..ef8daeed
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.h
@@ -0,0 +1,347 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_pstate.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. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pstate.h
+/// \brief Shared and global definitions for pstate H codes.
+/// \owner Michael Olsen Email: cmolsen@us.ibm.com
+///
+
+void pmcr_db0_thread(void*);
+
+#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)
+
+#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
+{
+ 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;
+
+// QCME->PGPE: cb_to_pgpe_ack
+// ---------------------------
+// Used by QCME to acknowledge DB requests.
+//
+typedef union comm_block_to_pgpe_ack
+{
+ 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;
+
+//
+// Return Codes
+//
+enum API_RETURN_CODES
+{
+ API_RC_INVALID = 0, // Don't use zero. Not reliable.
+ API_RC_SUCCESS = 1,
+ API_RC_FAILURE = 2
+};
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop.h b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop.h
index 6d8636dc..2378fbed 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop.h
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop.h
@@ -44,45 +44,54 @@
#include "cppm_firmware_registers.h"
#include "p9_stop_common.h"
-
+/*
+/// Compiler flags
+#define EPM_P9_LEVEL 1
+#define SKIP_ABORT 1
+#define SKIP_L2_PURGE_ABORT 1
+#define SKIP_CATCHUP 1
+#define STOP_PRIME 0
+#define SKIP_SCAN0 0
+#define SKIP_INITF 0
+#define SKIP_ARY_INIT 0
+#define SKIP_SELF_RESTORE 0
+*/
/// handcoded addresses TO BE REMOVED
-#define THREAD_INFO 0x20010A9B
-#define DIRECT_CONTROLS 0x20010A9C
-#define RAS_STATUS 0x20010A02
-#define RAM_MODEREG 0x20010A51
-#define RAM_CTRL 0x20010A52
-#define RAM_STATUS 0x20010A53
-
-#define C_SYNC_CONFIG 0x20030000
-#define C_OPCG_ALIGN 0x20030001
-#define C_SCAN_REGION_TYPE 0x20030005
-#define C_CLK_REGION 0x20030006
-#define C_CLOCK_STAT_SL 0x20030008
-#define C_CLOCK_STAT_NSL 0x20030009
-#define C_CLOCK_STAT_ARY 0x2003000a
-#define C_BIST 0x2003000B
-
-#define C_SLAVE_CONFIG_REG 0x200F001E
-#define C_ERROR_REG 0x200F001F
-#define C_HANG_PULSE_1_REG 0x200F0021
-#define C_PPM_CGCR 0x200F0164
-
-#define C_CPLT_CTRL0_OR 0x20000010
-#define C_CPLT_CTRL0_CLEAR 0x20000020
-#define C_CPLT_CTRL1_OR 0x20000011
-#define C_CPLT_CTRL1_CLEAR 0x20000021
-#define C_CPLT_STAT0 0x20000100
-
-#define PERV_CPLT_CTRL0_OR 0x00000010
-#define PERV_CPLT_CTRL0_CLEAR 0x00000020
-#define PERV_OPCG_REG0 0x00030002
-#define PERV_OPCG_REG1 0x00030003
-#define PERV_CLK_REGION 0x00030006
-#define PERV_BIST 0x0003000B
-#define PERV_CPLT_STAT0 0x00000100
-
-#define NCU_STATUS_REG 0x1001140F
+#define THREAD_INFO 0x20010A9B
+#define DIRECT_CONTROLS 0x20010A9C
+#define RAS_STATUS 0x20010A02
+#define RAM_MODEREG 0x20010A51
+#define RAM_CTRL 0x20010A52
+#define RAM_STATUS 0x20010A53
+
+#define C_SYNC_CONFIG 0x20030000
+#define C_OPCG_ALIGN 0x20030001
+#define C_SCAN_REGION_TYPE 0x20030005
+#define C_CLK_REGION 0x20030006
+#define C_CLOCK_STAT_SL 0x20030008
+#define C_CLOCK_STAT_NSL 0x20030009
+#define C_CLOCK_STAT_ARY 0x2003000a
+#define C_BIST 0x2003000B
+
+#define C_SLAVE_CONFIG_REG 0x200F001E
+#define C_ERROR_REG 0x200F001F
+#define C_HANG_PULSE_1_REG 0x200F0021
+#define C_PPM_CGCR 0x200F0164
+
+#define C_CPLT_CTRL0_OR 0x20000010
+#define C_CPLT_CTRL0_CLEAR 0x20000020
+#define C_CPLT_CTRL1_OR 0x20000011
+#define C_CPLT_CTRL1_CLEAR 0x20000021
+#define C_CPLT_STAT0 0x20000100
+
+#define PERV_CPLT_CTRL0_OR 0x00000010
+#define PERV_CPLT_CTRL0_CLEAR 0x00000020
+#define PERV_OPCG_REG0 0x00030002
+#define PERV_OPCG_REG1 0x00030003
+#define PERV_CLK_REGION 0x00030006
+#define PERV_BIST 0x0003000B
+#define PERV_CPLT_STAT0 0x00000100
/// Macro to update STOP History
#define CME_STOP_UPDATE_HISTORY(core,gated,trans,req_l,act_l,req_e,act_e) \
@@ -94,18 +103,15 @@
hist.fields.act_write_enable = act_e; \
CME_PUTSCOM(PPM_SSHSRC, core, hist.value);
-
+#define IRQ_VEC_WAKE_C0 (uint64_t)(0x000A800000000000)
+#define IRQ_VEC_WAKE_C1 (uint64_t)(0x0005400000000000)
+#define IRQ_VEC_STOP_C0 (uint64_t)(0x0000080000000000)
+#define IRQ_VEC_STOP_C1 (uint64_t)(0x0000040000000000)
/// CME STOP Return Codes
enum CME_STOP_RETURN_CODE
{
- CME_STOP_SUCCESS = 0,
- CME_STOP_ENTRY_PM_NOT_ACTIVE = 0x00726301,
- CME_STOP_ENTRY_STOP1_SENT_IRQ = 0x00726302,
- CME_STOP_ENTRY_VDD_PFET_NOT_IDLE = 0x00726303,
- CME_STOP_EXIT_NO_WAKEUP = 0x00726304,
- CME_STOP_EXIT_WAKEUP_FROM_STOP1 = 0x00726305,
- CME_STOP_EXIT_PCBMUX_LOST_GRANT = 0x00726306
+ CME_STOP_SUCCESS = 0
};
/// CME STOP IRQs with shorter names
@@ -136,13 +142,23 @@ enum CME_STOP_FLAGS
/// Stop Score Board Structure
typedef struct
{
- uint8_t req_stop_c0;
- uint8_t req_stop_c1;
- uint8_t act_stop_c0;
- uint8_t act_stop_c1;
- uint8_t active_core;
- uint8_t cme_flags;
- uint64_t mask_vector;
+ // requested stop levels are read from pm_state,
+ // need to be a global state for stop8 detection
+ uint8_t req_level_c0;
+ uint8_t req_level_c1;
+ // actual stop levels are changed through entry,
+ // need to be a global state for aborting entry
+ uint8_t act_level_c0;
+ uint8_t act_level_c1;
+ // whether core is in running state,
+ // need to be a global state for aborted entry detection and wakeup masking
+ uint32_t core_running;
+ // core stop handoff to sgpe from cme
+ // need to be a global state for wakeup and pm_active masking
+ uint32_t core_stopgpe;
+ // partial good configuration,
+ // todo: consider partial good changed during stop,
+ uint32_t core_enabled;
PkSemaphore sem[2];
} CmeStopRecord;
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_enter_marks.h b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_enter_marks.h
index deb1a86f..6e411ccd 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_enter_marks.h
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_enter_marks.h
@@ -37,22 +37,26 @@ namespace CME_STOP_ENTRY_MARKS
enum CME_SE_MARKS
{
SE_POLL_PCBMUX_GRANT = 0x0,
- SE_STOP_CORE_CLKS = 0x8,
- SE_DROP_CLK_SYNC = 0x10,
- SE_STOP2_DONE = 0x18,
- SE_IS0_BEGIN = 0x20,
- SE_IS0_END = 0x28,
- SE_CORE_VMIN = 0x30,
- SE_STOP3_DONE = 0x38,
- SE_POWER_OFF_CORE = 0x40,
- SE_STOP4_DONE = 0x48,
- SE_IS1_BEGIN = 0x50,
- SE_IS1_END = 0x68,
- SE_PURGE_L2 = 0xe0,
- SE_IS2_BEGIN = 0xe8,
- SE_IS2_END = 0xf0,
- SE_L2_PURGE_DONE = 0xf8,
- SE_SGPE_HANDOFF = 0x100,
+ SE_QUIESCE_CORE_INTF = 0x8,
+ SE_STOP_CORE_CLKS = 0x10,
+ SE_STOP_CORE_GRID = 0x18,
+ SE_STOP2_DONE = 0x20,
+ SE_IS0_BEGIN = 0x28,
+ SE_IS0_END = 0x30,
+ SE_CATCHUP = 0x38,
+ SE_CORE_VMIN = 0x40,
+ SE_STOP3_DONE = 0x48,
+ SE_POWER_OFF_CORE = 0x50,
+ SE_STOP4_DONE = 0x68,
+ SE_IS1_BEGIN = 0xe0,
+ SE_IS1_END = 0xe8,
+ SE_PURGE_L2 = 0xf0,
+ SE_IS2_BEGIN = 0xf8,
+ SE_PURGE_L2_ABORT = 0x100,
+ SE_PURGE_L2_ABORT_DONE = 0x108,
+ SE_IS2_END = 0x110,
+ SE_PURGE_L2_DONE = 0x118,
+ SE_SGPE_HANDOFF = 0x120,
BEGINSCOPE_STOP_ENTRY = 0x1f08,
ENDSCOPE_STOP_ENTRY = 0x1f10,
STOP_EVENT_HANDLER = 0x1f18,
@@ -65,11 +69,13 @@ enum CME_SE_MARKS
const std::vector<CME_SE_MARKS> MARKS =
{
SE_POLL_PCBMUX_GRANT,
+ SE_QUIESCE_CORE_INTF,
SE_STOP_CORE_CLKS,
- SE_DROP_CLK_SYNC,
+ SE_STOP_CORE_GRID,
SE_STOP2_DONE,
SE_IS0_BEGIN,
SE_IS0_END,
+ SE_CATCHUP,
SE_CORE_VMIN,
SE_STOP3_DONE,
SE_POWER_OFF_CORE,
@@ -78,8 +84,10 @@ const std::vector<CME_SE_MARKS> MARKS =
SE_IS1_END,
SE_PURGE_L2,
SE_IS2_BEGIN,
+ SE_PURGE_L2_ABORT,
+ SE_PURGE_L2_ABORT_DONE,
SE_IS2_END,
- SE_L2_PURGE_DONE,
+ SE_PURGE_L2_DONE,
SE_SGPE_HANDOFF,
BEGINSCOPE_STOP_ENTRY,
ENDSCOPE_STOP_ENTRY,
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c
index a41a8edf..a82af15c 100755
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_entry.c
@@ -53,16 +53,19 @@ p9_cme_stop_entry()
{
int rc = 0;
- uint8_t core_aborted = 0;
- uint8_t core_catchup = 0;
- uint8_t catchup_ongoing = 0;
- uint8_t entry_ongoing = 1;
+ int catchup_ongoing = 0;
+ int entry_ongoing = 1;
uint8_t target_level;
uint8_t deeper_level = 0;
+ uint8_t origin_level = 0;
+ uint32_t origin_core = 0;
uint32_t deeper_core = 0;
+ uint32_t core_aborted = 0;
+ uint32_t core_catchup = 0;
uint32_t core;
uint32_t loop;
uint32_t pm_states;
+ uint32_t lclr_data;
uint64_t scom_data;
ppm_sshsrc_t hist;
ppm_pig_t pig;
@@ -77,15 +80,19 @@ p9_cme_stop_entry()
// CME will do Daul-cast to both cores at the same time in entry flow.
core = (in32(CME_LCL_EISR) & BITS32(20, 2)) >> SHIFT32(21);
- // override with partial good core mask
- core = core & G_cme_stop_record.cme_flags & CME_MASK_BC;
+ // filter with partial good and running core mask
+ // core cannot enter stop if core is already stopped
+ core = core & G_cme_stop_record.core_enabled &
+ G_cme_stop_record.core_running;
- PK_TRACE("SE0: Core Select[%d]", core);
+ PK_TRACE("SE0: Core Select[%d] Enabled[%d] Running[%d]",
+ core, G_cme_stop_record.core_enabled,
+ G_cme_stop_record.core_running);
// Return error if None of both fired
if (!core)
{
- return CME_STOP_ENTRY_PM_NOT_ACTIVE;
+ pk_halt();
}
//===================================
@@ -95,57 +102,64 @@ p9_cme_stop_entry()
do // while(0) loop for stop flow control
{
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 1 (should be done by hardware)
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// Read SISR for pm_state_cX
pm_states = in32_sh(CME_LCL_SISR);
- G_cme_stop_record.req_stop_c0 = (pm_states & BITS32(4, 4)) >> SHIFT32(7);
- G_cme_stop_record.req_stop_c1 = (pm_states & BITS32(8, 4)) >> SHIFT32(11);
-
- // pm_active AND waken_up : pm_state = sisr (new state)
- // pm_active AND !waken_up : pm_state = sisr (only with auto promote)
- // !pm_active AND waken_up : pm_state = 0 (out dated state)
- // !pm_active AND !waken_up : pm_state = sisr (current state)
- if (~core & G_cme_stop_record.active_core & CME_MASK_C0)
+
+ // entry: req_level = target stop level
+ // act_level = current stop level
+ // running = FALSE, TRUE if aborted
+ // stopped: req_level = act_level = target and current stop level
+ // (if<=5)
+ // running = FALSE
+ // exit/abort: req_level = requested stop level
+ // act_level = latest stop level
+ // running = FALSE
+ // running: req_level = act_level = 0
+ // running = TRUE
+ // pm_active AND running : req_level = New requested stop level
+ // pm_active AND !running : req_level = Not possible,
+ // ignore false re-entry
+ // !pm_active AND running : req_level = 0 by exit,
+ // not changing req_level
+ // !pm_active AND !running : req_level = Current req_level
+ if (core & CME_MASK_C0)
{
- G_cme_stop_record.req_stop_c0 = 0;
+ G_cme_stop_record.req_level_c0 =
+ (pm_states & BITS32(4, 4)) >> SHIFT32(7);
}
- if (~core & G_cme_stop_record.active_core & CME_MASK_C1)
+ if (core & CME_MASK_C1)
{
- G_cme_stop_record.req_stop_c1 = 0;
+ G_cme_stop_record.req_level_c1 =
+ (pm_states & BITS32(8, 4)) >> SHIFT32(11);
}
- G_cme_stop_record.active_core &= ~core;
+ G_cme_stop_record.core_running &= ~core;
+ out32(CME_LCL_LMCR_OR, (core << SHIFT32(15)));
PK_TRACE("SE1: Request Stop Levels[%d %d]",
- G_cme_stop_record.req_stop_c0, G_cme_stop_record.req_stop_c1);
+ G_cme_stop_record.req_level_c0,
+ G_cme_stop_record.req_level_c1);
// Return error if target STOP level == 1(Nap)
- if((core == CME_MASK_C0 && G_cme_stop_record.req_stop_c0 <= STOP_LEVEL_1) ||
- (core == CME_MASK_C1 && G_cme_stop_record.req_stop_c1 <= STOP_LEVEL_1) ||
- (core == CME_MASK_BC && (G_cme_stop_record.req_stop_c0 <= STOP_LEVEL_1 ||
- G_cme_stop_record.req_stop_c1 <= STOP_LEVEL_1)))
+ if((core == CME_MASK_C0 &&
+ G_cme_stop_record.req_level_c0 <= STOP_LEVEL_1) ||
+ (core == CME_MASK_C1 &&
+ G_cme_stop_record.req_level_c1 <= STOP_LEVEL_1) ||
+ (core == CME_MASK_BC &&
+ (G_cme_stop_record.req_level_c0 <= STOP_LEVEL_1 ||
+ G_cme_stop_record.req_level_c1 <= STOP_LEVEL_1)))
{
- return CME_STOP_ENTRY_STOP1_SENT_IRQ;
+ pk_halt();
}
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 2
- //--------------------------------------------------------------------------
-
- PK_TRACE("SE2.a");
- // Disable fired Stop and corresponding Wakeup interrupts
- out32(CME_LCL_EIMR_OR, (CME_MASK_BC << SHIFT32(21)) |
- (core << SHIFT32(13)) |
- (core << SHIFT32(15)) |
- (core << SHIFT32(17)));
-
- PK_TRACE("SE2.b");
- // Also clear the status of the currently fired STOP interrupt(s)
- out32(CME_LCL_EISR_CLR, core << SHIFT32(21));
+ //----------------------------------------------------------------------
PK_TRACE("SE2.c");
// Request PCB Mux
@@ -156,29 +170,29 @@ p9_cme_stop_entry()
CME_PUTSCOM(CPPM_CPMMR_OR, core, BIT64(0));
// set target_level from pm_state for both cores or just one core
- target_level = (core == CME_MASK_C0) ? G_cme_stop_record.req_stop_c0 :
- G_cme_stop_record.req_stop_c1;
+ target_level = (core == CME_MASK_C0) ? G_cme_stop_record.req_level_c0 :
+ G_cme_stop_record.req_level_c1;
// If both cores are going into STOP but targeting different levels,
if ((core == CME_MASK_BC) &&
- (G_cme_stop_record.req_stop_c0 != G_cme_stop_record.req_stop_c1))
+ (G_cme_stop_record.req_level_c0 != G_cme_stop_record.req_level_c1))
{
// set target_level to the lighter level targeted by one core
// set deeper_level to the deeper level targeted by deeper core
- deeper_level = G_cme_stop_record.req_stop_c0;
+ deeper_level = G_cme_stop_record.req_level_c0;
deeper_core = CME_MASK_C0;
- if (G_cme_stop_record.req_stop_c0 < G_cme_stop_record.req_stop_c1)
+ if (G_cme_stop_record.req_level_c0 < G_cme_stop_record.req_level_c1)
{
- target_level = G_cme_stop_record.req_stop_c0;
- deeper_level = G_cme_stop_record.req_stop_c1;
+ target_level = G_cme_stop_record.req_level_c0;
+ deeper_level = G_cme_stop_record.req_level_c1;
deeper_core = CME_MASK_C1;
}
}
PK_TRACE("SE2.e");
// Update STOP History: In Transition of Entry
- // Set req_stop_level to target_level of either both or just one core
+ // Set req_level_level to target_level of either both or just one core
CME_STOP_UPDATE_HISTORY(core,
STOP_CORE_READY_RUN,
STOP_TRANS_ENTRY,
@@ -187,7 +201,7 @@ p9_cme_stop_entry()
STOP_REQ_ENABLE,
STOP_ACT_DISABLE);
- // Set req_stop_level to deeper_level for deeper core
+ // Set req_level_level to deeper_level for deeper core
if (deeper_core)
{
CME_STOP_UPDATE_HISTORY(deeper_core,
@@ -214,27 +228,39 @@ p9_cme_stop_entry()
PK_TRACE("SE2: PCB Mux Granted");
- //==========================
- MARK_TRAP(SE_STOP_CORE_CLKS)
- //==========================
+ //=============================
+ MARK_TRAP(SE_QUIESCE_CORE_INTF)
+ //=============================
PK_TRACE("SE2.g");
// Acknowledge the STOP Entry to PC with a pulse
- out32(CME_LCL_SICR_OR, core << SHIFT32(1));
+ out32(CME_LCL_SICR_OR, core << SHIFT32(1));
out32(CME_LCL_SICR_CLR, core << SHIFT32(1));
+ /// @todo Set LMCR bits 14 and/or 15 (override disables)
+
PK_TRACE("SE2.h");
// Raise Core-L2 + Core-CC Quiesces
out32(CME_LCL_SICR_OR, (core << SHIFT32(7)) | (core << SHIFT32(9)));
PK_TRACE("SE2.i");
+
+ do
+ {
+ lclr_data = in32(CME_LCL_SISR);
+ }
+ while((lclr_data & core) != core);
+
// Waits quiesce done for at least 512 core cycles
// MF: verify generate FCB otherwise math is wrong.
PPE_WAIT_CORE_CYCLES(loop, 512)
+ //==========================
+ MARK_TRAP(SE_STOP_CORE_CLKS)
+ //==========================
+
PK_TRACE("SE2.j");
// Raise Core Chiplet Fence
- CME_PUTSCOM(C_CPLT_CTRL0_OR, core, BIT64(2));
CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(18));
PK_TRACE("SE2.k");
@@ -243,7 +269,7 @@ p9_cme_stop_entry()
PK_TRACE("SE2.l");
// Stop Core Clocks
- CME_PUTSCOM(C_CLK_REGION, core, 0x9FFC00000000E000);
+ CME_PUTSCOM(C_CLK_REGION, core, 0x8FFC00000000E000);
PK_TRACE("SE2.m");
@@ -259,15 +285,14 @@ p9_cme_stop_entry()
PK_TRACE("SE2: Core Clock Stopped");
- //=========================
- MARK_TRAP(SE_DROP_CLK_SYNC)
- //=========================
+ //==============================
+ MARK_TRAP(SE_STOP_CORE_GRID)
+ //==============================
PK_TRACE("SE2.n");
// Drop clock sync enable before switch to refclk
CME_PUTSCOM(CPPM_CACCR_CLR, core, BIT64(15));
-#if !EPM_P9_TUNING
PK_TRACE("SE2.o");
// Poll for clock sync done to drop
@@ -277,24 +302,43 @@ p9_cme_stop_entry()
}
while(scom_data & BIT64(13));
-#endif
-
PK_TRACE("SE2.p");
// Switch glsmux to refclk to save clock grid power
CME_PUTSCOM(C_PPM_CGCR, core, 0);
- // Assert PCB Fence
- //CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(25));
// Assert Vital Fence
CME_PUTSCOM(C_CPLT_CTRL1_OR, core, BIT64(3));
// Assert Regional Fences
CME_PUTSCOM(C_CPLT_CTRL1_OR, core, 0xFFFF700000000000);
+ PK_TRACE("SE2: Clock Sync Dropped");
+
+ // Copy PECE CME sample to PPM Shadow
+ if (core & CME_MASK_C0)
+ {
+ scom_data = in64(CME_LCL_PECESR0);
+ CME_PUTSCOM(CPPM_PECES, core, scom_data);
+ G_cme_stop_record.act_level_c0 = STOP_LEVEL_2;
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ scom_data = in64(CME_LCL_PECESR1);
+ CME_PUTSCOM(CPPM_PECES, core, scom_data);
+ G_cme_stop_record.act_level_c1 = STOP_LEVEL_2;
+ }
+
+ //===========================
+ MARK_TAG(SE_STOP2_DONE, core)
+ //===========================
+
PK_TRACE("SE2.q");
// Update Stop History: In Core Stop Level 2
// Check if STOP level 2 reaches the target for both or one core
entry_ongoing =
- target_level == STOP_LEVEL_2 ? STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
+ target_level == STOP_LEVEL_2 ?
+ STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
+
CME_STOP_UPDATE_HISTORY(core,
STOP_CORE_IS_GATED,
entry_ongoing,
@@ -323,27 +367,11 @@ p9_cme_stop_entry()
entry_ongoing = 1;
}
- if (core & CME_MASK_C0)
- {
- G_cme_stop_record.act_stop_c0 = STOP_LEVEL_2;
- }
-
- if (core & CME_MASK_C1)
- {
- G_cme_stop_record.act_stop_c1 = STOP_LEVEL_2;
- }
-
- PK_TRACE("SE2: Clock Sync Dropped");
-
- //===========================
- MARK_TAG(SE_STOP2_DONE, core)
- //===========================
-
//===========================
MARK_TRAP(SE_IS0_BEGIN)
//===========================
#if !SKIP_ABORT
- out32(CME_LCL_EIMR_CLR, /*TODO(core << SHIFT32(13)) |*/
+ out32(CME_LCL_EIMR_CLR, (core << SHIFT32(13)) |
(core << SHIFT32(15)) |
(core << SHIFT32(17)));
sync();
@@ -355,36 +383,19 @@ p9_cme_stop_entry()
MARK_TRAP(SE_IS0_END)
//===================
- core_aborted = 0;
+ core_aborted = core & G_cme_stop_record.core_running;
- if ((core & CME_MASK_C0) &&
- G_cme_stop_record.act_stop_c0 == STOP_LEVEL_0 &&
- G_cme_stop_record.req_stop_c0 != STOP_LEVEL_0)
+ if (core_aborted && deeper_core)
{
- core_aborted |= CME_MASK_C0;
- core -= CME_MASK_C0;
- deeper_core = 0;
-
- if (deeper_core == CME_MASK_C1)
+ if (core_aborted != deeper_core)
{
target_level = deeper_level;
}
+ deeper_core = 0;
}
- if ((core & CME_MASK_C1) &&
- G_cme_stop_record.act_stop_c1 == STOP_LEVEL_0 &&
- G_cme_stop_record.req_stop_c1 != STOP_LEVEL_0)
- {
- core_aborted |= CME_MASK_C1;
- core -= CME_MASK_C1;
- deeper_core = 0;
-
- if (deeper_core == CME_MASK_C0)
- {
- target_level = deeper_level;
- }
- }
+ core = core & ~G_cme_stop_record.core_running;
if (!core)
{
@@ -393,22 +404,68 @@ p9_cme_stop_entry()
break;
}
+#if !SKIP_ENTRY_CATCHUP
+
if (catchup_ongoing)
{
- core = CME_MASK_BC;
+ // Y = 2 eo = 0 same if X = 2
+ // Y > 2 eo = 1 c=c t=t same if X = 2
+ // if X > 2 eo = 1
+ // if Y = 2 c=o t=o
+ // else (Y > 2) c=2
+ // if X != Y (X = Y: dl=0 dc=0 t=t)
+ // dl=o dc=o (X > Y)
+ // if X < Y
+ // dl=t dc=c t=o
+ if (origin_level > STOP_LEVEL_2)
+ {
+ if (target_level == STOP_LEVEL_2)
+ {
+ core = origin_core;
+ target_level = origin_level;
+ }
+ else
+ {
+ if (origin_level != target_level)
+ {
+ deeper_core = origin_core;
+ deeper_level = origin_level;
+
+ if (origin_level < target_level)
+ {
+ deeper_core = core;
+ deeper_level = target_level;
+ target_level = origin_level;
+ }
+ }
+
+ core = CME_MASK_BC;
+ }
+
+ entry_ongoing = 1;
+ }
+
break;
}
-#if !SKIP_CATCHUP
core_catchup = (in32(CME_LCL_EISR) & BITS32(20, 2)) >> SHIFT32(21);
-#endif
+ core_catchup = core_catchup & G_cme_stop_record.core_enabled &
+ G_cme_stop_record.core_running;
- if (core_catchup > core)
+ if (core_catchup)
{
- core = core_catchup - core;
+ origin_core = core;
+ origin_level = target_level;
+ core = core_catchup;
catchup_ongoing = 1;
+
+ //========================
+ MARK_TAG(SE_CATCHUP, core)
+ //========================
}
+#endif
+
}
while(catchup_ongoing);
@@ -425,9 +482,9 @@ p9_cme_stop_entry()
target_level[%d],deeper_level[%d]",
core, deeper_core, target_level, deeper_level);
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 3
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
if (target_level == 3)
{
@@ -442,6 +499,20 @@ p9_cme_stop_entry()
PK_TRACE("SE3.b");
// Drop to Vmin
+ if(core & CME_MASK_C0)
+ {
+ G_cme_stop_record.act_level_c0 = STOP_LEVEL_3;
+ }
+
+ if(core & CME_MASK_C1)
+ {
+ G_cme_stop_record.act_level_c1 = STOP_LEVEL_3;
+ }
+
+ //===========================
+ MARK_TAG(SE_STOP3_DONE, core)
+ //===========================
+
PK_TRACE("SE3.c");
// Update Stop History: In Core Stop Level 3
CME_STOP_UPDATE_HISTORY(core,
@@ -476,20 +547,6 @@ p9_cme_stop_entry()
entry_ongoing = 0;
}
- if(core & CME_MASK_C0)
- {
- G_cme_stop_record.act_stop_c0 = STOP_LEVEL_3;
- }
-
- if(core & CME_MASK_C1)
- {
- G_cme_stop_record.act_stop_c1 = STOP_LEVEL_3;
- }
-
- //===========================
- MARK_TAG(SE_STOP3_DONE, core)
- //===========================
-
// If we are done at STOP level 3
if (!entry_ongoing)
{
@@ -497,9 +554,9 @@ p9_cme_stop_entry()
}
}
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 4
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
//===============================
MARK_TAG(SE_POWER_OFF_CORE, core)
@@ -512,18 +569,6 @@ p9_cme_stop_entry()
CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(16));
#if !STOP_PRIME
-#if !EPM_P9_TUNING
- // Make sure we are not forcing PFET for VDD off
- // vdd_pfet_force_state == 00 (Nop)
- PK_TRACE("SE4.b");
- CME_GETSCOM(PPM_PFCS, core, CME_SCOM_AND, scom_data);
-
- if (scom_data & BITS64(0, 2))
- {
- return CME_STOP_ENTRY_VDD_PFET_NOT_IDLE;
- }
-
-#endif
// Prepare PFET Controls
// vdd_pfet_val/sel_override = 0 (disbaled)
@@ -545,23 +590,29 @@ p9_cme_stop_entry()
}
while(!(scom_data & BIT64(42)));
-#if !EPM_P9_TUNING
- // Optional: Poll for vdd_pg_sel being: 0x8
- PK_TRACE("SE4.f");
-
- do
- {
- CME_GETSCOM(PPM_PFCS, core, CME_SCOM_AND, scom_data);
- }
- while(!(scom_data & BIT64(46)));
-
-#endif
// Turn Off Force Voff
// vdd_pfet_force_state = 00 (Nop)
PK_TRACE("SE4.g");
CME_PUTSCOM(PPM_PFCS_CLR, core, BITS64(0, 2));
+
#endif
+ PK_TRACE("SE4: Core Powered Off");
+
+ if (core & CME_MASK_C0)
+ {
+ G_cme_stop_record.act_level_c0 = STOP_LEVEL_4;
+ }
+
+ if (core & CME_MASK_C1)
+ {
+ G_cme_stop_record.act_level_c1 = STOP_LEVEL_4;
+ }
+
+ //===========================
+ MARK_TAG(SE_STOP4_DONE, core)
+ //===========================
+
PK_TRACE("SE4.h");
// Update Stop History: In Core Stop Level 4
// Check if STOP level 4 reaches the target for both or one core
@@ -596,27 +647,11 @@ p9_cme_stop_entry()
entry_ongoing = 1;
}
- if (core & CME_MASK_C0)
- {
- G_cme_stop_record.act_stop_c0 = STOP_LEVEL_4;
- }
-
- if (core & CME_MASK_C1)
- {
- G_cme_stop_record.act_stop_c1 = STOP_LEVEL_4;
- }
-
- PK_TRACE("SE4: Core Powered Off");
-
- //===========================
- MARK_TAG(SE_STOP4_DONE, core)
- //===========================
-
//===========================
MARK_TRAP(SE_IS1_BEGIN)
//===========================
#if !SKIP_ABORT
- out32(CME_LCL_EIMR_CLR, /*TODO(core << SHIFT32(13)) |*/
+ out32(CME_LCL_EIMR_CLR, (core << SHIFT32(13)) |
(core << SHIFT32(15)) |
(core << SHIFT32(17)));
sync();
@@ -628,39 +663,25 @@ p9_cme_stop_entry()
MARK_TRAP(SE_IS1_END)
//===================
- if ((core & CME_MASK_C0) &&
- G_cme_stop_record.act_stop_c0 == STOP_LEVEL_0 &&
- G_cme_stop_record.req_stop_c0 != STOP_LEVEL_0)
- {
- core_aborted |= CME_MASK_C0;
- core -= CME_MASK_C0;
- deeper_core = 0;
+ core_aborted = core & G_cme_stop_record.core_running;
- if (deeper_core == CME_MASK_C1)
+ if (core_aborted && deeper_core)
+ {
+ if (core_aborted != deeper_core)
{
target_level = deeper_level;
}
+ deeper_core = 0;
}
- if ((core & CME_MASK_C1) &&
- G_cme_stop_record.act_stop_c1 == STOP_LEVEL_0 &&
- G_cme_stop_record.req_stop_c1 != STOP_LEVEL_0)
- {
- core_aborted |= CME_MASK_C1;
- core -= CME_MASK_C1;
- deeper_core = 0;
-
- if (deeper_core == CME_MASK_C0)
- {
- target_level = deeper_level;
- }
- }
+ core = core & ~G_cme_stop_record.core_running;
if (!core)
{
core |= core_aborted;
entry_ongoing = 0;
+ break;
}
// If we are done at STOP level 4 or aborted
@@ -673,16 +694,16 @@ p9_cme_stop_entry()
target_level[%d],deeper_level[%d]",
core, deeper_core, target_level, deeper_level);
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// STOP LEVEL 5 (preparsion of STOP LEVEL 8 and above)
- //--------------------------------------------------------------------------
+ //----------------------------------------------------------------------
// block all wake up before purge L2,
// this is last chance either core can exit
- out32(CME_LCL_EIMR_OR, BITS32(12, 6));
+ //out32(CME_LCL_EIMR_OR, BITS32(12, 6));
- if ((G_cme_stop_record.req_stop_c0 >= STOP_LEVEL_8) &&
- (G_cme_stop_record.req_stop_c1 >= STOP_LEVEL_8))
+ if ((G_cme_stop_record.req_level_c0 >= STOP_LEVEL_8) &&
+ (G_cme_stop_record.req_level_c1 >= STOP_LEVEL_8))
{
//=========================
@@ -698,16 +719,21 @@ p9_cme_stop_entry()
// Poll for Purged Done
PK_TRACE("SE5.1b");
+
//===========================
MARK_TRAP(SE_IS2_BEGIN)
-
//===========================
+
do
{
#if !SKIP_L2_PURGE_ABORT
if(in32(CME_LCL_EINR) & BITS32(12, 6))
{
+
+ //===============================
+ MARK_TAG(SE_PURGE_L2_ABORT, core)
+ //===============================
// abort L2+NCU purges
out32(CME_LCL_SICR_OR, BIT32(19) | BIT32(23));
}
@@ -726,9 +752,9 @@ p9_cme_stop_entry()
PK_TRACE("SE5.1: L2/NCU/CHTM Purged");
- //=========================
- MARK_TRAP(SE_L2_PURGE_DONE)
- //=========================
+ //==============================
+ MARK_TAG(SE_PURGE_L2_DONE, core)
+ //==============================
}
//=============================
@@ -745,30 +771,24 @@ p9_cme_stop_entry()
STOP_REQ_DISABLE,
STOP_ACT_ENABLE);
- if (core & CME_MASK_C0)
- {
- G_cme_stop_record.act_stop_c0 = STOP_LEVEL_5;
- }
-
- if (core & CME_MASK_C1)
- {
- G_cme_stop_record.act_stop_c1 = STOP_LEVEL_5;
- }
-
// Send PCB Interrupt per core
PK_TRACE("SE5.2b");
pig.fields.req_intr_type = 2; //0b010: STOP State Change
if (core & CME_MASK_C0)
{
- pig.fields.req_intr_payload = G_cme_stop_record.req_stop_c0;
+ pig.fields.req_intr_payload = G_cme_stop_record.req_level_c0;
CME_PUTSCOM(PPM_PIG, CME_MASK_C0, pig.value);
+ G_cme_stop_record.core_stopgpe |= core;
+ G_cme_stop_record.act_level_c0 = STOP_LEVEL_5;
}
if (core & CME_MASK_C1)
{
- pig.fields.req_intr_payload = G_cme_stop_record.req_stop_c1;
+ pig.fields.req_intr_payload = G_cme_stop_record.req_level_c1;
CME_PUTSCOM(PPM_PIG, CME_MASK_C1, pig.value);
+ G_cme_stop_record.core_stopgpe |= core;
+ G_cme_stop_record.act_level_c1 = STOP_LEVEL_5;
}
// Change PPM Wakeup to STOPGPE
@@ -787,21 +807,6 @@ p9_cme_stop_entry()
// Release PPM Write Protection
CME_PUTSCOM(CPPM_CPMMR_CLR, core, BIT64(0));
- // Enable Wakeup Interrupts of this entry core if no handoff to SGPE
- // Otherwise enable Doorbell interrupts of this entry core
- out32(CME_LCL_EIMR_CLR,
- ((~core & G_cme_stop_record.active_core & CME_MASK_BC) << SHIFT32(21)));
-
- if (!entry_ongoing)
- out32(CME_LCL_EIMR_CLR,
- /*TODO((core & ~core_aborted & CME_MASK_BC) << SHIFT32(13)) |*/
- ((core & ~core_aborted & CME_MASK_BC) << SHIFT32(15)) |
- ((core & ~core_aborted & CME_MASK_BC) << SHIFT32(17)));
- else
- {
- out32_sh(CME_LCL_EIMR_CLR, (core << SHIFT32((41 - 32))));
- }
-
//============================
MARK_TRAP(ENDSCOPE_STOP_ENTRY)
//============================
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c
index c86574ac..af473ea4 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit.c
@@ -31,19 +31,21 @@ extern CmeStopRecord G_cme_stop_record;
int
p9_cme_stop_exit()
{
- int rc = 0;
- uint8_t d2u4_flag = 0;
+ int rc = 0;
+ int d2u4_flag = 0;
+ int catchup_ongoing = 0;
uint8_t target_level;
- uint8_t deeper_level = 0;
- uint32_t deeper_core = 0;
+ uint8_t deeper_level = 0;
+ uint32_t deeper_core = 0;
uint32_t wakeup;
+ uint32_t pcwu;
+ uint32_t spwu;
+ uint32_t rgwu;
uint32_t core;
-#if !SKIP_CATCHUP
- uint8_t core_catchup;
+#if !SKIP_EXIT_CATCHUP
+ uint32_t core_catchup;
#endif
- uint8_t catchup_ongoing = 0;
- uint8_t pcwu, spwu, rgwu;
- //uint8_t grant;
+ //uint32_t grant;
ppm_sshsrc_t hist;
//--------------------------------------------------------------------------
@@ -60,8 +62,8 @@ p9_cme_stop_exit()
rgwu = (wakeup >> 0) & CME_MASK_BC;
core = pcwu | spwu | rgwu;
- // mask wake up interrupts
- out32(CME_LCL_EIMR_OR, BITS32(12, 6));
+ // override with partial good core mask
+ core = core & G_cme_stop_record.core_enabled;
PK_TRACE("X0: Core Select[%d], pcwu[%d], spwu[%d], rgwu[%d]",
core, pcwu, spwu, rgwu);
@@ -69,7 +71,7 @@ p9_cme_stop_exit()
// Code Error: function should never be entered without wakeup source active
if (!core)
{
- return CME_STOP_EXIT_NO_WAKEUP;
+ pk_halt();
}
//==================================
@@ -77,42 +79,42 @@ p9_cme_stop_exit()
//==================================
PK_TRACE("X0: Actual Stop Levels[%d %d]",
- G_cme_stop_record.act_stop_c0, G_cme_stop_record.act_stop_c1);
+ G_cme_stop_record.act_level_c0, G_cme_stop_record.act_level_c1);
// Code Error: by default stop 1 auto wakeup should be enabled
- if ((core == CME_MASK_C0 && G_cme_stop_record.act_stop_c0 < 2) ||
- (core == CME_MASK_C1 && G_cme_stop_record.act_stop_c1 < 2) ||
- (core == CME_MASK_BC && (G_cme_stop_record.act_stop_c0 < 2 ||
- G_cme_stop_record.act_stop_c1 < 2)))
+ if ((core == CME_MASK_C0 && G_cme_stop_record.act_level_c0 < 2) ||
+ (core == CME_MASK_C1 && G_cme_stop_record.act_level_c1 < 2) ||
+ (core == CME_MASK_BC && (G_cme_stop_record.act_level_c0 < 2 ||
+ G_cme_stop_record.act_level_c1 < 2)))
{
- return CME_STOP_EXIT_WAKEUP_FROM_STOP1;
+ pk_halt();
}
// set target_level to STOP level for c0
// unless c1(also or only) wants to wakeup
target_level = deeper_level =
- (core == CME_MASK_C0) ? G_cme_stop_record.act_stop_c0 :
- G_cme_stop_record.act_stop_c1;
+ (core == CME_MASK_C0) ? G_cme_stop_record.act_level_c0 :
+ G_cme_stop_record.act_level_c1;
// If both cores want to wakeup but are in different STOP levels,
// set deeper_level to the deeper level targeted by deeper core
if ((core == CME_MASK_BC) &&
- (G_cme_stop_record.act_stop_c0 != G_cme_stop_record.act_stop_c1))
+ (G_cme_stop_record.act_level_c0 != G_cme_stop_record.act_level_c1))
{
// Assume C0 is deeper, target_level is already set to C1
- deeper_level = G_cme_stop_record.act_stop_c0;
+ deeper_level = G_cme_stop_record.act_level_c0;
deeper_core = CME_MASK_C0;
// Otherwise correct assumption on which one is in lighter level
- if (G_cme_stop_record.act_stop_c0 < G_cme_stop_record.act_stop_c1)
+ if (G_cme_stop_record.act_level_c0 < G_cme_stop_record.act_level_c1)
{
- target_level = G_cme_stop_record.act_stop_c0;
- deeper_level = G_cme_stop_record.act_stop_c1;
+ target_level = G_cme_stop_record.act_level_c0;
+ deeper_level = G_cme_stop_record.act_level_c1;
deeper_core = CME_MASK_C1;
}
}
- PK_TRACE("X0: target_lv[%d], deeper_lv[%d], deeper_core[%d]",
+ PK_TRACE("X0: target_lv[%d], deeper_lv[%d], deeper_c[%d]",
target_level, deeper_level, deeper_core);
PK_TRACE("X0: Update STOP History: In Transition of Exit");
@@ -132,7 +134,7 @@ p9_cme_stop_exit()
// (G_cme_stop_record.pm_state_c0 < 11)) ||
// ((~grant & CME_MASK_C1 & core) &&
// (G_cme_stop_record.pm_state_c1 < 11)))
- // return CME_STOP_EXIT_PCBMUX_LOST_GRANT;
+ // pk_halt();
out32(CME_LCL_SICR_OR, core << SHIFT32(11));
while((core & (in32(CME_LCL_SISR) >> SHIFT32(11))) != core);
@@ -143,7 +145,9 @@ p9_cme_stop_exit()
// STOP LEVEL 4
//--------------------------------------------------------------------------
- MARK_TRAP(SX_WAKEUP_START)
+ //======================
+ MARK_TAG(SX_STOP3, core)
+ //======================
if (deeper_level >= 4)
{
@@ -165,18 +169,22 @@ p9_cme_stop_exit()
//PK_TRACE("X1: Request PCB Arbiter");
//p9_hcd_core_pcb_arb(core, 1);
+ //========================
+ MARK_TAG(SX_POWERON, core)
+ //========================
+
PK_TRACE("X1: Core Poweron");
- MARK_TRAP(SX_POWERON)
p9_hcd_core_poweron(core);
- MARK_TRAP(SX_POWERON_END)
- PK_TRACE("X2: Core Chiplet Reset");
+ //=========================
MARK_TRAP(SX_CHIPLET_RESET)
+ //=========================
+
+ PK_TRACE("X2: Core Chiplet Reset");
p9_hcd_core_chiplet_reset(core);
- MARK_TRAP(SX_CHIPLET_RESET_END)
#if !STOP_PRIME
-#if !SKIP_CATCHUP
+#if !SKIP_EXIT_CATCHUP
//catchup
if (catchup_ongoing)
@@ -188,58 +196,61 @@ p9_cme_stop_exit()
{
wakeup = (in32(CME_LCL_EISR) >> SHIFT32(17)) & 0x3F;
out32(CME_LCL_EISR_CLR, wakeup << SHIFT32(17));
- core_catchup = ((wakeup >> 4) | (wakeup >> 2) | (wakeup >> 0)) &
- CME_MASK_BC;
+ core_catchup =
+ ((wakeup >> 4) | (wakeup >> 2) | (wakeup >> 0)) &
+ CME_MASK_BC;
if (core_catchup && (core_catchup + core) == CME_MASK_BC)
{
out32(CME_LCL_SICR_OR, core_catchup << SHIFT32(11));
if(((core_catchup & CME_MASK_C0) &&
- G_cme_stop_record.act_stop_c0 == STOP_LEVEL_2) ||
+ G_cme_stop_record.act_level_c0 == STOP_LEVEL_2) ||
((core_catchup & CME_MASK_C1) &&
- G_cme_stop_record.act_stop_c1 == STOP_LEVEL_2))
+ G_cme_stop_record.act_level_c1 == STOP_LEVEL_2))
{
deeper_core = core;
d2u4_flag = 1;
}
else if(((core_catchup & CME_MASK_C0) &&
- G_cme_stop_record.act_stop_c0 == STOP_LEVEL_4) ||
+ G_cme_stop_record.act_level_c0 == STOP_LEVEL_4) ||
((core_catchup & CME_MASK_C1) &&
- G_cme_stop_record.act_stop_c1 == STOP_LEVEL_4))
+ G_cme_stop_record.act_level_c1 == STOP_LEVEL_4))
{
core = core_catchup;
catchup_ongoing = 1;
continue;
}
- while((core_catchup & (in32(CME_LCL_SISR) >> SHIFT32(11))) !=
- core_catchup);
+ while((core_catchup & (in32(CME_LCL_SISR) >>
+ SHIFT32(11))) != core_catchup);
}
+
+ //==========================
+ MARK_TAG(SX_CATCHUP_A, core)
+ //==========================
}
#endif
#if !SKIP_INITF
+ //==============================
+ MARK_TAG(SX_CHIPLET_INITS, core)
+ //==============================
+
PK_TRACE("X3: Core GPTR Time Initf");
- MARK_TRAP(SX_GPTR_TIME_INITF)
p9_hcd_core_gptr_time_initf(core);
- MARK_TRAP(SX_GPTR_TIME_INITF_END)
#endif
PK_TRACE("X5: Core Chiplet Init");
- MARK_TRAP(SX_CHIPLET_INIT)
p9_hcd_core_chiplet_init(core);
- MARK_TRAP(SX_CHIPLET_INIT_END)
#if !SKIP_INITF
PK_TRACE("X6: Core Repair Initf");
- MARK_TRAP(SX_REPAIR_INITF)
p9_hcd_core_repair_initf(core);
- MARK_TRAP(SX_REPAIR_INITF_END)
#endif
-#if !SKIP_CATCHUP
+#if !SKIP_EXIT_CATCHUP
//catchup
if (catchup_ongoing)
@@ -251,50 +262,59 @@ p9_cme_stop_exit()
{
wakeup = (in32(CME_LCL_EISR) >> SHIFT32(17)) & 0x3F;
out32(CME_LCL_EISR_CLR, wakeup << SHIFT32(17));
- core_catchup = ((wakeup >> 4) | (wakeup >> 2) | (wakeup >> 0)) &
- CME_MASK_BC;
+ core_catchup =
+ ((wakeup >> 4) | (wakeup >> 2) | (wakeup >> 0)) &
+ CME_MASK_BC;
if (core_catchup && (core_catchup + core) == CME_MASK_BC)
{
out32(CME_LCL_SICR_OR, core_catchup << SHIFT32(11));
if(((core_catchup & CME_MASK_C0) &&
- G_cme_stop_record.act_stop_c0 == STOP_LEVEL_2) ||
+ G_cme_stop_record.act_level_c0 == STOP_LEVEL_2) ||
((core_catchup & CME_MASK_C1) &&
- G_cme_stop_record.act_stop_c1 == STOP_LEVEL_2))
+ G_cme_stop_record.act_level_c1 == STOP_LEVEL_2))
{
deeper_core = core;
d2u4_flag = 1;
}
else if(((core_catchup & CME_MASK_C0) &&
- G_cme_stop_record.act_stop_c0 == STOP_LEVEL_4) ||
+ G_cme_stop_record.act_level_c0 == STOP_LEVEL_4) ||
((core_catchup & CME_MASK_C1) &&
- G_cme_stop_record.act_stop_c1 == STOP_LEVEL_4))
+ G_cme_stop_record.act_level_c1 == STOP_LEVEL_4))
{
core = core_catchup;
catchup_ongoing = 1;
continue;
}
- while((core_catchup & (in32(CME_LCL_SISR) >> SHIFT32(11))) !=
- core_catchup);
+ while((core_catchup & (in32(CME_LCL_SISR) >>
+ SHIFT32(11))) != core_catchup);
}
+
+ //==========================
+ MARK_TAG(SX_CATCHUP_B, core)
+ //==========================
}
#endif
#if !SKIP_ARY_INIT
+ //===========================
+ MARK_TAG(SX_ARRAY_INIT, core)
+ //===========================
+
PK_TRACE("X7: Core Array Init");
- MARK_TRAP(SX_ARRAY_INIT)
p9_hcd_core_arrayinit(core);
- MARK_TRAP(SX_ARRAY_INIT_END)
#endif
#if !SKIP_INITF
+ //=====================
+ MARK_TRAP(SX_FUNC_INIT)
+ //=====================
+
PK_TRACE("X8: Core Func Scan");
- MARK_TRAP(SX_INITF)
p9_hcd_core_initf(core);
- MARK_TRAP(SX_INITF_END)
#endif
#endif
@@ -313,10 +333,15 @@ p9_cme_stop_exit()
// STOP LEVEL 2
//--------------------------------------------------------------------------
+ //============================
+ MARK_TAG(SX_STARTCLOCKS, core)
+ //============================
+
PK_TRACE("X9: Start Core Clock");
- MARK_TRAP(SX_STARTCLOCKS)
p9_hcd_core_startclocks(core);
- MARK_TRAP(SX_STARTCLOCKS_END)
+
+ // Clear CPPM PECE Shadow
+ CME_PUTSCOM(CPPM_PECES, core, 0);
//--------------------------------------------------------------------------
// STOP LEVEL 4
@@ -332,42 +357,51 @@ p9_cme_stop_exit()
}
#if !STOP_PRIME
- // one example scom fir mask reg maybe
+ //===========================
+ MARK_TAG(SX_SCOM_INITS, core)
+ //===========================
+
PK_TRACE("X10: Image Hardcoded Scoms");
- MARK_TRAP(SX_SCOMINIT)
p9_hcd_core_scominit(core);
- MARK_TRAP(SX_SCOMINIT_END)
+ //==========================
+ MARK_TAG(SX_BCE_CHECK, core)
+ //==========================
// todo PK_TRACE("BCE Runtime Check");
// todo
//PK_TRACE("X11: XIP Customized Scoms");
//MARK_TRAP(SX_SCOMCUST)
//p9_hcd_core_scomcust(core);
- //MARK_TRAP(SX_SCOMCUST_END)
+
+ //==============================
+ MARK_TAG(SX_RUNTIME_INITS, core)
+ //==============================
// todo
//PK_TRACE("X12: RAS Runtime Scom");
- //MARK_TRAP(SX_RAS_RUNTIME_SCOM)
//p9_hcd_core_ras_runtime_scom(core);
- //MARK_TRAP(SX_RAS_RUNTIME_SCOM_END)
// todo
//PK_TRACE("X13: OCC Runtime Scom");
- //MARK_TRAP(SX_RAS_RUNTIME_SCOM)
//p9_hcd_core_occ_runtime_scom(core);
- //MARK_TRAP(SX_RAS_RUNTIME_SCOM_END)
#endif
+ //=============================
+ MARK_TAG(SX_SELF_RESTORE, core)
+ //=============================
+
PK_TRACE("X14: Core Self Restore");
- MARK_TRAP(SX_SELFRESTORE)
#if !SKIP_SELF_RESTORE
PK_TRACE("Raise block interrupt to PC");
out32(CME_LCL_SICR_OR, core << SHIFT32(3));
- PK_TRACE("RAM HRMOR");
+ //=====================
MARK_TRAP(SX_RAM_HRMOR)
+ //=====================
+
+ PK_TRACE("RAM HRMOR");
PK_TRACE("Now Wakeup the Core(pm_exit=1)");
out32(CME_LCL_SICR_OR, core << SHIFT32(5));
@@ -381,7 +415,9 @@ p9_cme_stop_exit()
// BIT64(3)|BIT64(11)|BIT64(19)|BIT64(27));
// BIT64(4)|BIT64(12)|BIT64(20)|BIT64(28));
+ //==========================
MARK_TRAP(SX_SRESET_THREADS)
+ //==========================
PK_TRACE("Allow threads to run(pm_exit=0)");
out32(CME_LCL_SICR_CLR, core << SHIFT32(5));
@@ -390,15 +426,29 @@ p9_cme_stop_exit()
while((~(in32(CME_LCL_EINR))) & (core << SHIFT32(21)));
+ //==========================
MARK_TRAP(SX_STOP15_THREADS)
+ //==========================
//PK_TRACE("Restore PSSCR back to actual level");
+ //PLS here:
+ if (core & CME_MASK_C0)
+ CME_PUTSCOM(DIRECT_CONTROLS, CME_MASK_C0,
+ (((uint64_t)G_cme_stop_record.act_level_c0 <<
+ SHIFT64(36)) | BIT64(32)));
+
+ if (core & CME_MASK_C1)
+ CME_PUTSCOM(DIRECT_CONTROLS, CME_MASK_C1,
+ (((uint64_t)G_cme_stop_record.act_level_c1 <<
+ SHIFT64(36)) | BIT64(32)));
PK_TRACE("Drop block interrupt to PC");
out32(CME_LCL_SICR_CLR, core << SHIFT32(3));
#endif
- MARK_TRAP(SX_SELFRESTORE_END)
+ //=========================
+ MARK_TRAP(SX_ENABLE_ANALOG)
+ //=========================
if (d2u4_flag)
{
@@ -431,31 +481,29 @@ p9_cme_stop_exit()
STOP_REQ_DISABLE,
STOP_ACT_DISABLE)
- G_cme_stop_record.active_core |= core;
+ G_cme_stop_record.core_running |= core;
+ G_cme_stop_record.core_stopgpe &= ~core;
+ out32(CME_LCL_LMCR_CLR, (core << SHIFT32(15)));
if (core & CME_MASK_C0)
{
- G_cme_stop_record.act_stop_c0 = 0;
+ G_cme_stop_record.req_level_c0 = 0;
+ G_cme_stop_record.act_level_c0 = 0;
}
if (core & CME_MASK_C1)
{
- G_cme_stop_record.act_stop_c1 = 0;
+ G_cme_stop_record.req_level_c1 = 0;
+ G_cme_stop_record.act_level_c1 = 0;
}
// If not special wakeup, allow core to go back into STOP in the future
if (!spwu)
{
- PK_TRACE("XF: Drop pm_exit if not special wakeup");
+ PK_TRACE("XF: Drop pm_exit if special wakeup is not present");
out32(CME_LCL_SICR_CLR, core << SHIFT32(5));
}
- // unmask stop interrupts
- out32(CME_LCL_EIMR_CLR, ((core << SHIFT32(21)) |
- /* ((~core & ~G_cme_stop_record.active_core & CME_MASK_BC)<<SHIFT32(13))| */
- ((~core & ~G_cme_stop_record.active_core & CME_MASK_BC) << SHIFT32(15)) |
- ((~core & ~G_cme_stop_record.active_core & CME_MASK_BC) << SHIFT32(17))));
-
//===========================
MARK_TRAP(ENDSCOPE_STOP_EXIT)
//===========================
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit_marks.h b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit_marks.h
index 59c59d5b..30f2121d 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit_marks.h
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_exit_marks.h
@@ -36,44 +36,31 @@ namespace CME_STOP_EXIT_MARKS
enum CME_SX_MARKS
{
- SX_WAKEUP_START = 0x0,
+ SX_STOP3 = 0x0,
SX_POWERON = 0x8,
SX_POWERON_DONE = 0x10,
- SX_POWERON_PG_SEL = 0x18,
- SX_POWERON_END = 0x20,
- SX_CHIPLET_RESET = 0x28,
- SX_CHIPLET_RESET_GLSMUX_RESET = 0x30,
- SX_CHIPLET_RESET_SCAN0 = 0x38,
- SX_CHIPLET_RESET_END = 0x40,
- SX_GPTR_TIME_INITF = 0x48,
- SX_GPTR_TIME_INITF_END = 0x50,
- SX_CHIPLET_INIT = 0x68,
- SX_CHIPLET_INIT_SCAN0 = 0xe0,
- SX_CHIPLET_INIT_END = 0xe8,
- SX_REPAIR_INITF = 0xf0,
- SX_REPAIR_INITF_END = 0xf8,
- SX_ARRAY_INIT = 0x100,
- SX_ARRAY_INIT_SUBMODULE = 0x108,
- SX_ARRAY_INIT_SCAN0 = 0x110,
- SX_ARRAY_INIT_END = 0x118,
- SX_INITF = 0x120,
- SX_INITF_END = 0x128,
- SX_STARTCLOCKS = 0x130,
- SX_STARTCLOCKS_DONE = 0x138,
- SX_STARTCLOCKS_END = 0x140,
- SX_SCOMINIT = 0x148,
- SX_SCOMINIT_END = 0x150,
- SX_SCOMCUST = 0x168,
- SX_SCOMCUST_END = 0x1e0,
- SX_RAS_RUNTIME_SCOM = 0x1e8,
- SX_RAS_RUNTIME_SCOM_END = 0x230,
- SX_OCC_RUNTIME_SCOM = 0x238,
- SX_OCC_RUNTIME_SCOM_END = 0x200,
- SX_SELFRESTORE = 0x208,
- SX_RAM_HRMOR = 0x210,
- SX_SRESET_THREADS = 0x218,
- SX_STOP15_THREADS = 0x220,
- SX_SELFRESTORE_END = 0x228,
+ SX_CHIPLET_RESET = 0x18,
+ SX_CHIPLET_RESET_GLSMUX_RESET = 0x20,
+ SX_CHIPLET_RESET_SCAN0 = 0x28,
+ SX_CATCHUP_A = 0x30,
+ SX_CHIPLET_INITS = 0x38,
+ SX_CHIPLET_INIT_SCAN0 = 0x40,
+ SX_CATCHUP_B = 0x48,
+ SX_ARRAY_INIT = 0x50,
+ SX_ARRAY_INIT_SUBMODULE = 0x68,
+ SX_ARRAY_INIT_SCAN0 = 0xe0,
+ SX_FUNC_INIT = 0xe8,
+ SX_STARTCLOCKS = 0xf0,
+ SX_STARTCLOCKS_GRID = 0xf8,
+ SX_STARTCLOCKS_DONE = 0x100,
+ SX_SCOM_INITS = 0x108,
+ SX_BCE_CHECK = 0x110,
+ SX_RUNTIME_INITS = 0x118,
+ SX_SELF_RESTORE = 0x120,
+ SX_RAM_HRMOR = 0x128,
+ SX_SRESET_THREADS = 0x130,
+ SX_STOP15_THREADS = 0x138,
+ SX_ENABLE_ANALOG = 0x140,
BEGINSCOPE_STOP_EXIT = 0x1f28,
ENDSCOPE_STOP_EXIT = 0x1f30
};
@@ -83,44 +70,31 @@ enum CME_SX_MARKS
const std::vector<CME_SX_MARKS> MARKS =
{
- SX_WAKEUP_START,
+ SX_STOP3,
SX_POWERON,
SX_POWERON_DONE,
- SX_POWERON_PG_SEL,
- SX_POWERON_END,
SX_CHIPLET_RESET,
SX_CHIPLET_RESET_GLSMUX_RESET,
SX_CHIPLET_RESET_SCAN0,
- SX_CHIPLET_RESET_END,
- SX_GPTR_TIME_INITF,
- SX_GPTR_TIME_INITF_END,
- SX_CHIPLET_INIT,
+ SX_CATCHUP_A,
+ SX_CHIPLET_INITS,
SX_CHIPLET_INIT_SCAN0,
- SX_CHIPLET_INIT_END,
- SX_REPAIR_INITF,
- SX_REPAIR_INITF_END,
+ SX_CATCHUP_B,
SX_ARRAY_INIT,
SX_ARRAY_INIT_SUBMODULE,
SX_ARRAY_INIT_SCAN0,
- SX_ARRAY_INIT_END,
- SX_INITF,
- SX_INITF_END,
+ SX_FUNC_INIT,
SX_STARTCLOCKS,
+ SX_STARTCLOCKS_GRID,
SX_STARTCLOCKS_DONE,
- SX_STARTCLOCKS_END,
- SX_SCOMINIT,
- SX_SCOMINIT_END,
- SX_SCOMCUST,
- SX_SCOMCUST_END,
- SX_RAS_RUNTIME_SCOM,
- SX_RAS_RUNTIME_SCOM_END,
- SX_OCC_RUNTIME_SCOM,
- SX_OCC_RUNTIME_SCOM_END,
- SX_SELFRESTORE,
+ SX_SCOM_INITS,
+ SX_BCE_CHECK,
+ SX_RUNTIME_INITS,
+ SX_SELF_RESTORE,
SX_RAM_HRMOR,
SX_SRESET_THREADS,
SX_STOP15_THREADS,
- SX_SELFRESTORE_END,
+ SX_ENABLE_ANALOG,
BEGINSCOPE_STOP_EXIT,
ENDSCOPE_STOP_EXIT
};
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_irq_handlers.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_irq_handlers.c
index e929ff31..59b95954 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_irq_handlers.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_cme_stop_irq_handlers.c
@@ -25,6 +25,7 @@
#include "p9_cme_stop.h"
#include "p9_cme_stop_enter_marks.h"
+#include "p9_cme_irq.h"
extern CmeStopRecord G_cme_stop_record;
@@ -33,24 +34,34 @@ p9_cme_stop_event_handler(void* arg, PkIrqId irq)
{
MARK_TRAP(STOP_EVENT_HANDLER)
PK_TRACE("SE-IRQ: %d", irq);
-
- if (irq == IRQ_STOP_C0 || irq == IRQ_STOP_C1)
- {
- out32(CME_LCL_EIMR_OR, BITS32(20, 2));
- }
-
- if (irq >= IRQ_PC_C0 && irq <= IRQ_SWU_C1)
- {
- out32(CME_LCL_EIMR_OR, BITS32(12, 6));
- }
-
pk_semaphore_post((PkSemaphore*)arg);
+
+ // Important: g_eimr_override at any time should mask wakeup interrupts of
+ // running core(s), the override vector should change after each
+ // entry and exit as core state is changed.
+ // For Entry, mask the following interrupts via unified interrupt handler:
+ // lower priority interrupts than pm_active, and both pm_active (catchup)
+ // wakeup interrupts of the entering core(s) should still be masked
+ // via g_eimr_override (abortion), stopped core can still exit any time
+ // as their wakeup interrupts should be unmasked
+ // After Entry, unmask the following interrupts via pk_irq_vec_restore:
+ // priority group on stack, likely at least both pm_active unmasked
+ // (stopped core cannot get extra pm_active, untouched core can enter)
+ // here needs to use g_eimr_override to mask wakeup of running core(s)
+ // wakeup of the stopped core(s) should be already unmasked by default
+ // (when restored, previous masked wakeups are being unmasked as well)
+ // For Exit, mask the following interrupts via unified interrupt handler:
+ // lower priority interrupts than wakeup, including DB2+pm_active(catchup)
+ // After Exit, unmask the following interrupts via pk_irq_vec_restore:
+ // priority group on stack, likely at least wakeup and DB2 unmasked
+ // here needs to use g_eimr_override to mask wakeup of exited core(s)
}
void
p9_cme_stop_doorbell_handler(void* arg, PkIrqId irq)
{
- int rc = 0;
+ int rc = 0;
+ PkMachineContext ctx;
MARK_TRAP(STOP_DOORBELL_HANDLER)
PK_TRACE("DB-IRQ: %d", irq);
@@ -60,15 +71,16 @@ p9_cme_stop_doorbell_handler(void* arg, PkIrqId irq)
if (irq == IRQ_DB1_C0)
{
CME_PUTSCOM(CPPM_CMEDB1, CME_MASK_C0, 0);
- out32(CME_LCL_EIMR_CLR, BIT32(12) | BIT32(14) | BIT32(16));
+ g_eimr_override &= ~IRQ_VEC_WAKE_C0;
+ //out32(CME_LCL_EIMR_CLR, BIT32(12) | BIT32(14) | BIT32(16));
}
if (irq == IRQ_DB1_C1)
{
CME_PUTSCOM(CPPM_CMEDB1, CME_MASK_C1, 0);
- out32(CME_LCL_EIMR_CLR, BIT32(13) | BIT32(15) | BIT32(17));
+ g_eimr_override &= ~IRQ_VEC_WAKE_C1;
+ //out32(CME_LCL_EIMR_CLR, BIT32(13) | BIT32(15) | BIT32(17));
}
- //TODO mask pc_itr_pending as workaround for double interrupts of pc and rwu
- out32(CME_LCL_EIMR_OR, BITS32(12, 2));
+ pk_irq_vec_restore(&ctx);
}
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_chiplet_reset.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_chiplet_reset.c
index ad044dfb..50c0e058 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_chiplet_reset.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_chiplet_reset.c
@@ -30,43 +30,55 @@ int
p9_hcd_core_chiplet_reset(uint32_t core)
{
int rc = CME_STOP_SUCCESS;
- uint64_t data, loop;
+ //uint64_t scom_data,
+ uint32_t loop;
- PK_TRACE("Init NETWORK_CONTROL0, step needed for hotplug");
+ PK_TRACE("Init NET_CTRL0[1-5,12-14,18,22,26],step needed for hotplug");
CME_PUTSCOM(CPPM_NC0INDIR_OR, core, NET_CTRL0_INIT_VECTOR);
- PK_TRACE("Assert Core Progdly and DCC Bypass");
+ PK_TRACE("Flip core glsmux to refclk via PPM_CGCR[3]");
+ CME_PUTSCOM(C_PPM_CGCR, core, BIT64(0));
+
+ PK_TRACE("Assert core progdly and DCC bypass via NET_CTRL1[1,2]");
CME_PUTSCOM(CPPM_NC1INDIR_OR, core, BITS64(1, 2));
- PK_TRACE("Assert Core DCC Reset");
+ PK_TRACE("Assert core DCC reset via NET_CTRL0[2]");
CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(2));
- PK_TRACE("Assert Vital Thold");
+ PK_TRACE("Drop vital thold via NET_CTRL0[16]");
CME_PUTSCOM(CPPM_NC0INDIR_CLR, core, BIT64(16));
-
- PK_TRACE("ONLY till TP030: SET VITL_PHASE=1");
- CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(8));
- PPE_WAIT_CORE_CYCLES(loop, 50);
-
+ /*
+ PK_TRACE("ONLY till TP030: SET VITL_PHASE=1");
+ CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(8));
+ PPE_WAIT_CORE_CYCLES(loop, 50);
+ */
MARK_TRAP(SX_CHIPLET_RESET_GLSMUX_RESET)
- PK_TRACE("Init Core Glitchless Mux Reset/Select via CLOCK_GRID_CTRL[0:3]");
+ PK_TRACE("Drop core glsmux reset via PPM_CGCR[0]");
+ CME_PUTSCOM(C_PPM_CGCR, core, 0);
+ PPE_WAIT_CORE_CYCLES(loop, 400);
+
+ PK_TRACE("Flip core glsmux to DPLL via PPM_CGCR[3]");
CME_PUTSCOM(C_PPM_CGCR, core, BIT64(3));
- PK_TRACE("Clear PCB Endpoint Reset via NET_CTRL0[1]");
+ PK_TRACE("Assert chiplet enable via NET_CTRL0[0]");
+ CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(0));
+
+ PK_TRACE("Drop PCB endpoint reset via NET_CTRL0[1]");
CME_PUTSCOM(CPPM_NC0INDIR_CLR, core, BIT64(1));
- PPE_WAIT_CORE_CYCLES(loop, 50);
- PK_TRACE("Remove chiplet electrical fence via NET_CTRL0[26]");
+ PK_TRACE("Drop chiplet electrical fence via NET_CTRL0[26]");
CME_PUTSCOM(CPPM_NC0INDIR_CLR, core, BIT64(26));
- CME_PUTSCOM(CPPM_NC0INDIR_CLR, core, BIT64(25));
-
- PK_TRACE("ONLY till TP030: SET SYNC_PULSE_DELAY=0b0011");
- CME_GETSCOM(C_SYNC_CONFIG, core, CME_SCOM_AND, data);
- data = data | 0x3000000000000000;
- data = data & 0x3FFFFFFFFFFFFFFF;
- CME_PUTSCOM(C_SYNC_CONFIG, core, data);
+ PK_TRACE("Drop PCB fence via NET_CTRL0[25]");
+ CME_PUTSCOM(CPPM_NC0INDIR_CLR, core, BIT64(25));
+ /*
+ PK_TRACE("ONLY till TP030: SET SYNC_PULSE_DELAY=0b0011");
+ CME_GETSCOM(C_SYNC_CONFIG, core, CME_SCOM_AND, scom_data);
+ scom_data = scom_data | 0x3000000000000000;
+ scom_data = scom_data & 0x3FFFFFFFFFFFFFFF;
+ CME_PUTSCOM(C_SYNC_CONFIG, core, scom_data);
+ */
#if !SKIP_SCAN0
// Marker for scan0
MARK_TRAP(SX_CHIPLET_RESET_SCAN0)
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_poweron.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_poweron.c
index 7dce5e04..b24a192e 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_poweron.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_poweron.c
@@ -31,21 +31,23 @@ p9_hcd_core_poweron(uint32_t core)
{
int rc = CME_STOP_SUCCESS;
- PK_TRACE("Set core glsmux reset");
+ PK_TRACE("Drop chiplet enable via NET_CTRL0[0]");
+ CME_PUTSCOM(CPPM_NC0INDIR_CLR, core, BIT64(0));
+
+ PK_TRACE("Assert PCB fence via NET_CTRL0[25]");
+ CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(25));
+
+ PK_TRACE("Assert chiplet electrical fence via NET_CTRL0[26]");
+ CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(26));
+
+ PK_TRACE("Assert vital thold via NET_CTRL0[16]");
+ CME_PUTSCOM(CPPM_NC0INDIR_OR, core, BIT64(16));
+
+ PK_TRACE("Assert core glsmux reset via PPM_CGCR[0]");
CME_PUTSCOM(C_PPM_CGCR, core, BIT64(0));
+
#if !STOP_PRIME
uint64_t scom_data;
-#if !EPM_P9_TUNNING
- // vdd_pfet_force_state == 00 (Nop)
- PK_TRACE("Make sure we are not forcing PFET for VDD off");
- CME_GETSCOM(PPM_PFCS, core, CME_SCOM_AND, scom_data);
-
- if (scom_data & BITS64(0, 2))
- {
- return CME_STOP_ENTRY_VDD_PFET_NOT_IDLE;
- }
-
-#endif
// vdd_pfet_val/sel_override = 0 (disbaled)
// vdd_pfet_regulation_finger_en = 0 (controled by FSM)
@@ -66,17 +68,6 @@ p9_hcd_core_poweron(uint32_t core)
MARK_TRAP(SX_POWERON_DONE)
-#if !EPM_P9_TUNNING
- PK_TRACE("Optional: Poll for vdd_pg_sel being: 0x0");
-
- do
- {
- CME_GETSCOM(PPM_PFCS, core, CME_SCOM_AND, scom_data);
- }
- while(scom_data & BIT64(46));
-
- MARK_TRAP(SX_POWERON_PG_SEL)
-#endif
// vdd_pfet_force_state = 00 (Nop)
PK_TRACE("Turn Off Force Von");
CME_PUTSCOM(PPM_PFCS_CLR, core, BITS64(0, 2));
diff --git a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_startclocks.c b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_startclocks.c
index 5f383b74..3ab36b7f 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_startclocks.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/stop_cme/p9_hcd_core_startclocks.c
@@ -30,84 +30,85 @@ int
p9_hcd_core_startclocks(uint32_t core)
{
int rc = CME_STOP_SUCCESS;
- uint64_t data, loop;
+ uint64_t scom_data, loop;
- PK_TRACE("Setup OPCG_ALIGN Register");
- CME_GETSCOM(C_OPCG_ALIGN, core, CME_SCOM_AND, data);
- data = data & ~(BITS64(0, 4) & BITS64(12, 8) & BITS64(52, 12));
- data = data | (BIT64(1) | BIT64(3) | BIT64(59));
- CME_PUTSCOM(C_OPCG_ALIGN, core, data);
+ // do this again here for stop2 in addition to chiplet_reset
+ PK_TRACE("4S2: Set Core Glitchless Mux to DPLL");
+ CME_PUTSCOM(C_PPM_CGCR, core, BIT64(3));
- PK_TRACE("Drop partial good fences via CPLT_CTRL1");
+ PK_TRACE("Set inop_align/wait/wait_cycles via OPCG_ALIGN[0-3,12-19,52-63]");
+ CME_GETSCOM(C_OPCG_ALIGN, core, CME_SCOM_AND, scom_data);
+ scom_data = scom_data & ~(BITS64(0, 4) & BITS64(12, 8) & BITS64(52, 12));
+ scom_data = scom_data | (BIT64(1) | BIT64(3) | BIT64(59));
+ CME_PUTSCOM(C_OPCG_ALIGN, core, scom_data);
+
+ PK_TRACE("Drop partial good fences via CPLT_CTRL1[3-14]");
CME_PUTSCOM(C_CPLT_CTRL1_CLEAR, core, 0xFFFF700000000000);
- PK_TRACE("Drop vital fences via CPLT_CTRL1");
+ PK_TRACE("Drop vital fences via CPLT_CTRL1[3]");
CME_PUTSCOM(C_CPLT_CTRL1_CLEAR, core, BIT64(3));
- PK_TRACE("Raise core clock sync enable");
+ PK_TRACE("Assert core clock sync enable via CPPM_CACCR[15]");
CME_PUTSCOM(CPPM_CACCR_OR, core, BIT64(15));
-#if !EPM_P9_TUNING
- PK_TRACE("Poll for core clock sync done to raise");
+ PK_TRACE("Poll for core clock sync done via CPPM_CACSR[13]");
do
{
- CME_GETSCOM(CPPM_CACSR, core, CME_SCOM_AND, data);
+ CME_GETSCOM(CPPM_CACSR, core, CME_SCOM_AND, scom_data);
}
- while(~data & BIT64(13));
-
-#endif
+ while(~scom_data & BIT64(13));
PK_TRACE("Reset abstclk & syncclk muxsel(io_clk_sel) via CPLT_CTRL0[0:1]");
CME_PUTSCOM(C_CPLT_CTRL0_CLEAR, core, BITS64(0, 2));
// align_chiplets()
- PK_TRACE("Set flushmode_inhibit via CPLT_CTRL0[2]");
+ PK_TRACE("Assert flushmode_inhibit via CPLT_CTRL0[2]");
CME_PUTSCOM(C_CPLT_CTRL0_OR, core, BIT64(2));
- PK_TRACE("Set force_align via CPLT_CTRL0[3]");
+ PK_TRACE("Assert force_align via CPLT_CTRL0[3]");
CME_PUTSCOM(C_CPLT_CTRL0_OR, core, BIT64(3));
- PK_TRACE("Set/Unset clear_chiplet_is_aligned via SYNC_CONFIG[7]");
- CME_GETSCOM(C_SYNC_CONFIG, core, CME_SCOM_AND, data);
- data = data | BIT64(7);
- CME_PUTSCOM(C_SYNC_CONFIG, core, data);
- data = data & ~BIT64(7);
- CME_PUTSCOM(C_SYNC_CONFIG, core, data);
+ PK_TRACE("Set then unset clear_chiplet_is_aligned via SYNC_CONFIG[7]");
+ CME_GETSCOM(C_SYNC_CONFIG, core, CME_SCOM_AND, scom_data);
+ scom_data = scom_data | BIT64(7);
+ CME_PUTSCOM(C_SYNC_CONFIG, core, scom_data);
+ scom_data = scom_data & ~BIT64(7);
+ CME_PUTSCOM(C_SYNC_CONFIG, core, scom_data);
PK_TRACE("Check chiplet_is_aligned");
do
{
- CME_GETSCOM(C_CPLT_STAT0, core, CME_SCOM_AND, data);
+ CME_GETSCOM(C_CPLT_STAT0, core, CME_SCOM_AND, scom_data);
}
- while(~data & BIT64(9));
+ while(~scom_data & BIT64(9));
- PK_TRACE("Clear force_align via CPLT_CTRL0[3]");
+ PK_TRACE("Drop force_align via CPLT_CTRL0[3]");
CME_PUTSCOM(C_CPLT_CTRL0_CLEAR, core, BIT64(3));
PPE_WAIT_CORE_CYCLES(loop, 450);
// clock_start()
- PK_TRACE("Set all bits to zero prior clock start via SCAN_REGION_TYPE");
+ PK_TRACE("Clear all bits prior start core clocks via SCAN_REGION_TYPE");
CME_PUTSCOM(C_SCAN_REGION_TYPE, core, 0);
- PK_TRACE("Start clock(arrays+nsl clock region) via CLK_REGION");
- data = 0x5FFC000000006000;
- CME_PUTSCOM(C_CLK_REGION, core, data);
+ PK_TRACE("Start core clocks(arrays+nsl clock region) via CLK_REGION");
+ scom_data = 0x4FFC000000006000;
+ CME_PUTSCOM(C_CLK_REGION, core, scom_data);
- PK_TRACE("Start clock(sl+refresh clock region) via CLK_REGION");
- data = 0x5FFC00000000E000;
- CME_PUTSCOM(C_CLK_REGION, core, data);
+ PK_TRACE("Start core clocks(sl+refresh clock region) via CLK_REGION");
+ scom_data = 0x4FFC00000000E000;
+ CME_PUTSCOM(C_CLK_REGION, core, scom_data);
- PK_TRACE("Polling for clocks starting via CLOCK_STAT_SL");
+ PK_TRACE("Polling for core clocks running via CLOCK_STAT_SL");
do
{
- CME_GETSCOM(C_CLOCK_STAT_SL, core, CME_SCOM_AND, data);
+ CME_GETSCOM(C_CLOCK_STAT_SL, core, CME_SCOM_AND, scom_data);
}
- while((~data & BITS64(4, 10)) != BITS64(4, 10));
+ while((scom_data & BITS64(4, 10)) != 0);
PK_TRACE("Core clock is now running");
@@ -116,12 +117,9 @@ p9_hcd_core_startclocks(uint32_t core)
PK_TRACE("Drop chiplet fence via NC0INDIR[18]");
CME_PUTSCOM(CPPM_NC0INDIR_CLR, core, BIT64(18));
- //PK_TRACE("Drop fence to allow PCB operations to chiplet via NC0INDIR[26]");
- //CME_PUTSCOM(CPPM_NC0INDIR_CLR, core, BIT64(25));
-
// checkstop
- PK_TRACE("Clear flushmode_inhibit via CPLT_CTRL0[2]");
+ PK_TRACE("Drop flushmode_inhibit via CPLT_CTRL0[2]");
CME_PUTSCOM(C_CPLT_CTRL0_CLEAR, core, BIT64(2));
// check align
diff --git a/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk b/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk
new file mode 100644
index 00000000..4112e534
--- /dev/null
+++ b/import/chips/p9/procedures/ppe_closed/cme/topfiles.mk
@@ -0,0 +1,51 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: import/chips/p9/procedures/ppe_closed/cme/topfiles.mk $
+#
+# 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
+
+
+TOP-C-SOURCES = p9_cme_main.c \
+ p9_cme_irq.c
+PSTATE-C-SOURCES = pstate_cme/p9_cme_pstate.c
+STOP-C-SOURCES = stop_cme/p9_cme_stop_irq_handlers.c \
+ stop_cme/p9_cme_stop_enter_thread.c \
+ stop_cme/p9_cme_stop_exit_thread.c \
+ stop_cme/p9_cme_stop_entry.c \
+ stop_cme/p9_cme_stop_exit.c \
+ stop_cme/p9_hcd_core_poweron.c \
+ stop_cme/p9_hcd_core_chiplet_reset.c \
+ stop_cme/p9_hcd_core_gptr_time_initf.c \
+ stop_cme/p9_hcd_core_chiplet_init.c \
+ stop_cme/p9_hcd_core_repair_initf.c \
+ stop_cme/p9_hcd_core_arrayinit.c \
+ stop_cme/p9_hcd_core_initf.c \
+ stop_cme/p9_hcd_core_startclocks.c \
+ stop_cme/p9_hcd_core_scominit.c \
+ stop_cme/p9_hcd_core_scomcust.c \
+ stop_cme/p9_hcd_core_ras_runtime_scom.c \
+ stop_cme/p9_hcd_core_occ_runtime_scom.c
+TOP-S-SOURCES =
+
+TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-S-SOURCES:.S=.o)
+PSTATE_OBJECTS = $(PSTATE-C-SOURCES:.c=.o)
+STOP_OBJECTS = $(STOP-C-SOURCES:.c=.o)
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_arrayinit.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_arrayinit.c
index ad8e25b4..018fbeb5 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_arrayinit.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_arrayinit.c
@@ -27,12 +27,12 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_arrayinit(uint8_t quad)
+p9_hcd_cache_arrayinit(uint32_t quad)
{
int rc = SGPE_STOP_SUCCESS;
#if !SKIP_SCAN0
- MARK_TRAP(SX_ARRAYINIT_SCAN0)
+ MARK_TRAP(SX_ARRAY_INIT_SCAN0)
#endif
return rc;
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_init.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_init.c
index 200d9f18..db934114 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_init.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_init.c
@@ -27,7 +27,7 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_chiplet_init(uint8_t quad)
+p9_hcd_cache_chiplet_init(uint32_t quad)
{
int rc = SGPE_STOP_SUCCESS;
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_reset.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_reset.c
index ccad9c57..f9f2393a 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_reset.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_chiplet_reset.c
@@ -27,47 +27,58 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_chiplet_reset(uint8_t quad)
+p9_hcd_cache_chiplet_reset(uint32_t quad)
{
int rc = SGPE_STOP_SUCCESS;
+ uint64_t scom_data;
- PK_TRACE("Init NETWORK_CONTROL0, step needed for hotplug");
+ PK_TRACE("Init NET_CTRL0[1-5,12-14,18,22,26],step needed for hotplug");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, quad), NET_CTRL0_INIT_VECTOR);
- PK_TRACE("Assert L3, L2-0, L2-1 Progdly, DCC Bypass and Reset");
+ PK_TRACE("Assert Progdly/DCC bypass,L2 DCC reset via NET_CTRL1[1,2,23,24]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL1_WOR, quad), (BITS64(1, 2) | BITS64(23, 2)));
- PK_TRACE("Assert Skew Adjust Reset");
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, quad), BIT64(2));
-
- PK_TRACE("Set DPLL ff_bypass to 1");
+ PK_TRACE("Assert DPLL ff_bypass via QPPM_DPLL_CTRL[2]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_DPLL_CTRL_OR, quad), BIT64(2));
- PK_TRACE("Drop Vital Thold");
+ PK_TRACE("Drop vital thold via NET_CTRL0[16]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(16));
MARK_TRAP(SX_CHIPLET_RESET_GLSMUX_RESET)
- PK_TRACE("Init Cache Glitchless Mux Reset/Select via CLOCK_GRID_CTRL[0:3]");
+ PK_TRACE("Drop L3 glsmux reset and select refclk via PPM_CGCR[0:3]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_PPM_CGCR, quad), 0);
- PK_TRACE("Init L2 Glitchless Mux Reset/Select via EXCLK_GRID_CTRL[32:33]");
+ PK_TRACE("Drop L2 glsmux reset and select refclk via QPPM_EXCGCR[32:35]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_CLR, quad), BITS64(32, 4));
- PK_TRACE("Clear PCB Endpoint Reset via NET_CTRL0[1]");
+ PK_TRACE("Assert chiplet enable via NET_CTRL0[0]");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, quad), BIT64(0));
+
+ PK_TRACE("Drop PCB endpoint reset via NET_CTRL0[1]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(1));
- PK_TRACE("Remove chiplet electrical fence via NET_CTRL0[26]");
+ PK_TRACE("Drop chiplet electrical fence via NET_CTRL0[26]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(26));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(25));
- PK_TRACE("Remove PCB fence via NET_CTRL0[25]");
+ PK_TRACE("Drop PCB fence via NET_CTRL0[25]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(25));
+ PK_TRACE("Set scan ratio to 1:1 in bypass mode via OPCG_ALIGN[47-51]");
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_OPCG_ALIGN, quad), scom_data);
+ scom_data &= ~BITS64(47, 5);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_OPCG_ALIGN, quad), scom_data);
+
#if !SKIP_SCAN0
// Marker for scan0
MARK_TRAP(SX_CHIPLET_RESET_SCAN0)
#endif
+ /// @todo scan_with_setpulse_module(l3 dcc)
+
+ PK_TRACE("Drop L3 DCC bypass via NET_CTRL1[1]");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL1_WAND, quad), ~BIT64(1));
+
+
return rc;
}
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_dpll_setup.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_dpll_setup.c
index 89da6490..f5efec7d 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_dpll_setup.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_dpll_setup.c
@@ -27,80 +27,82 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_dpll_setup(uint8_t quad)
+p9_hcd_cache_dpll_setup(uint32_t quad)
{
int rc = SGPE_STOP_SUCCESS;
- uint64_t data;
-
- // --------------
- // PRE-SCAN
- // --------------
-
- // --------------
- // DPLL SCAN
- // --------------
- /// @todo scan dpll here
-
- // --------------
- // DPLL SETUP
- // --------------
+ uint64_t scom_data;
// This is necessary to ensure that the DPLL is in Mode 1.
// If not, the lock times will go from ~30us to 3-5ms
- PK_TRACE("Ensure DPLL in Mode 1, and set slew rate to a modest value");
+ PK_TRACE("Assert DPLL in mode 1,set slew rate via QPPM_DPLL_CTRL[2,6-15]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_DPLL_CTRL_OR, quad), BIT64(2) | BIT64(8));
- PK_TRACE("Drop DPLL Test Mode and Reset");
+ PK_TRACE("Drop DPLL test mode and reset via NET_CTRL0[3,4]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BITS64(3, 2));
- PK_TRACE("Drop DPLL Clock Region Fence");
+ PK_TRACE("Drop DPLL clock region fence via NET_CTRL1[14]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL1_CLEAR, quad), BIT64(14));
- PK_TRACE("Set all bits to zero prior clock start via SCAN_REGION_TYPE");
+ PK_TRACE("Clear all bits prior start DPLL clock via SCAN_REGION_TYPE");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SCAN_REGION_TYPE, quad), 0);
- PK_TRACE("Start clock(arrays+nsl clock region) via CLK_REGION");
- data = 0x5002000000006000;
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), data);
+ PK_TRACE("Start DPLL clock(arrays+nsl clock region) via CLK_REGION");
+ scom_data = 0x4002000000006000;
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), scom_data);
- PK_TRACE("Start clock(sl+refresh clock region) via CLK_REGION");
- data = 0x500200000000E000;
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), data);
+ PK_TRACE("Start DPLL clock(sl+refresh clock region) via CLK_REGION");
+ scom_data = 0x400200000000E000;
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), scom_data);
- PK_TRACE("Polling for clocks starting via CLOCK_STAT_SL");
+ PK_TRACE("Polling for DPLL clock running via CLOCK_STAT_SL");
do
{
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, quad), data);
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, quad), scom_data);
}
- while((~data & BIT64(14)) != BIT64(14));
+ while((~scom_data & BIT64(14)) != BIT64(14));
PK_TRACE("DPLL clock is now running");
MARK_TRAP(SX_DPLL_START_DONE)
- PK_TRACE("Poll for dpll lock");
+ PK_TRACE("Poll for DPLL lock");
do
{
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_DPLL_STAT, quad), data);
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_DPLL_STAT, quad), scom_data);
break; /// @todo Skipping the lock checking until model is ready
}
- while (!(data & BIT64(63)));
+ while (!(scom_data & BIT64(63)));
- PK_TRACE("DPLL is locked");
+ PK_TRACE("DPLL is locked now");
- PK_TRACE("Take DPLL out of bypass");
+ PK_TRACE("Drop DPLL bypass via NET_CTRL0[5]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(5));
- PK_TRACE("Switch L3 glsmux select to DPLL output");
+ PK_TRACE("Flip L3 glsmux select to DPLL output via PPM_CGCR[3]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_PPM_CGCR, quad), BIT64(3));
- PK_TRACE("Switch L2 glsmux select to DPLL output");
+ PK_TRACE("Flip L2 glsmux select to DPLL output via QPPM_EXCGCR[34,35]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_OR, quad), BITS64(34, 2));
- PK_TRACE("Drop ff_bypass to switch into slew-controlled mode");
+ PK_TRACE("Drop DPLL ff_bypass via QPPM_DPLL_CTRL[2]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_DPLL_CTRL_CLEAR, quad), BIT64(2));
+ PK_TRACE("Set scan ratio to 4:1 in bypass mode via OPCG_ALIGN[47-51]");
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_OPCG_ALIGN, quad), scom_data);
+ scom_data &= ~BITS64(47, 5);
+ scom_data |= BITS64(50, 2);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_OPCG_ALIGN, quad), scom_data);
+
+ PK_TRACE("Drop ANEP clock region fence via CPLT_CTRL1[10]");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL1_CLEAR, quad), BIT64(10));
+
+ PK_TRACE("Drop skew/duty cycle adjust func_clksel via NET_CTRL0[22]");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(22));
+
+ PK_TRACE("Drop skew adjust reset via NET_CTRL0[2]");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(2));
+
return rc;
}
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_l2_startclocks.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_l2_startclocks.c
index 3a929cdc..c36b862e 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_l2_startclocks.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_l2_startclocks.c
@@ -27,12 +27,13 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_l2_startclocks(uint8_t ex, uint8_t quad)
+p9_hcd_cache_l2_startclocks(uint32_t quad, uint32_t ex)
{
int rc = SGPE_STOP_SUCCESS;
uint64_t scom_data;
- PK_TRACE("Switch L2 glsmux select to DPLL output");
+ // do this again here for stop8 in addition to dpll_setup
+ PK_TRACE("4S8: Switch L2 glsmux select to DPLL output");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_OR, quad), BITS64(34, 2));
PK_TRACE("Setup OPCG_ALIGN Register");
@@ -74,7 +75,6 @@ p9_hcd_cache_l2_startclocks(uint8_t ex, uint8_t quad)
PK_TRACE("Raise clock sync enable before switch to dpll");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_OR, quad), (ex << SHIFT64(37)));
-#if !EPM_P9_TUNING
PK_TRACE("Poll for clock sync done to raise");
do
@@ -83,7 +83,7 @@ p9_hcd_cache_l2_startclocks(uint8_t ex, uint8_t quad)
}
while(!(scom_data & (ex << SHIFT64(37))));
-#endif
+ MARK_TRAP(SX_L2_STARTCLOCKS_GRID)
// -------------------------------
// Start L2 Clock
@@ -93,11 +93,11 @@ p9_hcd_cache_l2_startclocks(uint8_t ex, uint8_t quad)
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SCAN_REGION_TYPE, quad), 0);
PK_TRACE("Start clock(arrays+nsl clock region) via CLK_REGION");
- scom_data = 0x5000000000006000 | ((uint64_t)ex << SHIFT64(9));
+ scom_data = 0x4000000000006000 | ((uint64_t)ex << SHIFT64(9));
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), scom_data);
PK_TRACE("Start clock(sl+refresh clock region) via CLK_REGION");
- scom_data = 0x500000000000E000 | ((uint64_t)ex << SHIFT64(9));
+ scom_data = 0x400000000000E000 | ((uint64_t)ex << SHIFT64(9));
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), scom_data);
PK_TRACE("Polling for clocks starting via CLOCK_STAT_SL");
@@ -116,19 +116,28 @@ p9_hcd_cache_l2_startclocks(uint8_t ex, uint8_t quad)
if (ex & FST_EX_IN_QUAD)
{
- GPE_PUTSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_SICR_CLR, quad, 1), BIT64(21));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_SICR_CLR, quad, 0), BIT64(21));
}
if (ex & SND_EX_IN_QUAD)
{
- GPE_PUTSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_SICR_CLR, quad, 2), BIT64(21));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_CME(CME_SCOM_SICR_CLR, quad, 1), BIT64(21));
}
PK_TRACE("Clear flushmode_inhibit via CPLT_CTRL0[2]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL0_CLEAR, quad), BIT64(2));
PK_TRACE("Drop L2 Snoop Disable");
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_L2_RCMD_DIS_REG, quad, ex), 0);
+
+ if (ex & FST_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_L2_RCMD_DIS_REG, quad, 0), 0);
+ }
+
+ if (ex & SND_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_L2_RCMD_DIS_REG, quad, 1), 0);
+ }
return rc;
}
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_occ_runtime_scom.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_occ_runtime_scom.c
index b854f2c4..e56de266 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_occ_runtime_scom.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_occ_runtime_scom.c
@@ -27,7 +27,7 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_occ_runtime_scom(uint8_t quad)
+p9_hcd_cache_occ_runtime_scom(uint32_t quad)
{
return 0;
}
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_poweron.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_poweron.c
index 8427eaf6..c6a979df 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_poweron.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_poweron.c
@@ -27,32 +27,30 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_poweron(uint8_t quad)
+p9_hcd_cache_poweron(uint32_t quad)
{
int rc = SGPE_STOP_SUCCESS;
- PK_TRACE("Set L3 glsmux reset via CLOCK_GRID_CTRL[0]");
+ PK_TRACE("Drop chiplet enable via NET_CTRL0[0]");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(0));
+
+ PK_TRACE("Assert PCB fence via NET_CTRL0[25]");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, quad), BIT64(25));
+
+ PK_TRACE("Assert chiplet electrical fence via NET_CTRL0[26]");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, quad), BIT64(26));
+
+ PK_TRACE("Assert vital thold via NET_CTRL0[16]");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, quad), BIT64(16));
+
+ PK_TRACE("Assert L3 glsmux reset via PPM_CGCR[0]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_PPM_CGCR, quad), BIT64(0));
- PK_TRACE("Set L2 glsmux reset via EXCLK_GRID_CTRL[32:33]");
+ PK_TRACE("Assert L2 glsmux reset via QPPM_EXCGCR[32:33]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_OR, quad), BITS64(32, 2));
- PK_TRACE("Set DPLL ff_bypass via EQ_QPPM_DPLL_CTRL[2]");
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(QPPM_DPLL_CTRL_OR, quad), BIT64(2));
-
#if !STOP_PRIME
uint64_t scom_data;
-#if !EPM_P9_TUNNING
- // vdd_pfet_force_state == 00 (Nop)
- PK_TRACE("Make sure we are not forcing PFET for VDD off");
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, quad), scom_data);
-
- if (scom_data & BITS64(0, 2))
- {
- return SGPE_STOP_ENTRY_VDD_PFET_NOT_IDLE;
- }
-
-#endif
// vdd_pfet_val/sel_override = 0 (disbaled)
// vcs_pfet_val/sel_override = 0 (disbaled)
@@ -87,21 +85,12 @@ p9_hcd_cache_poweron(uint8_t quad)
MARK_TRAP(SX_POWERON_DONE)
-#if !EPM_P9_TUNNING
- PK_TRACE("Optional: Poll for vdd_pg_sel being: 0x0");
-
- do
- {
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, quad), scom_data);
- }
- while(scom_data & BIT64(46));
-
- MARK_TRAP(SX_POWERON_PG_SEL)
-#endif
-
// vdd_pfet_force_state = 00 (Nop)
+ // vcs_pfet_force_state = 00 (Nop)
PK_TRACE("Turn Off Force Von");
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_CLR, quad), BITS64(0, 2));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_CLR, quad), BITS64(0, 4));
+
#endif
+
return rc;
}
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_ras_runtime_scom.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_ras_runtime_scom.c
index 29878251..f207ceea 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_ras_runtime_scom.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_ras_runtime_scom.c
@@ -27,7 +27,7 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_ras_runtime_scom(uint8_t quad)
+p9_hcd_cache_ras_runtime_scom(uint32_t quad)
{
return 0;
}
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scomcust.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scomcust.c
index 5f5a2c99..d125dc7e 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scomcust.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scomcust.c
@@ -27,7 +27,7 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_scomcust(uint8_t quad)
+p9_hcd_cache_scomcust(uint32_t quad)
{
int rc = SGPE_STOP_SUCCESS;
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scominit.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scominit.c
index f9367265..ac43bda5 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scominit.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_scominit.c
@@ -27,7 +27,7 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_scominit(uint8_t quad)
+p9_hcd_cache_scominit(uint32_t quad)
{
int rc = SGPE_STOP_SUCCESS;
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_startclocks.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_startclocks.c
index 00d5e21e..fbb2c264 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_startclocks.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_hcd_cache_startclocks.c
@@ -27,46 +27,50 @@
#include "p9_sgpe_stop_exit_marks.h"
int
-p9_hcd_cache_startclocks(uint8_t quad)
+p9_hcd_cache_startclocks(uint32_t quad, uint32_t ex)
{
int rc = SGPE_STOP_SUCCESS;
- uint64_t data, loop;
+ uint64_t scom_data, loop;
// -------------------------------
// Prepare to cache startclocks
// -------------------------------
- PK_TRACE("Enable L3 EDRAM/LCO setup on both EXs");
- //DD:GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, quad), BIT64(23) | BIT64(24));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, quad), BIT64(23));
+ PK_TRACE("Sequence EX-L3 EDRAM enables via QPPM_QCCR[0-7]");
// 0x0 -> 0x8 -> 0xC -> 0xE -> 0xF to turn on edram
// stagger EDRAM turn-on per EX (not both at same time)
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(0));
- PPE_WAIT_CORE_CYCLES(loop, 100);
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(1));
- PPE_WAIT_CORE_CYCLES(loop, 100);
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(2));
- PPE_WAIT_CORE_CYCLES(loop, 100);
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(3));
- PPE_WAIT_CORE_CYCLES(loop, 100);
- /* DD:
+ if (ex & FST_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(0));
+ //PPE_WAIT_CORE_CYCLES(loop, 48000);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(1));
+ //PPE_WAIT_CORE_CYCLES(loop, 4000);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(2));
+ //PPE_WAIT_CORE_CYCLES(loop, 16000);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(3));
+ //PPE_WAIT_CORE_CYCLES(loop, 4000);
+ }
+
+ if (ex & SND_EX_IN_QUAD)
+ {
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(4));
- PPE_WAIT_CORE_CYCLES(loop, 100);
+ //PPE_WAIT_CORE_CYCLES(loop, 100);
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(5));
- PPE_WAIT_CORE_CYCLES(loop, 100);
+ //PPE_WAIT_CORE_CYCLES(loop, 100);
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(6));
- PPE_WAIT_CORE_CYCLES(loop, 100);
+ //PPE_WAIT_CORE_CYCLES(loop, 100);
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WOR, quad), BIT64(7));
- PPE_WAIT_CORE_CYCLES(loop, 100);
- */
- PK_TRACE("Setup OPCG_ALIGN Register");
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_OPCG_ALIGN, quad), data);
- data = data & ~(BITS64(0, 4) & BITS64(12, 8) & BITS64(52, 12));
- data = data | (BIT64(1) | BIT64(3) | BIT64(59));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_OPCG_ALIGN, quad), data);
-
- PK_TRACE("Drop partial good fences via CPLT_CTRL1");
+ //PPE_WAIT_CORE_CYCLES(loop, 100);
+ }
+
+ PK_TRACE("Set inop_align/wait/wait_cycles via OPCG_ALIGN[0-3,12-19,52-63]");
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_OPCG_ALIGN, quad), scom_data);
+ scom_data = scom_data & ~(BITS64(0, 4) & BITS64(12, 8) & BITS64(52, 12));
+ scom_data = scom_data | (BIT64(1) | BIT64(3) | BIT64(59));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_OPCG_ALIGN, quad), scom_data);
+
+ PK_TRACE("Drop partial good fences via CPLT_CTRL1[3-14]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL1_CLEAR, quad),
0xFFFF700000000000);
@@ -80,60 +84,60 @@ p9_hcd_cache_startclocks(uint8_t quad)
// align_chiplets()
- PK_TRACE("Set flushmode_inhibit via CPLT_CTRL0[2]");
+ PK_TRACE("Assert flushmode_inhibit via CPLT_CTRL0[2]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL0_OR, quad), BIT64(2));
- PK_TRACE("Set force_align via CPLT_CTRL0[3]");
+ PK_TRACE("Assert force_align via CPLT_CTRL0[3]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL0_OR, quad), BIT64(3));
- PK_TRACE("Set/Unset clear_chiplet_is_aligned via SYNC_CONFIG[7]");
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_SYNC_CONFIG, quad), data);
- data = data | BIT64(7);
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SYNC_CONFIG, quad), data);
- data = data & ~BIT64(7);
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SYNC_CONFIG, quad), data);
+ PK_TRACE("Set then unset clear_chiplet_is_aligned via SYNC_CONFIG[7]");
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_SYNC_CONFIG, quad), scom_data);
+ scom_data = scom_data | BIT64(7);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SYNC_CONFIG, quad), scom_data);
+ scom_data = scom_data & ~BIT64(7);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SYNC_CONFIG, quad), scom_data);
PK_TRACE("Check chiplet_is_aligned");
do
{
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_STAT0, quad), data);
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_STAT0, quad), scom_data);
}
- while(~data & BIT64(9));
+ while(~scom_data & BIT64(9));
- PK_TRACE("Clear force_align via CPLT_CTRL0[3]");
+ PK_TRACE("Drop force_align via CPLT_CTRL0[3]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL0_CLEAR, quad), BIT64(3));
+ PPE_WAIT_CORE_CYCLES(loop, 450);
// -------------------------------
// Start L3 Clock
// -------------------------------
- PK_TRACE("Set all bits to zero prior clock start via SCAN_REGION_TYPE");
+ PK_TRACE("Clear all bits prior start cache clocks via SCAN_REGION_TYPE");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SCAN_REGION_TYPE, quad), 0);
- PK_TRACE("Start clock(arrays+nsl clock region) via CLK_REGION");
- //DD: data = 0x5F3C000000006000;
- data = 0x5E3C000000006000;
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), data);
+ PK_TRACE("Start cache clocks(arrays+nsl clock region) via CLK_REGION");
+ scom_data = 0x4C3C000000006000 | ((uint64_t)ex << SHIFT64(7));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), scom_data);
- PK_TRACE("Start clock(sl+refresh clock region) via CLK_REGION");
- //DD: data = 0x5F3C00000000E000;
- data = 0x5E3C00000000E000;
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), data);
+ PK_TRACE("Start cache clocks(sl+refresh clock region) via CLK_REGION");
+ scom_data = 0x4C3C00000000E000 | ((uint64_t)ex << SHIFT64(7));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, quad), scom_data);
// Read Clock Status Register (Cache chiplet)
// check for bits 4:14 eq. zero, no tholds on
- PK_TRACE("Poll for L3 clock running");
+ PK_TRACE("Poll for cache clocks running");
do
{
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, quad), data);
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, quad), scom_data);
}
+ while((scom_data &
+ (BITS64(4, 2) | ((uint64_t)ex << SHIFT64(7)) | BITS64(10, 4))) != 0);
- //while((~data & (BITS64(4, 3) | BITS64(10, 4))) != (BITS64(4, 3) | BITS64(10, 4)));
- while((~data & (BITS64(4, 3) | BITS64(10, 4))) != (BITS64(4, 3) | BITS64(10, 4)));
+ PK_TRACE("Cache clocks running now");
- PK_TRACE("L3 clock running now");
+ MARK_TRAP(SX_CACHE_STARTCLOCKS_DONE)
// @todo
// deskew_init()
@@ -145,23 +149,39 @@ p9_hcd_cache_startclocks(uint8_t quad)
PK_TRACE("Drop chiplet fence via NET_CTRL0[18]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(18));
- //PK_TRACE("Drop fence to allow PCB operations to chiplet via NET_CTRL0[25]");
- //GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WAND, quad), ~BIT64(25));
-
/// @todo Check the Global Checkstop FIR of dedicated EX chiplet
- PK_TRACE("Clear flushmode_inhibit via CPLT_CTRL0[2]");
+ PK_TRACE("Drop flushmode_inhibit via CPLT_CTRL0[2]");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL0_CLEAR, quad), BIT64(2));
- uint32_t ex = 2;
PK_TRACE("Drop refresh quiesce");
- GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, quad, ex), data);
- data &= ~BIT64(7);
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, quad, ex), data);
+
+ if (ex & FST_EX_IN_QUAD)
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, quad, 0), scom_data);
+ scom_data &= ~BIT64(7);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, quad, 0), scom_data);
+ }
+
+ if (ex & SND_EX_IN_QUAD)
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, quad, 1), scom_data);
+ scom_data &= ~BIT64(7);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, quad, 1), scom_data);
+ }
PK_TRACE("Drop LCO Disable");
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG, quad, ex), 0);
+
+ if (ex & FST_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG, quad, 0), 0);
+ }
+
+ if (ex & SND_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG, quad, 1), 0);
+ }
return rc;
}
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
index e2a644c9..8c329801 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop.h
@@ -81,6 +81,7 @@
#define EQ_QPPM_QCCR_WCLEAR 0x100F01BE
#define EQ_QPPM_QCCR_WOR 0x100F01BF
+#define EX_NCU_STATUS_REG 0x1001100F
#define EX_DRAM_REF_REG 0x1001180F
#define EX_PM_PURGE_REG 0x10011813
#define EX_PM_LCO_DIS_REG 0x10011816
@@ -99,18 +100,15 @@
hist.fields.act_write_enable = act_e; \
GPE_PUTSCOM_VAR(PPM_SSHSRC, base, id, 0, hist.value);
-
enum SGPE_STOP_RETURN_CODES
{
- SGPE_STOP_SUCCESS = 0,
- SGPE_STOP_RECEIVE_WRONG_PM_STATE = 0x00747301,
- SGPE_STOP_ENTRY_VDD_PFET_NOT_IDLE = 0x00747302
+ SGPE_STOP_SUCCESS = 0
};
enum SGPE_STOP_IRQ_SHORT_NAMES
{
IRQ_STOP_TYPE2 = OCCHW_IRQ_PMC_PCB_INTR_TYPE2_PENDING,
- IRQ_STOP_TYPE5 = OCCHW_IRQ_PMC_PCB_INTR_TYPE5_PENDING,
+ IRQ_STOP_TYPE3 = OCCHW_IRQ_PMC_PCB_INTR_TYPE3_PENDING,
IRQ_STOP_TYPE6 = OCCHW_IRQ_PMC_PCB_INTR_TYPE6_PENDING
};
@@ -132,64 +130,50 @@ enum SGPE_STOP_EVENT_FLAGS
SGPE_EXIT_FLAG = 1
};
-typedef union sgpe_level
-{
- uint16_t qlevel;
- struct
- {
- uint8_t x0lv : 8;
- uint8_t x1lv : 8;
- } xlevel;
- struct
- {
- uint8_t c0lv : 4;
- uint8_t c1lv : 4;
- uint8_t c2lv : 4;
- uint8_t c3lv : 4;
- } clevel;
-} sgpe_level_t;
-
-typedef union sgpe_state
+typedef struct
{
- uint32_t status;
- struct
- {
- uint8_t spare0 : 4;
- uint8_t q_req : 4;
- uint8_t x0req : 4;
- uint8_t x1req : 4;
- uint8_t spare1 : 4;
- uint8_t q_act : 4;
- uint8_t x0act : 4;
- uint8_t x1act : 4;
- } detail;
+ // requested stop state calculated from core stop levels
+ uint8_t req_state_x0;
+ uint8_t req_state_x1;
+ uint8_t req_state_q;
+ // actual stop state
+ uint8_t act_state_x0;
+ uint8_t act_state_x1;
+ uint8_t act_state_q;
} sgpe_state_t;
-typedef union sgpe_group
+typedef struct
{
- uint64_t vector[2];
- struct
- {
- uint32_t c_out;
- uint16_t x_out;
- uint16_t q_out;
- uint32_t c_in;
- uint16_t x_in;
- uint16_t q_in;
- } member;
+ uint32_t entry_x0;
+ uint32_t entry_x1;
+ uint32_t entry_x;
+ uint32_t entry_q;
+ uint32_t entry_c;
+ uint32_t exit_x0;
+ uint32_t exit_x1;
+ uint32_t exit_x;
+ uint32_t exit_q;
+ uint32_t exit_c;
+ uint32_t good_x0;
+ uint32_t good_x1;
+ uint32_t good_x;
+ uint32_t good_q;
+ uint32_t good_c;
} sgpe_group_t;
-
/// SGPE Stop Score Board Structure
typedef struct
{
- sgpe_group_t group;
+ // requested stop level for all cores in all quads
+ // needs to be global variable for ex/quad stop evaluation
+ uint8_t level[MAX_QUADS][CORES_PER_QUAD];
+ // requested and actual state of quad stop
sgpe_state_t state[MAX_QUADS];
- sgpe_level_t level[MAX_QUADS];
+ // group of ex and quad entering or exiting the stop
+ sgpe_group_t group;
PkSemaphore sem[2];
} SgpeStopRecord;
-
/// SGPE STOP Entry and Exit Prototypes
void p9_sgpe_stop_pig_type2_handler(void*, PkIrqId);
void p9_sgpe_stop_enter_thread(void*);
@@ -197,17 +181,17 @@ void p9_sgpe_stop_exit_thread(void*);
int p9_sgpe_stop_entry();
int p9_sgpe_stop_exit();
-int p9_hcd_cache_poweron(uint8_t);
-int p9_hcd_cache_chiplet_reset(uint8_t);
-int p9_hcd_cache_gptr_time_initf(uint8_t);
-int p9_hcd_cache_dpll_setup(uint8_t);
-int p9_hcd_cache_chiplet_init(uint8_t);
-int p9_hcd_cache_repair_initf(uint8_t);
-int p9_hcd_cache_arrayinit(uint8_t);
-int p9_hcd_cache_initf(uint8_t);
-int p9_hcd_cache_startclocks(uint8_t);
-int p9_hcd_cache_l2_startclocks(uint8_t, uint8_t);
-int p9_hcd_cache_scominit(uint8_t);
-int p9_hcd_cache_scomcust(uint8_t);
-int p9_hcd_cache_ras_runtime_scom(uint8_t);
-int p9_hcd_cache_occ_runtime_scom(uint8_t);
+int p9_hcd_cache_poweron(uint32_t);
+int p9_hcd_cache_chiplet_reset(uint32_t);
+int p9_hcd_cache_gptr_time_initf(uint32_t);
+int p9_hcd_cache_dpll_setup(uint32_t);
+int p9_hcd_cache_chiplet_init(uint32_t);
+int p9_hcd_cache_repair_initf(uint32_t);
+int p9_hcd_cache_arrayinit(uint32_t);
+int p9_hcd_cache_initf(uint32_t);
+int p9_hcd_cache_startclocks(uint32_t, uint32_t);
+int p9_hcd_cache_l2_startclocks(uint32_t, uint32_t);
+int p9_hcd_cache_scominit(uint32_t);
+int p9_hcd_cache_scomcust(uint32_t);
+int p9_hcd_cache_ras_runtime_scom(uint32_t);
+int p9_hcd_cache_occ_runtime_scom(uint32_t);
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_enter_marks.h b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_enter_marks.h
index 6e86ea67..e928d987 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_enter_marks.h
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_enter_marks.h
@@ -45,8 +45,8 @@ enum SGPE_SE_MARKS
SE_PURGE_L3_ABORT_DONE = 0x30,
SE_PURGE_PB = 0x38,
SE_WAIT_PGPE_SUSPEND = 0x40,
- SE_STOP_CACHE_CLKS = 0x48,
- SE_STOP_CACHE_CLKS_DONE = 0x50,
+ SE_QUIESCE_QUAD = 0x48,
+ SE_STOP_CACHE_CLKS = 0x50,
SE_POWER_OFF_CACHE = 0x68,
SE_STOP11_DONE = 0xe0,
BEGINSCOPE_STOP_ENTRY = 0x1f08,
@@ -68,8 +68,8 @@ const std::vector<SGPE_SE_MARKS> MARKS =
SE_PURGE_L3_ABORT_DONE,
SE_PURGE_PB,
SE_WAIT_PGPE_SUSPEND,
+ SE_QUIESCE_QUAD,
SE_STOP_CACHE_CLKS,
- SE_STOP_CACHE_CLKS_DONE,
SE_POWER_OFF_CACHE,
SE_STOP11_DONE,
BEGINSCOPE_STOP_ENTRY,
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c
index ba3453f7..6a554b4e 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_entry.c
@@ -31,234 +31,253 @@ extern SgpeStopRecord G_sgpe_stop_record;
int
p9_sgpe_stop_entry()
{
- int rc;
- uint8_t ex;
- uint8_t qloop;
- uint8_t cloop;
- uint8_t climit;
- uint16_t qentry;
- uint16_t xentry;
- uint8_t entry_ongoing[2] = {0, 0};
- uint8_t l3_purge_aborted = 0;
+ int entry_ongoing[2] = {0, 0};
+ int l3_purge_aborted = 0;
+ int rc = 0;
+ uint32_t ex = 0;
+ uint32_t qloop;
+ uint32_t cloop;
+ uint32_t climit;
+ uint32_t xentry;
+ uint32_t qentry;
uint32_t loop;
uint64_t scom_data;
ppm_sshsrc_t hist;
- //===================================================================
- MARK_TAG(BEGINSCOPE_STOP_ENTRY, (G_sgpe_stop_record.group.member.q_in >> 10))
- //===================================================================
+ //================================
+ MARK_TAG(BEGINSCOPE_STOP_ENTRY, 0)
+ //================================
- if (G_sgpe_stop_record.group.member.q_in)
+ if (G_sgpe_stop_record.group.entry_q)
+ {
MARK_TRAP(SE_STOP_SUSPEND_PSTATE)
+ }
- //TODO: message pgpe to suspend Pstate
-
- // ------------------------------------------------------------------------
- // EX STOP ENTRY
- // ------------------------------------------------------------------------
+ //TODO: message pgpe to suspend Pstate only if stop level >= 8
- for(xentry = G_sgpe_stop_record.group.member.x_in, qloop = 0;
- xentry > 0;
- xentry = xentry << 2, qloop++)
+ // ------------------------------------------------------------------------
+ // EX STOP ENTRY [LEVEL 8-10]
+ // ------------------------------------------------------------------------
+ // only stop 8 sets x_in
+ for(xentry = G_sgpe_stop_record.group.entry_x, qloop = 0;
+ xentry > 0;
+ xentry = xentry << 2, qloop++)
+ {
+ // if this ex is not up to entry, skip
+ if (!(ex = ((xentry & BITS32(0, 2)) >> SHIFT32(1))))
{
- // if this ex is not up to entry, skip
- if (!(ex = ((xentry & BITS16(0, 2)) >> SHIFT16(1))))
- {
- continue;
- }
+ continue;
+ }
- PK_TRACE("q[%d]exmask[%d] starts entry", qloop, ex);
+ PK_TRACE("q[%d]exmask[%d] starts entry", qloop, ex);
- //-------------------------------------------------------------------------
- // STOP LEVEL 8
- //-------------------------------------------------------------------------
+ // Update QSSR: stop_entry_ongoing
+ out32(OCB_QSSR_OR, BIT32(qloop + 20));
- // Update QSSR: stop_entry_ongoing
- out32(OCB_QSSR_OR, BIT32(qloop + 20));
+ // Update History for ongoing stop 8 entry
+ cloop = (ex & FST_EX_IN_QUAD) ? 0 : CORES_PER_EX;
+ climit = (ex & SND_EX_IN_QUAD) ? CORES_PER_QUAD : CORES_PER_EX;
+
+ for(; cloop < climit; cloop++)
+ {
+ SGPE_STOP_UPDATE_HISTORY(((qloop << 2) + cloop),
+ CORE_ADDR_BASE,
+ STOP_CORE_IS_GATED,
+ STOP_TRANS_ENTRY,
+ STOP_LEVEL_8,
+ STOP_LEVEL_8,
+ STOP_REQ_DISABLE,
+ STOP_ACT_DISABLE);
+ }
- // Update History for ongoing stop 8 entry
- cloop = (ex & FST_EX_IN_QUAD) ? 0 : CORES_PER_EX;
- climit = (ex & SND_EX_IN_QUAD) ? CORES_PER_QUAD : CORES_PER_EX;
+ //====================================================
+ MARK_TAG(SE_STOP_L2_CLKS, ((ex << 6) | (32 >> qloop)))
+ //====================================================
- for(; cloop < climit; cloop++)
- {
- SGPE_STOP_UPDATE_HISTORY(((qloop << 2) + cloop),
- CORE_ADDR_BASE,
- STOP_CORE_IS_GATED,
- STOP_TRANS_ENTRY,
- STOP_LEVEL_8,
- STOP_LEVEL_8,
- STOP_REQ_DISABLE,
- STOP_ACT_DISABLE);
- }
+ PK_TRACE("SE8.a");
- //========================
- MARK_TRAP(SE_STOP_L2_CLKS)
- //========================
+ // Disable L2 Snoop(quiesce L2-L3 interface, what about NCU?)
+ if (ex & FST_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_L2_RCMD_DIS_REG, qloop, 0),
+ BIT64(0));
- PK_TRACE("SE8.a");
- // Assert L2 Regional Fences
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL1_OR, qloop),
- ((uint64_t)ex << SHIFT64(9)));
- // Disable L2 Snoop(quiesce L2-L3 interface, what about NCU?)
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_L2_RCMD_DIS_REG, qloop, ex), BIT64(0));
- PPE_WAIT_CORE_CYCLES(loop, 256)
+ if (ex & SND_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_L2_RCMD_DIS_REG, qloop, 1),
+ BIT64(0));
- PK_TRACE("SE8.b");
- // Set all bits to zero prior stop core clocks
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SCAN_REGION_TYPE, qloop), 0);
+ PPE_WAIT_CORE_CYCLES(loop, 256)
- PK_TRACE("SE8.c");
- // Stop L2 Clocks
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop),
- (0x900000000000E000 | ((uint64_t)ex << SHIFT64(9))));
+ PK_TRACE("SE8.b");
+ // Set all bits to zero prior stop cache clocks
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_SCAN_REGION_TYPE, qloop), 0);
- PK_TRACE("SE8.d");
+ PK_TRACE("SE8.c");
+ // Stop L2 Clocks
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop),
+ (0x800000000000E000 | ((uint64_t)ex << SHIFT64(9))));
- // Poll for L2 clocks stopped
- do
- {
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, qloop), scom_data);
- }
- while(((scom_data >> SHIFT64(9)) & ex) != ex);
+ PK_TRACE("SE8.d");
- // MF: verify compiler generate single rlwmni
- // MF: delay may be needed for stage latch to propagate thold
+ // Poll for L2 clocks stopped
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, qloop), scom_data);
+ }
+ while(((scom_data >> SHIFT64(9)) & ex) != ex);
- PK_TRACE("SE8: L2 Clock Stopped");
+ // MF: verify compiler generate single rlwmni
+ // MF: delay may be needed for stage latch to propagate thold
- //========================
- MARK_TRAP(SE_STOP_L2_GRID)
- //========================
+ PK_TRACE("SE8: L2 Clock Stopped");
- PK_TRACE("SE8.e");
- // Drop clock sync enable before switch to refclk
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_CLR, qloop),
- (ex << SHIFT64(37)));
+ //========================
+ MARK_TRAP(SE_STOP_L2_GRID)
+ //========================
-#if !EPM_P9_TUNING
- PK_TRACE("SE8.f");
+ PK_TRACE("SE8.e");
+ // Drop clock sync enable before switch to refclk
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_CLR, qloop),
+ ((uint64_t)ex << SHIFT64(37)));
- // Poll for clock sync done to drop
- do
- {
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(QPPM_QACSR, qloop), scom_data);
- }
- while((~scom_data >> SHIFT64(37)) & ex != ex);
+ PK_TRACE("SE8.f");
-#endif
+ // Poll for clock sync done to drop
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(QPPM_QACSR, qloop), scom_data);
+ }
+ while(((~scom_data >> SHIFT64(37)) & ex) != ex);
- PK_TRACE("SE8.g");
- // Switch glsmux to refclk to save clock grid power
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_CLR, qloop),
- (ex << SHIFT64(35)));
+ PK_TRACE("SE8.g");
+ // Switch glsmux to refclk to save clock grid power
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_EXCGCR_CLR, qloop),
+ ((uint64_t)ex << SHIFT64(35)));
- PK_TRACE("SE8.h");
+ PK_TRACE("SE8.h");
- if (ex & FST_EX_IN_QUAD)
- {
- cloop = 0;
- G_sgpe_stop_record.state[qloop].detail.x0act = STOP_LEVEL_8;
- entry_ongoing[0] =
- G_sgpe_stop_record.state[qloop].detail.x0req == STOP_LEVEL_8 ?
- STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
- }
- else
- {
- cloop = CORES_PER_EX;
- }
+ if (ex & FST_EX_IN_QUAD)
+ {
+ cloop = 0;
+ G_sgpe_stop_record.state[qloop].act_state_x0 = STOP_LEVEL_8;
+ entry_ongoing[0] =
+ G_sgpe_stop_record.state[qloop].req_state_x0 == STOP_LEVEL_8 ?
+ STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
+ }
+ else
+ {
+ cloop = CORES_PER_EX;
+ }
- if (ex & SND_EX_IN_QUAD)
- {
- climit = CORES_PER_QUAD;
- G_sgpe_stop_record.state[qloop].detail.x1act = STOP_LEVEL_8;
- entry_ongoing[1] =
- G_sgpe_stop_record.state[qloop].detail.x0req == STOP_LEVEL_8 ?
- STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
- }
- else
- {
- climit = CORES_PER_EX;
- }
+ if (ex & SND_EX_IN_QUAD)
+ {
+ climit = CORES_PER_QUAD;
+ G_sgpe_stop_record.state[qloop].act_state_x1 = STOP_LEVEL_8;
+ entry_ongoing[1] =
+ G_sgpe_stop_record.state[qloop].req_state_x0 == STOP_LEVEL_8 ?
+ STOP_TRANS_COMPLETE : STOP_TRANS_ENTRY;
+ }
+ else
+ {
+ climit = CORES_PER_EX;
+ }
- for(; cloop < climit; cloop++)
- {
- SGPE_STOP_UPDATE_HISTORY(((qloop << 2) + cloop),
- CORE_ADDR_BASE,
- STOP_CORE_IS_GATED,
- entry_ongoing[cloop >> 1],
- STOP_LEVEL_8,
- STOP_LEVEL_8,
- STOP_REQ_DISABLE,
- STOP_ACT_ENABLE);
- }
+ for(; cloop < climit; cloop++)
+ {
+ // request levle already set by CME
+ // shift by 2 == times 4, which is cores per quad
+ SGPE_STOP_UPDATE_HISTORY(((qloop << 2) + cloop),
+ CORE_ADDR_BASE,
+ STOP_CORE_IS_GATED,
+ entry_ongoing[cloop >> 1],
+ STOP_LEVEL_8,
+ STOP_LEVEL_8,
+ STOP_REQ_DISABLE,
+ STOP_ACT_ENABLE);
+ }
- // Update QSSR: l2_stopped, drop stop_entry_ongoing
- out32(OCB_QSSR_OR, (ex << SHIFT32((qloop << 1) + 1)) | BIT32(qloop + 20));
+ // Update QSSR: l2_stopped, entry_ongoing = 0
+ out32(OCB_QSSR_CLR, BIT32(qloop + 20));
+ out32(OCB_QSSR_OR, (ex << SHIFT32((qloop << 1) + 1)));
- //=================================================
- MARK_TAG(SE_STOP8_DONE, ((ex << 6) | (32 >> qloop)))
- //=================================================
+ //==================================================
+ MARK_TAG(SE_STOP8_DONE, ((ex << 6) | (32 >> qloop)))
+ //==================================================
- };
+ };
// ------------------------------------------------------------------------
- // QUAD STOP ENTRY
+ // QUAD STOP ENTRY [LEVEL 11-15]
// ------------------------------------------------------------------------
- for(qentry = G_sgpe_stop_record.group.member.q_in, qloop = 0;
+ for(qentry = G_sgpe_stop_record.group.entry_q, qloop = 0;
qentry > 0;
qentry = qentry << 1, qloop++)
{
- PK_TRACE("q[%x] starts entry", qentry);
-
// if this quad is not up to entry, skip
- if (!(qentry & BIT16(0)))
+ if (!(qentry & BIT32(0)))
{
continue;
}
- PK_TRACE("q[%d] starts entry", qloop);
+ if (G_sgpe_stop_record.group.good_x0 & BIT32(qloop))
+ {
+ ex |= FST_EX_IN_QUAD;
+ }
+
+ if (G_sgpe_stop_record.group.good_x1 & BIT32(qloop))
+ {
+ ex |= SND_EX_IN_QUAD;
+ }
+
+ PK_TRACE("q[%d]x[%d] starts quad entry", qloop, ex);
// Update QSSR: stop_entry_ongoing
out32(OCB_QSSR_OR, BIT32(qloop + 20));
- // Update STOP History
+ // Update Quad STOP History
SGPE_STOP_UPDATE_HISTORY(qloop,
QUAD_ADDR_BASE,
STOP_CORE_IS_GATED,
STOP_TRANS_ENTRY,
- G_sgpe_stop_record.state[qloop].detail.q_req,
+ G_sgpe_stop_record.state[qloop].req_state_q,
STOP_LEVEL_11,
STOP_REQ_ENABLE,
STOP_ACT_DISABLE);
- // ------------------------------------------------------------------------
- // STOP LEVEL 11.A
- //-------------------------------------------------------------------------
-
- //=================================
+ //==================================
MARK_TAG(SE_PURGE_L3, (32 >> qloop))
- //=================================
-
- ex = 2;
+ //==================================
PK_TRACE("SE11.a");
+
// Disable LCO prior to purge
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG, qloop, ex), BIT64(0));
+ if(ex & FST_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG, qloop, 0),
+ BIT64(0));
+ }
+
+ if(ex & SND_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG, qloop, 1),
+ BIT64(0));
+ }
#if !SKIP_L3_PURGE
PK_TRACE("SE11.b");
+
// Assert Purge L3
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, ex), BIT64(0));
+ if(ex & FST_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, 0), BIT64(0));
+ }
+
+ if(ex & SND_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, 1), BIT64(0));
+ }
- // PK_TRACE("SE11.c");
- // No need: Assert chtm purges
// todo: stop debug trace, attribute may be needed
- //GPE_PUTSCOM(CME_SCOM_SICR_OR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX0,
- // qloop, BIT64(24)|BIT64(25));
- //GPE_PUTSCOM(CME_SCOM_SICR_OR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX1,
- // qloop, BIT64(24)|BIT64(25));
PK_TRACE("SE11.d");
@@ -273,27 +292,62 @@ p9_sgpe_stop_entry()
{
for(cloop = 0; cloop < CORES_PER_QUAD; cloop++)
{
+ // todo type3
if (in32(OCB_OPIT2CN(((qloop << 2) + cloop))) &
TYPE2_PAYLOAD_STOP_EVENT)
{
- MARK_TRAP(SE_PURGE_L3_ABORT)
+
+ //========================================
+ MARK_TAG(SE_PURGE_L3_ABORT, (32 >> qloop))
+ //========================================
+
// Assert Purge L3 Abort
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG,
- qloop, ex), BIT64(2));
+ if (ex & FST_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG,
+ qloop, 0),
+ BIT64(2));
+
+ if (ex & SND_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG,
+ qloop, 1),
+ BIT64(2));
// Poll for Abort Done
- do
+ if(ex & FST_EX_IN_QUAD)
{
- GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG,
- qloop, ex), scom_data);
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(
+ EX_PM_PURGE_REG,
+ qloop, 0), scom_data);
+ }
+ while(scom_data & (BIT64(0) | BIT64(2)));
}
- while(scom_data & (BIT64(0) | BIT64(2)));
- MARK_TRAP(SE_PURGE_L3_ABORT_DONE)
+ if(ex & SND_EX_IN_QUAD)
+ {
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(
+ EX_PM_PURGE_REG,
+ qloop, 1), scom_data);
+ }
+ while(scom_data & (BIT64(0) | BIT64(2)));
+ }
+
+ //=============================================
+ MARK_TAG(SE_PURGE_L3_ABORT_DONE, (32 >> qloop))
+ //=============================================
// Deassert LCO Disable
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG,
- qloop, ex), 0);
+ if(ex & FST_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG,
+ qloop, 0), 0);
+
+ if(ex & SND_EX_IN_QUAD)
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_PM_LCO_DIS_REG,
+ qloop, 1), 0);
+
// Notify PGPE to resume
l3_purge_aborted = 1;
break;
@@ -303,7 +357,14 @@ p9_sgpe_stop_entry()
}
#endif
- GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, ex), scom_data);
+
+ if (ex & FST_EX_IN_QUAD)
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, 0),
+ scom_data);
+
+ if (ex & SND_EX_IN_QUAD)
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_PM_PURGE_REG, qloop, 1),
+ scom_data);
}
while(scom_data & BIT64(0));
@@ -314,30 +375,9 @@ p9_sgpe_stop_entry()
#endif
- //====================
- MARK_TRAP(SE_PURGE_PB)
- //====================
-
-#if EPM_P9_TUNING
- // PK_TRACE("SE11.e");
- // No need: Poll for chtm purge done
- // do {
- // GPE_GETSCOM(CME_SCOM_EISR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX0,
- // qloop, scom_data);
- // } while((scom_data & BITS64(24,2)) != BITS64(22,2));
- // do {
- // GPE_GETSCOM(CME_SCOM_EISR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX1,
- // qloop, scom_data);
- // } while((scom_data & BITS64(24,2)) != BITS64(22,2));
- // cme scom eisr is read-only, cannot clear the eisr here, clear in cme
-#endif
-
- // PK_TRACE("SE11.f");
- // No need: Deassert chtm purges
- //GPE_PUTSCOM(CME_SCOM_SICR_CLR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX0,
- // qloop, BIT64(24)|BIT64(25));
- //GPE_PUTSCOM(CME_SCOM_SICR_CLR, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX1,
- // qloop, BIT64(24)|BIT64(25));
+ //==================================
+ MARK_TAG(SE_PURGE_PB, (32 >> qloop))
+ //==================================
PK_TRACE("SE11.g");
// Assert PowerBus purge
@@ -354,29 +394,63 @@ p9_sgpe_stop_entry()
PK_TRACE("SE11.i");
// Deassert PowerBus purge
+ // todo may need to move this to wakeup
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(30));
- //==========================================
+ //===========================================
MARK_TAG(SE_WAIT_PGPE_SUSPEND, (32 >> qloop))
- //==========================================
+ //===========================================
// TODO: Poll PGPE Suspend Ack
- //=====================================
- MARK_TAG(SE_STOP_CACHE_CLKS, (32 >> qloop))
- //=====================================
+ //======================================
+ MARK_TAG(SE_QUIESCE_QUAD, (32 >> qloop))
+ //======================================
+ // todo halt cme here
PK_TRACE("SE11.j");
+
// Assert refresh quiesce prior to L3 (refresh domain) stop clk
// Edram quiesce is asserted by hardware when l3 thold is asserted in cc
- GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, ex), scom_data);
- scom_data |= BIT64(7);
- GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, ex), scom_data);
+ if (ex & FST_EX_IN_QUAD)
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, 0), scom_data);
+ scom_data |= BIT64(7);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, 0), scom_data);
+ }
- // todo: check NCU_SATUS_REG[0:3] for all zeros
+ if (ex & SND_EX_IN_QUAD)
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, 1), scom_data);
+ scom_data |= BIT64(7);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_EX(EX_DRAM_REF_REG, qloop, 1), scom_data);
+ }
+
+ // Check NCU_SATUS_REG[0:3] for all zeros
+ if (ex & FST_EX_IN_QUAD)
+ {
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_NCU_STATUS_REG, qloop, 0),
+ scom_data);
+ }
+ while((~scom_data & BITS64(0, 4)) != BITS64(0 , 4));
+ }
+
+ if (ex & SND_EX_IN_QUAD)
+ {
+ do
+ {
+ GPE_GETSCOM(GPE_SCOM_ADDR_EX(EX_NCU_STATUS_REG, qloop, 1),
+ scom_data);
+ }
+ while((~scom_data & BITS64(0, 4)) != BITS64(0 , 4));
+ }
+
+ //===========================
+ MARK_TRAP(SE_STOP_CACHE_CLKS)
+ //===========================
PK_TRACE("SE11.k");
- // Assert flush_inhibit
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CPLT_CTRL0_OR, qloop), BIT64(2));
// Raise Cache Logical fence
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, qloop), BIT64(18));
@@ -387,8 +461,8 @@ p9_sgpe_stop_entry()
PK_TRACE("SE11.m");
// Stop Cache Clocks
- //GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop), 0x9F3E00000000E000);
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop), 0x9E3E00000000E000);
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLK_REGION, qloop),
+ 0x8C3E00000000E000 | ((uint64_t)ex << SHIFT64(7)));
PK_TRACE("SE11.n");
@@ -397,9 +471,9 @@ p9_sgpe_stop_entry()
{
GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(EQ_CLOCK_STAT_SL, qloop), scom_data);
}
-
- //while((scom_data & (BITS64(4, 4) | BITS64(10, 4))) != (BITS64(4, 4) | BITS64(10, 4)));
- while((scom_data & (BITS64(4, 3) | BITS64(10, 5))) != (BITS64(4, 3) | BITS64(10, 5)));
+ while((scom_data &
+ (BITS64(4, 2) | ((uint64_t)ex << SHIFT64(7)) | BITS64(10, 5))) !=
+ (BITS64(4, 2) | ((uint64_t)ex << SHIFT64(7)) | BITS64(10, 5)));
// MF: verify compiler generate single rlwmni
// MF: delay may be needed for stage latch to propagate thold
@@ -418,17 +492,9 @@ p9_sgpe_stop_entry()
// Update QSSR: quad_stopped
out32(OCB_QSSR_OR, BIT32(qloop + 14));
- //===================================
- MARK_TAG(SE_STOP_CACHE_CLKS_DONE, (32 >> qloop))
- //===================================
-
- //-------------------------------------------------------------------------
- // STOP LEVEL 11.B
- //-------------------------------------------------------------------------
-
- //========================================
+ //=========================================
MARK_TAG(SE_POWER_OFF_CACHE, (32 >> qloop))
- //========================================
+ //=========================================
// DD: Assert Cache Vital Thold/PCB Fence/Electrical Fence
PK_TRACE("SE11.q");
@@ -437,45 +503,49 @@ p9_sgpe_stop_entry()
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_NET_CTRL0_WOR, qloop), BIT64(16));
// L3 edram shutdown
+ // todo: not EPM flag for delay
PK_TRACE("SE11.r");
- /*
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(7));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(6));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(5));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(4));
- */
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(3));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(2));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(1));
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop), BIT64(0));
-#if !STOP_PRIME
-#if !EPM_P9_TUNING
- // Make sure we are not forcing PFET for VDD or VCS off
- // vdd_pfet_force_state == 00 (Nop)
- // vcs_pfet_force_state == 00 (Nop)
- PK_TRACE("SE11.s");
- GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, qloop), scom_data);
-
- if (scom_data & BITS64(0, 4))
+ if (ex & SND_EX_IN_QUAD)
{
- return SGPE_STOP_ENTRY_VDD_PFET_NOT_IDLE;
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(7));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(6));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(5));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(4));
}
-#endif
+ if (ex & FST_EX_IN_QUAD)
+ {
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(3));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(2));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(1));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(EQ_QPPM_QCCR_WCLEAR, qloop),
+ BIT64(0));
+ }
+#if !STOP_PRIME
+ // todo needed?
// Prepare PFET Controls
// vdd_pfet_val/sel_override = 0 (disbaled)
// vcs_pfet_val/sel_override = 0 (disbaled)
// vdd_pfet_regulation_finger_en = 0 (controled by FSM)
PK_TRACE("SE11.t");
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_CLR, qloop), BITS64(4, 4) | BIT64(8));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_CLR, qloop),
+ BITS64(4, 4) | BIT64(8));
- // Power Off Cache VDD/VDS
- // vdd_pfet_force_state = 01 (Force Voff)
+ // Power Off Cache VDS then VDD
// vcs_pfet_force_state = 01 (Force Voff)
PK_TRACE("SE11.u");
- GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_OR, qloop), BIT64(1) | BIT64(3));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_OR, qloop), BIT64(3));
+
+ // todo: poll the sense line instead
// Poll for power gate sequencer state: 0x8 (FSM Idle)
PK_TRACE("SE11.v");
@@ -483,28 +553,32 @@ p9_sgpe_stop_entry()
{
GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, qloop), scom_data);
}
- while(!(scom_data & (BIT64(42) | BIT64(50))));
+ while(!(scom_data & BIT64(50)));
-#if !EPM_P9_TUNING
- // Optional: Poll for vdd_pg_sel/vcs_pg_sel being: 0x8
- PK_TRACE("SE11.w");
+ // vdd_pfet_force_state = 01 (Force Voff)
+ PK_TRACE("SE11.u");
+ GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_OR, qloop), BIT64(1));
+
+ // todo: poll the sense line instead
+ // Poll for power gate sequencer state: 0x8 (FSM Idle)
+ PK_TRACE("SE11.v");
do
{
- CME_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, qloop), scom_data);
+ GPE_GETSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS, qloop), scom_data);
}
- while(!(scom_data & BIT64(46) | BIT64(54)));
-
-#endif
+ while(!(scom_data & BIT64(42)));
// Turn Off Force Voff
// vdd_pfet_force_state = 00 (Nop)
+ // vcs_pfet_force_state = 00 (Nop)
PK_TRACE("SE11.x");
GPE_PUTSCOM(GPE_SCOM_ADDR_QUAD(PPM_PFCS_CLR, qloop), BITS64(0, 4));
+
#endif
PK_TRACE("SE11.y");
- G_sgpe_stop_record.state[qloop].detail.q_act = STOP_LEVEL_11;
+ G_sgpe_stop_record.state[qloop].act_state_q = STOP_LEVEL_11;
for(cloop = 0; cloop < CORES_PER_QUAD; cloop++)
{
@@ -530,9 +604,9 @@ p9_sgpe_stop_entry()
// Update QSSR: drop stop_entry_ongoing
out32(OCB_QSSR_CLR, BIT32(qloop + 20));
- //====================================
+ //=====================================
MARK_TAG(SE_STOP11_DONE, (32 >> qloop))
- //====================================
+ //=====================================
}
// Enable Type2 Interrupt
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit.c
index 6283fc53..83efa302 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit.c
@@ -31,29 +31,32 @@ extern SgpeStopRecord G_sgpe_stop_record;
int
p9_sgpe_stop_exit()
{
- int rc;
- uint8_t ex;
- uint8_t cloop;
- uint8_t qloop;
+ int rc = 0;
+ uint32_t m_l2;
+ uint32_t m_l3;
+ uint32_t cloop;
+ uint32_t qloop;
uint32_t cexit;
//uint64_t scom_data;
ppm_sshsrc_t hist;
- MARK_TAG(BEGINSCOPE_STOP_EXIT, (G_sgpe_stop_record.group.member.q_out >> 10))
+ //===============================
+ MARK_TAG(BEGINSCOPE_STOP_EXIT, 0)
+ //===============================
- for(cexit = G_sgpe_stop_record.group.member.c_out, qloop = 0, ex = 0;
+ for(cexit = G_sgpe_stop_record.group.exit_c, qloop = 0, m_l2 = 0, m_l3 = 0;
cexit > 0;
- cexit = cexit << 4, qloop++, ex = 0)
+ cexit = cexit << 4, qloop++, m_l2 = 0, m_l3 = 0)
{
- ex |= ((cexit & BITS32(0, 2)) ? FST_EX_IN_QUAD : 0);
- ex |= ((cexit & BITS32(2, 2)) ? SND_EX_IN_QUAD : 0);
+ m_l2 |= ((cexit & BITS32(0, 2)) ? FST_EX_IN_QUAD : 0);
+ m_l2 |= ((cexit & BITS32(2, 2)) ? SND_EX_IN_QUAD : 0);
- if(!ex)
+ if(!m_l2)
{
continue;
}
- if(G_sgpe_stop_record.state[qloop].detail.q_act >= STOP_LEVEL_11)
+ if(G_sgpe_stop_record.state[qloop].act_state_q >= STOP_LEVEL_11)
{
SGPE_STOP_UPDATE_HISTORY(qloop,
QUAD_ADDR_BASE,
@@ -63,54 +66,84 @@ p9_sgpe_stop_exit()
STOP_LEVEL_0,
STOP_REQ_DISABLE,
STOP_ACT_DISABLE);
- MARK_TRAP(SX_LV11_WAKEUP_START)
+
+ //=================================
+ MARK_TAG(SX_POWERON, (32 >> qloop))
+ //=================================
PK_TRACE("Cache Poweron");
p9_hcd_cache_poweron(qloop);
- MARK_TRAP(SX_POWERON_END)
+
+ //=========================
+ MARK_TRAP(SX_CHIPLET_RESET)
+ //=========================
PK_TRACE("Cache Chiplet Reset");
p9_hcd_cache_chiplet_reset(qloop);
- MARK_TRAP(SX_CHIPLET_RESET_END)
#if !STOP_PRIME
PK_TRACE("Cache Gptr Time Initf");
p9_hcd_cache_gptr_time_initf(qloop);
- MARK_TRAP(SX_GPTR_TIME_INITF_END)
#endif
+ //====================================
+ MARK_TAG(SX_DPLL_SETUP, (32 >> qloop))
+ //====================================
+
+ ///@todo dpll_initf
+
PK_TRACE("Cache Dpll Setup");
p9_hcd_cache_dpll_setup(qloop);
- MARK_TRAP(SX_DPLL_SETUP_END)
#if !STOP_PRIME
+ //=======================================
+ MARK_TAG(SX_CHIPLET_INITS, (32 >> qloop))
+ //=======================================
+
PK_TRACE("Cache Chiplet Init");
p9_hcd_cache_chiplet_init(qloop);
- MARK_TRAP(SX_CHIPLET_INIT_END)
PK_TRACE("Cache Repair Initf");
p9_hcd_cache_repair_initf(qloop);
- MARK_TRAP(SX_REPAIR_INITF_END)
+
+ //====================================
+ MARK_TAG(SX_ARRAY_INIT, (32 >> qloop))
+ //====================================
PK_TRACE("Cache Arrayinit");
p9_hcd_cache_arrayinit(qloop);
- MARK_TRAP(SX_ARRAYINIT_END)
+
+ //=====================
+ MARK_TRAP(SX_FUNC_INIT)
+ //=====================
PK_TRACE("Cache Initf");
p9_hcd_cache_initf(qloop);
- MARK_TRAP(SX_INITF_END)
#endif
+ if (G_sgpe_stop_record.group.good_x0 & BIT32(qloop))
+ {
+ m_l3 |= FST_EX_IN_QUAD;
+ }
+
+ if (G_sgpe_stop_record.group.good_x1 & BIT32(qloop))
+ {
+ m_l3 |= SND_EX_IN_QUAD;
+ }
+
+ //===========================================
+ MARK_TAG(SX_CACHE_STARTCLOCKS, (32 >> qloop))
+ //===========================================
+
PK_TRACE("Cache Startclocks");
- p9_hcd_cache_startclocks(qloop);
- MARK_TRAP(SX_STARTCLOCKS_END)
+ p9_hcd_cache_startclocks(qloop, m_l3);
}
- if((G_sgpe_stop_record.state[qloop].detail.x0act >= STOP_LEVEL_8 &&
- ex == FST_EX_IN_QUAD) ||
- (G_sgpe_stop_record.state[qloop].detail.x1act >= STOP_LEVEL_8 &&
- ex == SND_EX_IN_QUAD) )
+ if((G_sgpe_stop_record.state[qloop].act_state_x0 >= STOP_LEVEL_8 &&
+ m_l2 == FST_EX_IN_QUAD) ||
+ (G_sgpe_stop_record.state[qloop].act_state_x1 >= STOP_LEVEL_8 &&
+ m_l2 == SND_EX_IN_QUAD) )
{
for(cloop = 0; cloop < CORES_PER_QUAD; cloop++)
{
@@ -129,51 +162,61 @@ p9_sgpe_stop_exit()
STOP_ACT_DISABLE);
}
- MARK_TRAP(SX_LV8_WAKEUP_START)
+ //========================================================
+ MARK_TAG(SX_L2_STARTCLOCKS, ((m_l2 << 6) | (32 >> qloop)))
+ //========================================================
PK_TRACE("Cache L2 Startclocks");
- p9_hcd_cache_l2_startclocks(ex, qloop);
- MARK_TRAP(SX_L2_STARTCLOCKS_END)
+ p9_hcd_cache_l2_startclocks(qloop, m_l2);
// reset ex actual state if ex is exited.
- if (ex & FST_EX_IN_QUAD)
+ if (m_l2 & FST_EX_IN_QUAD)
{
- G_sgpe_stop_record.state[qloop].detail.x0act = 0;
+ G_sgpe_stop_record.state[qloop].act_state_x0 = 0;
}
- if (ex & SND_EX_IN_QUAD)
+ if (m_l2 & SND_EX_IN_QUAD)
{
- G_sgpe_stop_record.state[qloop].detail.x1act = 0;
+ G_sgpe_stop_record.state[qloop].act_state_x1 = 0;
}
}
- if(G_sgpe_stop_record.state[qloop].detail.q_act >= STOP_LEVEL_11)
+ if(G_sgpe_stop_record.state[qloop].act_state_q >= STOP_LEVEL_11)
{
- MARK_TRAP(SX_LV11_WAKEUP_CONTINUE)
#if !STOP_PRIME
+ //====================================
+ MARK_TAG(SX_SCOM_INITS, (32 >> qloop))
+ //====================================
+
PK_TRACE("Cache Scom Init");
p9_hcd_cache_scominit(qloop);
- MARK_TRAP(SX_SCOMINIT_END)
PK_TRACE("Cache Scom Cust");
p9_hcd_cache_scomcust(qloop);
- MARK_TRAP(SX_SCOMCUST_END)
+
+ //==================================
+ MARK_TAG(SX_CME_BOOT, (32 >> qloop))
+ //==================================
PK_TRACE("Boot CME");
//cme_boot();
- MARK_TRAP(SX_CME_BOOT_END)
+
+ //=======================================
+ MARK_TAG(SX_RUNTIME_INITS, (32 >> qloop))
+ //=======================================
PK_TRACE("Cache RAS Runtime Scom");
p9_hcd_cache_ras_runtime_scom(qloop);
- MARK_TRAP(SX_RAS_RUNTIME_SCOM_END)
PK_TRACE("Cache OCC Runtime Scom");
p9_hcd_cache_occ_runtime_scom(qloop);
- MARK_TRAP(SX_OCC_RUNTIME_SCOM_END)
+ //=========================
+ MARK_TRAP(SX_ENABLE_ANALOG)
+ //=========================
#endif
- G_sgpe_stop_record.state[qloop].detail.q_act = 0;
+ G_sgpe_stop_record.state[qloop].act_state_q = 0;
}
for(cloop = 0; cloop < CORES_PER_QUAD; cloop++)
@@ -184,27 +227,29 @@ p9_sgpe_stop_exit()
}
// reset clevel to 0 if core is going to wake up
- G_sgpe_stop_record.level[qloop].qlevel &= ~BITS16((cloop << 2), 4);
+ G_sgpe_stop_record.level[qloop][cloop] = 0;
/*do {
GPE_GETSCOM(CME_SCOM_FLAGS, QUAD_ADDR_BASE|CME_ADDR_OFFSET_EX0,
((qloop<<2)+cloop), scom_data);
} while(!(scom_data & BIT64(0)));*/
// TODO PUT THE FOLLOWING TWO BEFORE CME_BOOT()
// Change PPM Wakeup to CME
- GPE_PUTSCOM(GPE_SCOM_ADDR_CORE(CPPM_CPMMR_CLR, ((qloop << 2) + cloop)),
- BIT64(13));
+ GPE_PUTSCOM(GPE_SCOM_ADDR_CORE(CPPM_CPMMR_CLR,
+ ((qloop << 2) + cloop)), BIT64(13));
PK_TRACE("Doorbell1 the CME");
GPE_PUTSCOM(GPE_SCOM_ADDR_CORE(CPPM_CMEMSG, ((qloop << 2) + cloop)),
(BIT64(0)));
- GPE_PUTSCOM(GPE_SCOM_ADDR_CORE(CPPM_CMEDB1_OR, ((qloop << 2) + cloop)),
- BIT64(7));
-
+ GPE_PUTSCOM(GPE_SCOM_ADDR_CORE(CPPM_CMEDB1_OR,
+ ((qloop << 2) + cloop)), BIT64(7));
}
}
// Enable Type2 Interrupt
out32(OCB_OIMR1_CLR, BIT32(15));
+ //===========================
MARK_TRAP(ENDSCOPE_STOP_EXIT)
+ //===========================
+
return SGPE_STOP_SUCCESS;
}
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit_marks.h b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit_marks.h
index beb48b20..11905aa3 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit_marks.h
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_exit_marks.h
@@ -36,37 +36,31 @@ namespace SGPE_STOP_EXIT_MARKS
enum SGPE_SX_MARKS
{
- SX_LV11_WAKEUP_START = 0x0,
+ SX_POWERON = 0x0,
SX_POWERON_DONE = 0x8,
- SX_POWERON_PG_SEL = 0x10,
- SX_POWERON_END = 0x18,
- SX_CHIPLET_RESET_GLSMUX_RESET = 0x20,
- SX_CHIPLET_RESET_SCAN0 = 0x28,
- SX_CHIPLET_RESET_END = 0x30,
- SX_GPTR_TIME_INITF_END = 0x38,
- SX_DPLL_START_DONE = 0x40,
- SX_DPLL_SETUP_END = 0x48,
- SX_CHIPLET_INIT_SCAN0 = 0x50,
- SX_CHIPLET_INIT_END = 0x68,
- SX_REPAIR_INITF_END = 0xe0,
- SX_ARRAYINIT_SUBMODULE = 0xe8,
- SX_ARRAYINIT_SCAN0 = 0xf0,
- SX_ARRAYINIT_END = 0xf8,
- SX_INITF_END = 0x100,
- SX_LV9_WAKEUP_START = 0x108,
- SX_STARTCLOCKS_DONE = 0x110,
- SX_STARTCLOCKS_END = 0x118,
- SX_LV8_WAKEUP_START = 0x120,
- SX_L2_STARTCLOCKS_DONE = 0x128,
- SX_L2_STARTCLOCKS_END = 0x130,
- SX_LV11_WAKEUP_CONTINUE = 0x138,
- SX_SCOMINIT_END = 0x140,
- SX_SCOMCUST_END = 0x148,
- SX_CME_BOOT_END = 0x150,
- SX_RAS_RUNTIME_SCOM_END = 0x168,
- SX_OCC_RUNTIME_SCOM_END = 0x1e0,
- BEGINSCOPE_STOP_EXIT = 0x1f20,
- ENDSCOPE_STOP_EXIT = 0x1f28
+ SX_CHIPLET_RESET = 0x10,
+ SX_CHIPLET_RESET_GLSMUX_RESET = 0x18,
+ SX_CHIPLET_RESET_SCAN0 = 0x20,
+ SX_DPLL_SETUP = 0x28,
+ SX_DPLL_START_DONE = 0x30,
+ SX_CHIPLET_INITS = 0x38,
+ SX_CHIPLET_INIT_SCAN0 = 0x40,
+ SX_ARRAY_INIT = 0x48,
+ SX_ARRAY_INIT_SUBMODULE = 0x50,
+ SX_ARRAY_INIT_SCAN0 = 0x68,
+ SX_FUNC_INIT = 0xe0,
+ SX_CACHE_STARTCLOCKS = 0xe8,
+ SX_CACHE_STARTCLOCKS_DONE = 0xf0,
+ SX_L2_STARTCLOCKS = 0xf8,
+ SX_L2_STARTCLOCKS_GRID = 0x100,
+ SX_L2_STARTCLOCKS_DONE = 0x108,
+ SX_SCOM_INITS = 0x110,
+ SX_CME_BOOT = 0x118,
+ SX_RUNTIME_INITS = 0x120,
+ SX_ENABLE_ANALOG = 0x128,
+ SX_LESSTHAN8_WAIT = 0x130,
+ BEGINSCOPE_STOP_EXIT = 0x1f28,
+ ENDSCOPE_STOP_EXIT = 0x1f30
};
@@ -74,35 +68,29 @@ enum SGPE_SX_MARKS
const std::vector<SGPE_SX_MARKS> MARKS =
{
- SX_LV11_WAKEUP_START,
+ SX_POWERON,
SX_POWERON_DONE,
- SX_POWERON_PG_SEL,
- SX_POWERON_END,
+ SX_CHIPLET_RESET,
SX_CHIPLET_RESET_GLSMUX_RESET,
SX_CHIPLET_RESET_SCAN0,
- SX_CHIPLET_RESET_END,
- SX_GPTR_TIME_INITF_END,
+ SX_DPLL_SETUP,
SX_DPLL_START_DONE,
- SX_DPLL_SETUP_END,
+ SX_CHIPLET_INITS,
SX_CHIPLET_INIT_SCAN0,
- SX_CHIPLET_INIT_END,
- SX_REPAIR_INITF_END,
- SX_ARRAYINIT_SUBMODULE,
- SX_ARRAYINIT_SCAN0,
- SX_ARRAYINIT_END,
- SX_INITF_END,
- SX_LV9_WAKEUP_START,
- SX_STARTCLOCKS_DONE,
- SX_STARTCLOCKS_END,
- SX_LV8_WAKEUP_START,
+ SX_ARRAY_INIT,
+ SX_ARRAY_INIT_SUBMODULE,
+ SX_ARRAY_INIT_SCAN0,
+ SX_FUNC_INIT,
+ SX_CACHE_STARTCLOCKS,
+ SX_CACHE_STARTCLOCKS_DONE,
+ SX_L2_STARTCLOCKS,
+ SX_L2_STARTCLOCKS_GRID,
SX_L2_STARTCLOCKS_DONE,
- SX_L2_STARTCLOCKS_END,
- SX_LV11_WAKEUP_CONTINUE,
- SX_SCOMINIT_END,
- SX_SCOMCUST_END,
- SX_CME_BOOT_END,
- SX_RAS_RUNTIME_SCOM_END,
- SX_OCC_RUNTIME_SCOM_END,
+ SX_SCOM_INITS,
+ SX_CME_BOOT,
+ SX_RUNTIME_INITS,
+ SX_ENABLE_ANALOG,
+ SX_LESSTHAN8_WAIT,
BEGINSCOPE_STOP_EXIT,
ENDSCOPE_STOP_EXIT
};
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c
index f6051236..f5176187 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/p9_sgpe_stop_irq_handlers.c
@@ -53,9 +53,10 @@ SgpeStopRecord G_sgpe_stop_record;
void
p9_sgpe_stop_pig_type2_handler(void* arg, PkIrqId irq)
{
- uint8_t qloop;
- uint8_t cloop;
- uint8_t event;
+ int event;
+ uint32_t qloop;
+ uint32_t cloop;
+ uint32_t cgood;
uint32_t pending;
uint32_t payload;
@@ -71,19 +72,34 @@ p9_sgpe_stop_pig_type2_handler(void* arg, PkIrqId irq)
PK_TRACE("Type2: %x", pending);
// clear group before analyzing input
- G_sgpe_stop_record.group.vector[0] = 0;
- G_sgpe_stop_record.group.vector[1] = 0;
+ G_sgpe_stop_record.group.entry_x0 = 0;
+ G_sgpe_stop_record.group.entry_x1 = 0;
+ G_sgpe_stop_record.group.entry_x = 0;
+ G_sgpe_stop_record.group.entry_q = 0;
+ G_sgpe_stop_record.group.entry_c = 0;
+ G_sgpe_stop_record.group.exit_x0 = 0;
+ G_sgpe_stop_record.group.exit_x1 = 0;
+ G_sgpe_stop_record.group.exit_x = 0;
+ G_sgpe_stop_record.group.exit_q = 0;
+ G_sgpe_stop_record.group.exit_c = 0;
// loop all quads
- for(qloop = 0; qloop < MAX_QUADS; qloop++, pending = pending << 4)
+ for(qloop = 0, cgood = G_sgpe_stop_record.group.good_c;
+ qloop < MAX_QUADS;
+ qloop++, pending = pending << 4, cgood = cgood << 4)
{
// if nothing happening to this quad, skip
- if(!(BITS32(0, 4) & pending))
+ if(!(BITS32(0, 4) & pending & cgood))
{
continue;
}
- PK_TRACE("q[%d]lv: %x", qloop, G_sgpe_stop_record.level[qloop].qlevel);
+ PK_TRACE("q[%d]", qloop);
+ PK_TRACE("clv[%d][%d][%d][%d]",
+ G_sgpe_stop_record.level[qloop][0],
+ G_sgpe_stop_record.level[qloop][1],
+ G_sgpe_stop_record.level[qloop][2],
+ G_sgpe_stop_record.level[qloop][3]);
// then loop all cores in the quad
for(cloop = 0, event = 0; cloop < CORES_PER_QUAD; cloop++)
@@ -96,108 +112,153 @@ p9_sgpe_stop_pig_type2_handler(void* arg, PkIrqId irq)
// read payload on core has interrupt pending
payload = in32(OCB_OPIT2CN(((qloop << 2) + cloop)));
- PK_TRACE("q[%d]c[%d] payload: %x", qloop, cloop, payload);
+ PK_TRACE("c[%d] payload [%x]", cloop, payload);
// check if exit request
if (payload & TYPE2_PAYLOAD_STOP_EVENT)
{
- PK_TRACE("q[%d]c[%d] requested exit", qloop, cloop);
+ PK_TRACE("c[%d] request exit", cloop);
// remember which core asking to exit
event |= SGPE_EXIT_FLAG;
- G_sgpe_stop_record.group.member.c_out |=
+
+ if (cloop < CORES_PER_EX)
+ {
+ G_sgpe_stop_record.group.exit_x0 |= BIT32(qloop);
+ G_sgpe_stop_record.group.exit_x |= BIT32(qloop << 1);
+ }
+ else
+ {
+ G_sgpe_stop_record.group.exit_x1 |= BIT32(qloop);
+ G_sgpe_stop_record.group.exit_x |= BIT32((qloop << 1) + 1);
+ }
+
+ G_sgpe_stop_record.group.exit_q |= BIT32(qloop);
+ G_sgpe_stop_record.group.exit_c |=
BIT32(((qloop << 2) + cloop));
- G_sgpe_stop_record.group.member.x_out |=
- BIT16(((qloop << 1) + (cloop >> 1)));
- G_sgpe_stop_record.group.member.q_out |=
- BIT16(qloop);
- // otherwise it is entry request with stop level in payload
}
+ // otherwise it is entry request with stop level in payload
else
{
- PK_TRACE("q[%d]c[%d] requested enter to lv%d", qloop, cloop,
+ PK_TRACE("c[%d] request enter to lv[%d]", cloop,
(payload & TYPE2_PAYLOAD_STOP_LEVEL));
// read stop level on core asking to enter
event |= SGPE_ENTRY_FLAG;
- G_sgpe_stop_record.level[qloop].qlevel &= ~BITS16((cloop << 2), 4);
- G_sgpe_stop_record.level[qloop].qlevel |=
- ((payload & TYPE2_PAYLOAD_STOP_LEVEL) << SHIFT16(((cloop << 2) + 3)));
- G_sgpe_stop_record.group.member.c_in |=
+ G_sgpe_stop_record.level[qloop][cloop] =
+ (payload & TYPE2_PAYLOAD_STOP_LEVEL);
+ G_sgpe_stop_record.group.entry_c |=
BIT32(((qloop << 2) + cloop));
}
- }
- PK_TRACE("q[%d]lv: %x", qloop, G_sgpe_stop_record.level[qloop].qlevel);
- PK_TRACE("q[%d]st: %x", qloop, G_sgpe_stop_record.state[qloop].status);
+ }
// If an entry being requested by at least one core
if (event & SGPE_ENTRY_FLAG)
{
+ PK_TRACE("clv[%d][%d][%d][%d]",
+ G_sgpe_stop_record.level[qloop][0],
+ G_sgpe_stop_record.level[qloop][1],
+ G_sgpe_stop_record.level[qloop][2],
+ G_sgpe_stop_record.level[qloop][3]);
+
// Calculate EX and Quad targets based on current core stop levels
- G_sgpe_stop_record.state[qloop].detail.x0req =
- G_sgpe_stop_record.level[qloop].clevel.c0lv <
- G_sgpe_stop_record.level[qloop].clevel.c1lv ?
- G_sgpe_stop_record.level[qloop].clevel.c0lv :
- G_sgpe_stop_record.level[qloop].clevel.c1lv ;
- G_sgpe_stop_record.state[qloop].detail.x1req =
- G_sgpe_stop_record.level[qloop].clevel.c2lv <
- G_sgpe_stop_record.level[qloop].clevel.c3lv ?
- G_sgpe_stop_record.level[qloop].clevel.c2lv :
- G_sgpe_stop_record.level[qloop].clevel.c3lv ;
- G_sgpe_stop_record.state[qloop].detail.q_req =
- G_sgpe_stop_record.state[qloop].detail.x0req <
- G_sgpe_stop_record.state[qloop].detail.x1req ?
- G_sgpe_stop_record.state[qloop].detail.x0req :
- G_sgpe_stop_record.state[qloop].detail.x1req ;
+ G_sgpe_stop_record.state[qloop].req_state_x0 =
+ G_sgpe_stop_record.level[qloop][0] <
+ G_sgpe_stop_record.level[qloop][1] ?
+ G_sgpe_stop_record.level[qloop][0] :
+ G_sgpe_stop_record.level[qloop][1] ;
+ G_sgpe_stop_record.state[qloop].req_state_x1 =
+ G_sgpe_stop_record.level[qloop][2] <
+ G_sgpe_stop_record.level[qloop][3] ?
+ G_sgpe_stop_record.level[qloop][2] :
+ G_sgpe_stop_record.level[qloop][3] ;
+ G_sgpe_stop_record.state[qloop].req_state_q =
+ G_sgpe_stop_record.state[qloop].req_state_x0 <
+ G_sgpe_stop_record.state[qloop].req_state_x1 ?
+ G_sgpe_stop_record.state[qloop].req_state_x0 :
+ G_sgpe_stop_record.state[qloop].req_state_x1 ;
// Check if EX and/or Quad qualifies to proceed with entry
- if (G_sgpe_stop_record.state[qloop].detail.x0act < SGPE_EX_BASE_LV &&
- G_sgpe_stop_record.state[qloop].detail.x0req >= SGPE_EX_BASE_LV)
+ if (G_sgpe_stop_record.state[qloop].act_state_x0 <
+ SGPE_EX_BASE_LV &&
+ G_sgpe_stop_record.state[qloop].req_state_x0 >=
+ SGPE_EX_BASE_LV)
{
- G_sgpe_stop_record.group.member.x_in |= BIT16((qloop << 1));
+ G_sgpe_stop_record.group.entry_x0 |= BIT32(qloop);
+ G_sgpe_stop_record.group.entry_x |= BIT32(qloop << 1);
}
- if (G_sgpe_stop_record.state[qloop].detail.x1act < SGPE_EX_BASE_LV &&
- G_sgpe_stop_record.state[qloop].detail.x1req >= SGPE_EX_BASE_LV)
+ if (G_sgpe_stop_record.state[qloop].act_state_x1 <
+ SGPE_EX_BASE_LV &&
+ G_sgpe_stop_record.state[qloop].req_state_x1 >=
+ SGPE_EX_BASE_LV)
{
- G_sgpe_stop_record.group.member.x_in |= BIT16(((qloop << 1) + 1));
+ G_sgpe_stop_record.group.entry_x1 |= BIT32(qloop);
+ G_sgpe_stop_record.group.entry_x |= BIT32((qloop << 1) + 1);
}
- if (G_sgpe_stop_record.state[qloop].detail.q_act <
- G_sgpe_stop_record.state[qloop].detail.q_req &&
- G_sgpe_stop_record.state[qloop].detail.q_req >= SGPE_EQ_BASE_LV)
+ if (G_sgpe_stop_record.state[qloop].act_state_q <
+ G_sgpe_stop_record.state[qloop].req_state_q &&
+ G_sgpe_stop_record.state[qloop].req_state_q >=
+ SGPE_EQ_BASE_LV)
{
- G_sgpe_stop_record.group.member.q_in |= BIT16(qloop);
+ G_sgpe_stop_record.group.entry_q |= BIT32(qloop);
}
+
}
- PK_TRACE("q[%d]st: %x", qloop, G_sgpe_stop_record.state[qloop].status);
+ // todo MARK_TAG(SE_LESSTHAN8_WAIT)
+ PK_TRACE("req:x0lv[%d]x1lv[%d]qlv[%d]",
+ G_sgpe_stop_record.state[qloop].req_state_x0,
+ G_sgpe_stop_record.state[qloop].req_state_x1,
+ G_sgpe_stop_record.state[qloop].req_state_q);
+
+ PK_TRACE("act:x0lv[%d]x1lv[%d]qlv[%d]",
+ G_sgpe_stop_record.state[qloop].act_state_x0,
+ G_sgpe_stop_record.state[qloop].act_state_x1,
+ G_sgpe_stop_record.state[qloop].act_state_q);
}
- PK_TRACE("Entry: C%x, X%x, Q%x",
- G_sgpe_stop_record.group.member.c_in,
- G_sgpe_stop_record.group.member.x_in,
- G_sgpe_stop_record.group.member.q_in);
- PK_TRACE("Exit: C%x, X%x, Q%x",
- G_sgpe_stop_record.group.member.c_out,
- G_sgpe_stop_record.group.member.x_out,
- G_sgpe_stop_record.group.member.q_out);
+ G_sgpe_stop_record.group.entry_x0 &= G_sgpe_stop_record.group.good_x0;
+ G_sgpe_stop_record.group.entry_x1 &= G_sgpe_stop_record.group.good_x1;
+ G_sgpe_stop_record.group.entry_x &= G_sgpe_stop_record.group.good_x;
+ G_sgpe_stop_record.group.entry_q &= G_sgpe_stop_record.group.good_q;
+ G_sgpe_stop_record.group.entry_c &= G_sgpe_stop_record.group.good_c;
+ G_sgpe_stop_record.group.exit_x0 &= G_sgpe_stop_record.group.good_x0;
+ G_sgpe_stop_record.group.exit_x1 &= G_sgpe_stop_record.group.good_x1;
+ G_sgpe_stop_record.group.exit_x &= G_sgpe_stop_record.group.good_x;
+ G_sgpe_stop_record.group.exit_q &= G_sgpe_stop_record.group.good_q;
+ G_sgpe_stop_record.group.exit_c &= G_sgpe_stop_record.group.good_c;
- if (G_sgpe_stop_record.group.member.c_in)
- {
- PK_TRACE("unblock entry");
- pk_semaphore_post(&(G_sgpe_stop_record.sem[0]));
- }
+ PK_TRACE("Good: X0[%x] X1[%x] Q[%x] C[%x]",
+ G_sgpe_stop_record.group.good_x0,
+ G_sgpe_stop_record.group.good_x1,
+ G_sgpe_stop_record.group.good_q,
+ G_sgpe_stop_record.group.good_c);
+ PK_TRACE("Entry: X0[%x] X1[%x] Q[%x] C[%x]",
+ G_sgpe_stop_record.group.entry_x0,
+ G_sgpe_stop_record.group.entry_x1,
+ G_sgpe_stop_record.group.entry_q,
+ G_sgpe_stop_record.group.entry_c);
+ PK_TRACE("Exit: X0[%x] X1[%x] Q[%x] C[%x]",
+ G_sgpe_stop_record.group.exit_x0,
+ G_sgpe_stop_record.group.exit_x1,
+ G_sgpe_stop_record.group.exit_q,
+ G_sgpe_stop_record.group.exit_c);
+ PK_TRACE("X: G[%x] E[%x] X[%x]",
+ G_sgpe_stop_record.group.good_x,
+ G_sgpe_stop_record.group.entry_x,
+ G_sgpe_stop_record.group.exit_x);
- if (G_sgpe_stop_record.group.member.c_out)
+ if (G_sgpe_stop_record.group.exit_c)
{
PK_TRACE("unblock exit");
pk_semaphore_post(&(G_sgpe_stop_record.sem[1]));
}
- /*
- if (!G_sgpe_stop_record.group.vector[0])
- {
- out32(OCB_OIMR1_CLR, BIT32(15));
- }
- */
+ if (G_sgpe_stop_record.group.entry_c)
+ {
+ PK_TRACE("unblock entry");
+ pk_semaphore_post(&(G_sgpe_stop_record.sem[0]));
+ }
+
}
diff --git a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/pk_app_cfg.h b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/pk_app_cfg.h
index b7a6194b..178185bb 100644
--- a/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/pk_app_cfg.h
+++ b/import/chips/p9/procedures/ppe_closed/sgpe/stop_gpe/pk_app_cfg.h
@@ -36,7 +36,7 @@
#define STOP_PRIME 0
#define SKIP_L3_PURGE 0
-#define SKIP_L3_PURGE_ABORT 1
+#define SKIP_L3_PURGE_ABORT 0
// --------------------
OpenPOWER on IntegriCloud