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