summaryrefslogtreecommitdiffstats
path: root/import/chips/p9/procedures/ppe_closed/cme
diff options
context:
space:
mode:
Diffstat (limited to 'import/chips/p9/procedures/ppe_closed/cme')
-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
18 files changed, 2595 insertions, 537 deletions
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)
OpenPOWER on IntegriCloud