summaryrefslogtreecommitdiffstats
path: root/import/chips/p9/procedures/ppe_closed/cme/pstate_cme
diff options
context:
space:
mode:
authorMichael Floyd <mfloyd@us.ibm.com>2018-02-05 10:30:38 -0600
committerhostboot <hostboot@us.ibm.com>2018-03-22 14:04:33 -0500
commit36da534370a91cfe1f93ef10417a2a969b4779ff (patch)
tree5ef44043d5f8510d4a789a74cd3c9c40174858ad /import/chips/p9/procedures/ppe_closed/cme/pstate_cme
parente877c046104eedaa97e616f492a837b79884cbb4 (diff)
downloadtalos-hcode-36da534370a91cfe1f93ef10417a2a969b4779ff.tar.gz
talos-hcode-36da534370a91cfe1f93ef10417a2a969b4779ff.zip
CME Code Size Reduction ATTEMPT#3
-- some IOTA kernel cleanup -- also add checking for IOTA execution stack overflow -- re-coded to eliminate some math library macro usage -- added native 16-bit multiply -- re-coded to remove redundancy from external interrupt handler -- removed dec handler (optional define) and other minor cleanup -- fixed Interrupt initialization code in std_init (all PPE images) -- always inline pstate_db0_clip_bcast & update_vdm_jump_values_in_dpll -- optimized pls calculation code -- optimized pstate init, db1 handler, core good handling -- optimized pmcr requests and pmsr updates (always write for both cores) Key_Cronus_Test=PM_REGRESS Change-Id: I64f1f3a01772ab1f58c681a00c7e1a76f6ddf31a Original-Change-Id: If48fec5832bd5e46cb89f0d6a97d90a488e8ff7b CQ: SW415503 RTC: 178789 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/53381 Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Cronus HW CI <cronushw-ci+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: YUE DU <daviddu@us.ibm.com> Reviewed-by: RANGANATHPRASAD G. BRAHMASAMUDRA <prasadbgr@in.ibm.com> Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
Diffstat (limited to 'import/chips/p9/procedures/ppe_closed/cme/pstate_cme')
-rw-r--r--import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c442
1 files changed, 159 insertions, 283 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c
index 37e61b83..471c4d8f 100644
--- a/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c
+++ b/import/chips/p9/procedures/ppe_closed/cme/pstate_cme/p9_cme_thread_db.c
@@ -55,9 +55,8 @@ extern CmePstateRecord G_cme_pstate_record;
extern cmeHeader_t* G_cmeHeader;
extern LocalPstateParmBlock* G_lppb;
extern uint8_t G_vdm_threshold_table[];
-uint32_t G_cme_flags;
cppm_cmedb0_t G_dbData;
-uint32_t G_next_pstate;
+
//This is set and cleared during registration, so no need
//to protect it in critical section. It only serves to make sure
//that p9_cme_update_analog is called if pstates are started during
@@ -68,16 +67,18 @@ uint32_t G_update_analog_error;
//
//Function Prototypes
//
-inline void p9_cme_pstate_register() __attribute__((always_inline));
+inline void p9_cme_pstate_register()__attribute__((always_inline));
inline void p9_cme_pstate_db0_stop() __attribute__((always_inline));
-inline void p9_cme_pstate_db0_clip_bcast() __attribute__((always_inline));
inline void p9_cme_pstate_db0_pmsr_updt() __attribute__((always_inline));
-inline void p9_cme_pstate_freq_update() __attribute__((always_inline));
+inline void p9_cme_pstate_freq_update(uint32_t) __attribute__((always_inline));
inline void p9_cme_pstate_update_analog() __attribute__((always_inline));
+
+void p9_cme_pstate_init();
void p9_cme_pstate_process_db0();
void p9_cme_pstate_notify_sib();
void p9_cme_pstate_db0_start();
void p9_cme_pstate_db0_glb_bcast();
+void p9_cme_pstate_db0_clip_bcast();
void p9_cme_pstate_update();
void p9_cme_pstate_pig_send();
@@ -85,45 +86,25 @@ void p9_cme_pstate_pig_send();
//Doorbell0 interrupt handler
//
//Only enabled on QuadManager-CME
-void p9_cme_pstate_db0_handler(void* arg, PkIrqId irq)
+void p9_cme_pstate_db0_handler(void)
{
- PK_TRACE_INF("DB_HDL: Entered\n");
-#if defined(__IOTA__)
wrteei(1);
p9_cme_pstate_process_db0();
-#else
- pk_semaphore_post((PkSemaphore*)arg);
-#endif
- PK_TRACE_INF("DB_HDL: Exited\n");
}
//
//Doorbell3 interrupt handler
//
//Note: This enabled on both QuadManagerCME and SiblingCME
-void p9_cme_pstate_db3_handler(void* arg, PkIrqId irq)
+void p9_cme_pstate_db3_handler(void)
{
cppm_cmedb3_t db3;
PK_TRACE_INF("DB3 Handler");
//Clear EISR and read DB3 register
- if (in32(CME_LCL_FLAGS) & BIT32(CME_FLAGS_CORE0_GOOD))
- {
- out32(CME_LCL_EISR_CLR, BIT32(10));
- CME_GETSCOM(CPPM_CMEDB3, CME_MASK_C0, db3.value);
-
- //Clear DB3_C1 if CORE1 is good
- if (in32(CME_LCL_FLAGS) & BIT32(CME_FLAGS_CORE1_GOOD))
- {
- out32(CME_LCL_EISR_CLR, BIT32(11));
- }
- }
- else if (in32(CME_LCL_FLAGS) & BIT32(CME_FLAGS_CORE1_GOOD))
- {
- out32(CME_LCL_EISR_CLR, BIT32(11));
- CME_GETSCOM(CPPM_CMEDB3, CME_MASK_C1, db3.value);
- }
+ out32(CME_LCL_EISR_CLR, BITS32(10, 2));
+ CME_GETSCOM(CPPM_CMEDB3, G_cme_pstate_record.firstGoodCoreMask, db3.value);
if(db3.fields.cme_message_numbern >= MSGID_DB3_HIGH_PRIORITY_PSTATE)
{
@@ -144,10 +125,9 @@ void p9_cme_pstate_db3_handler(void* arg, PkIrqId irq)
//
void p9_cme_pstate_db3_handler_replay_db0()
{
- G_cme_flags = in32(CME_LCL_FLAGS);
G_update_analog_error = 0;
- PK_TRACE_INF("DB_TH: Process DB0 Replay");
+ PK_TRACE_INF("PSTATE: Process DB0 Replay");
//QuadManager
if(G_cme_pstate_record.qmFlag)
@@ -181,19 +161,19 @@ void p9_cme_pstate_db3_handler_high_priority_pstate()
}
//
-//p9_cme_db_thread
-//
-void p9_cme_pstate_db0_thread(void* arg)
+void p9_cme_pstate_init()
{
- PK_TRACE_INF("DB_TH: Started\n");
+ PK_TRACE_INF("PSTATE: Init Started\n");
PkMachineContext ctx __attribute__((unused));
uint32_t cores = 0;
data64_t scom_data;
+ uint64_t eimr_clr = 0;
+ uint64_t eimr_or = 0;
uint32_t resclk_data;
G_cmeHeader = (cmeHeader_t*)(CME_SRAM_HEADER_ADDR);
G_lppb = (LocalPstateParmBlock*)(G_cmeHeader->g_cme_pstate_region_offset + CME_SRAM_BASE_ADDR);
- PK_TRACE_INF("DB_TH: Hdr=0x%x, LPPB=0x%x, Nominal_Freq_Mhz=%d \n", (uint32_t)G_cmeHeader, (uint32_t)G_lppb,
+ PK_TRACE_INF("PSTATE: Hdr=0x%x, LPPB=0x%x, Nominal_Freq_Mhz=%d \n", (uint32_t)G_cmeHeader, (uint32_t)G_lppb,
G_lppb->operating_points[NOMINAL].frequency_mhz);
G_register_in_progress = 0;
@@ -213,14 +193,24 @@ void p9_cme_pstate_db0_thread(void* arg)
G_cme_record.spurr_freq_ref_upper = ((~core_freq) + 1) << 24;
// Mask PMCR interrupts, these will be unmasked when starting Pstates
- g_eimr_override |= BITS64(34, 2);
- out32_sh(CME_LCL_EIMR_OR, (BITS64SH(34, 2)));
+ eimr_or |= BITS64(34, 2);
//Read CME_LCL_FLAGS
- G_cme_flags = in32(CME_LCL_FLAGS);
+ uint32_t cme_flags = in32(CME_LCL_FLAGS);
- G_cme_pstate_record.qmFlag = G_cme_flags & BIT32(CME_FLAGS_QMGR_MASTER);
- G_cme_pstate_record.siblingCMEFlag = G_cme_flags & BIT32(CME_FLAGS_SIBLING_FUNCTIONAL);
+ G_cme_pstate_record.qmFlag = cme_flags & BIT32(CME_FLAGS_QMGR_MASTER);
+ G_cme_pstate_record.siblingCMEFlag = cme_flags & BIT32(CME_FLAGS_SIBLING_FUNCTIONAL);
+
+ if(cme_flags & BIT32(CME_FLAGS_CORE0_GOOD))
+ {
+ G_cme_pstate_record.firstGoodCoreMask = CME_MASK_C0;
+ cores |= CME_MASK_C0;
+ }
+ else // Core1 must be good
+ {
+ G_cme_pstate_record.firstGoodCoreMask = CME_MASK_C1;
+ cores |= CME_MASK_C1;
+ }
//Enable Interrupts depending on whether this CME is
//a quadManager or siblingCME. DB0 is enabled only
@@ -230,35 +220,25 @@ void p9_cme_pstate_db0_thread(void* arg)
//if quadManager
if (G_cme_pstate_record.qmFlag)
{
-#if !defined(__IOTA__)
- pk_semaphore_create(&G_cme_pstate_record.sem[1], 0, 1);
-#endif
-
if(G_cme_pstate_record.siblingCMEFlag)
{
// Wait for the sibling to boot
intercme_direct(INTERCME_DIRECT_IN1, INTERCME_DIRECT_NOTIFY, 1);
}
- if (G_cme_flags & BIT32(CME_FLAGS_CORE0_GOOD))
+ if (cme_flags & BIT32(CME_FLAGS_CORE0_GOOD))
{
- out32_sh(CME_LCL_EIMR_CLR, BIT64SH(36));//Enable DB0_0
- out32_sh(CME_LCL_EIMR_OR, BIT64SH(37));//Disable DB0_1
- g_eimr_override |= (BIT64(37) | BIT64(11)) ;
- G_cme_pstate_record.cmeMaskGoodCore = CME_MASK_C0;
- cores |= CME_MASK_C0;
+ eimr_clr |= BIT64(10) | BIT64(36); //Enable DB3_0 and DB0_0
+ eimr_or |= BIT64(11) | BIT64(37); //Disable DB3_1 and DB0_1
}
- else if (G_cme_flags & BIT32(CME_FLAGS_CORE1_GOOD))
+ else
{
- out32_sh(CME_LCL_EIMR_OR, BIT64SH(36));//Disable DB0_0
- out32_sh(CME_LCL_EIMR_CLR, BIT64SH(37));//Enable DB0_1
- g_eimr_override |= (BIT64(36) | BIT64(10)) ;
- G_cme_pstate_record.cmeMaskGoodCore = CME_MASK_C1;
- cores |= CME_MASK_C1;
+ eimr_clr |= BIT64(11) | BIT64(37); //Enable DB3_1 and DB0_1
+ eimr_or |= BIT64(10) | BIT64(36); //Disable DB3_0 and DB0_0
}
- out64(CME_LCL_EIMR_OR, BIT64(7) | BIT64(38));//Disable InterCME_IN0/IN1
- g_eimr_override |= (BIT64(7) | BIT64(38));
+ // Disable the intercme messages used by the Sibling
+ eimr_or |= BIT64(7) | BIT64(38);
// Pstate Clocking Initialization (QM)
// Calculate the initial pstate
@@ -279,7 +259,7 @@ void p9_cme_pstate_db0_thread(void* arg)
uint32_t region = pstate_to_vpd_region(G_cme_pstate_record.quadPstate);
// VID compare
scom_data.value = (uint64_t)(pstate_to_vid_compare(G_cme_pstate_record.quadPstate, region)
- & BITS32(24, 8)) << 56;
+ & BITS32(24, 8)) << SHIFT64(7);
// Calculate the new index for each threshold
calc_vdm_threshold_indices(G_cme_pstate_record.quadPstate, region,
G_cme_pstate_record.vdmData.vdm_threshold_idx);
@@ -288,9 +268,9 @@ void p9_cme_pstate_db0_thread(void* arg)
// disabled at this point.
for(i = 0; i < NUM_THRESHOLD_POINTS; ++i)
{
- scom_data.value |= (uint64_t)G_vdm_threshold_table[
- G_cme_pstate_record.vdmData.vdm_threshold_idx[i]]
- << (52 - (i * 4));
+ scom_data.words.upper |= G_vdm_threshold_table[
+ G_cme_pstate_record.vdmData.vdm_threshold_idx[i]]
+ << (SHIFT32(11) - (i * 4));
}
PK_TRACE_INF("qm | initial vdmcfgr=%08x%08x", scom_data.words.upper,
@@ -320,20 +300,10 @@ void p9_cme_pstate_db0_thread(void* arg)
IMT_INIT_PSTATE);
}
}
- else
+ else // Sibling CME
{
- out32_sh(CME_LCL_EIMR_OR, BIT32(4) | BIT32(5));//Disable DB0_0 and DB0_1
-
- if(G_cme_flags & BIT32(CME_FLAGS_CORE0_GOOD))
- {
- G_cme_pstate_record.cmeMaskGoodCore = CME_MASK_C0;
- cores |= CME_MASK_C0;
- }
- else if(G_cme_flags & BIT32(CME_FLAGS_CORE1_GOOD))
- {
- G_cme_pstate_record.cmeMaskGoodCore = CME_MASK_C1;
- cores |= CME_MASK_C1;
- }
+ // Disable all DB0 and DB3 interrupts
+ eimr_or |= BITS64(36, 2) | BITS64(10, 2);
// Sibling set-up for intercme messaging, after this respond to the QMs
// notify to tell him the Sib is ready to go
@@ -341,20 +311,21 @@ void p9_cme_pstate_db0_thread(void* arg)
out32(CME_LCL_EIPR_OR, BIT32(29));
// Wait for QM to send an initial notify
- while(!(in32_sh(CME_LCL_EISR) & BIT32(6)));
+ while(!(in32_sh(CME_LCL_EISR) & BIT64SH(38)));
intercme_direct(INTERCME_DIRECT_IN1, INTERCME_DIRECT_ACK, 0);
intercme_msg_recv(&G_cme_pstate_record.quadPstate, IMT_INIT_PSTATE);
PK_TRACE_INF("sib | initial pstate=%d", G_cme_pstate_record.quadPstate);
- out32(CME_LCL_EIMR_CLR, BIT32(7)); //Enable InterCME_IN0
- g_eimr_override |= BIT64(37); //DB0_C1
- g_eimr_override |= BIT64(36); //DB0_C0
- g_eimr_override |= BIT64(10); //DB3_C0
- g_eimr_override |= BIT64(11); //DB3_C1
+ eimr_clr |= BIT32(7); //Enable InterCME_IN0
}
+ g_eimr_override |= eimr_or;
+ g_eimr_override &= ~eimr_clr;
+ out64(CME_LCL_EIMR_OR, eimr_or);
+ out64(CME_LCL_EIMR_CLR, eimr_clr);
+
// At this point, both QM and Sib can set their initial global Pstate
G_cme_pstate_record.globalPstate = G_cme_pstate_record.quadPstate;
@@ -393,12 +364,12 @@ void p9_cme_pstate_db0_thread(void* arg)
if(G_cme_pstate_record.qmFlag)
{
- G_cme_pstate_record.resclkData.l2_ex0_resclk_idx = curr_idx;
- G_cme_pstate_record.resclkData.l2_ex1_resclk_idx = curr_idx;
-
uint32_t next_idx = p9_cme_resclk_get_index(G_cme_pstate_record.quadPstate);
#if DISABLE_STOP8 == 0
+ G_cme_pstate_record.resclkData.l2_ex0_resclk_idx = curr_idx;
+ G_cme_pstate_record.resclkData.l2_ex1_resclk_idx = curr_idx;
+
// Directly Write QACCR without stepping, prepare for later enablement
// since cores and L2s are currently being overridden with CACCR and EXCGCR
G_cme_pstate_record.resclkData.common_resclk_idx = next_idx;
@@ -433,36 +404,10 @@ void p9_cme_pstate_db0_thread(void* arg)
#endif//USE_CME_VDM_FEATURE
- //Read CME_LCL_FLAGS again
- G_cme_flags = in32(CME_LCL_FLAGS);
-
//Register with PGPE
p9_cme_pstate_register();
- //Doorbell Thread(this thread) will continue to run on
- //Quad Manager CME. The sibling CME has intercme_in0 enabled
- //and won't run this thread past this point.
- if (G_cme_pstate_record.qmFlag)
- {
- PK_TRACE_INF("DB_TH: Inited\n");
-
-#if !defined(__IOTA__)
-
- while(1)
- {
- //pend on sempahore
- pk_semaphore_pend(&G_cme_pstate_record.sem[1], PK_WAIT_FOREVER);
- wrteei(1);
-
- p9_cme_pstate_process_db0();
-
- pk_irq_vec_restore(&ctx);
- }
-
-#endif
- }
-
- PK_TRACE_INF("DB_TH: Exit\n");
+ PK_TRACE_INF("PSTATE: Init Exit\n");
}
//
@@ -471,33 +416,25 @@ void p9_cme_pstate_db0_thread(void* arg)
void p9_cme_pstate_process_db0()
{
ppm_pig_t ppmPigData;
- G_cme_flags = in32(CME_LCL_FLAGS);
G_update_analog_error = 0;
uint64_t scom_data = 0;
- PK_TRACE_INF("DB_TH: Process DB0 Enter\n");
+ PK_TRACE_INF("PSTATE: Process DB0 Enter\n");
//Clear EISR and read DB0 register
- //It's important that we do it in
- if (G_cme_flags & BIT32(CME_FLAGS_CORE0_GOOD))
- {
- out32_sh(CME_LCL_EISR_CLR, BIT64SH(36));
- CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C0, G_dbData.value);
- }
- else if (G_cme_flags & BIT32(CME_FLAGS_CORE1_GOOD))
- {
- out32_sh(CME_LCL_EISR_CLR, BIT64SH(37));
- CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C1, G_dbData.value);
- }
+ out32_sh(CME_LCL_EISR_CLR, BITS64SH(36, 2));
+ CME_GETSCOM(CPPM_CMEDB0, G_cme_pstate_record.firstGoodCoreMask, G_dbData.value);
CME_GETSCOM_OR( CPPM_CSAR, CME_MASK_BC, scom_data );
- if( ( scom_data >> 32 ) & CME_PSTATE_HCODE_ERR_INJ_BIT )
+ if( scom_data & BIT64(CPPM_CSAR_PSTATE_HCODE_ERROR_INJECT) )
{
PK_TRACE_ERR("CME PSTATE ERROR INJECT TRAP");
PK_PANIC(CME_PSTATE_TRAP_INJECT);
}
+ uint32_t cme_flags = in32(CME_LCL_FLAGS);
+
//Ignore if Doorbell0 if DB0_PROCESSING_ENABLE=0. This bit is zero
//upon CME boot. PGPE will set it right before sending Pstate Starts.
//PGPE clears it before ACKing Stop Entry Notify(this CME is about to powered off)
@@ -507,7 +444,7 @@ void p9_cme_pstate_process_db0()
//Process DB0
//Start Pstates and Pstates NOT enabled
if((G_dbData.fields.cme_message_number0 == MSGID_DB0_START_PSTATE_BROADCAST) &&
- (!(G_cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED))))
+ (!(cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED))))
{
//This will Clear EISR[DB0_C0/1] to prevent another DB0 interrupt
//PGPE multicast Global Bcast/Clip Bcast DB0, and it's possible that
@@ -525,14 +462,14 @@ void p9_cme_pstate_process_db0()
//Otherwise, ignore. The reason is PGPE multicasts Global Bcast, and doorbell0
//can be written while this CME is powered-off or or about to be powered-off.
//For Pstate Start and Stop PGPE only unicasts.
- if (G_cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED))
+ if (cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED))
{
p9_cme_pstate_db0_glb_bcast();
}
}
//Stop Pstates and Pstates enabled
else if((G_dbData.fields.cme_message_number0 == MSGID_DB0_STOP_PSTATE_BROADCAST) &&
- (G_cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED)))
+ (cme_flags & BIT32(CME_FLAGS_PSTATES_ENABLED)))
{
p9_cme_pstate_db0_stop();
}
@@ -551,8 +488,8 @@ void p9_cme_pstate_process_db0()
ppmPigData.value = 0;
ppmPigData.fields.req_intr_type = 4;
ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_ERROR;
- send_pig_packet(ppmPigData.value, G_cme_pstate_record.cmeMaskGoodCore);
- PK_TRACE_INF("DB_TH: Bad DB0=0x%x Pstate=0x%x", G_dbData.fields.cme_message_number0, G_cme_flags);
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
+ PK_TRACE_INF("PSTATE: Bad DB0=0x%x", (uint8_t)G_dbData.fields.cme_message_number0);
if(G_dbData.fields.cme_message_number0 < MSGID_DB0_VALID_START ||
G_dbData.fields.cme_message_number0 > MSGID_DB0_VALID_END)
@@ -566,40 +503,34 @@ void p9_cme_pstate_process_db0()
}
}
- PK_TRACE_INF("DB_TH: Process DB0 Exit\n");
+ PK_TRACE_INF("PSTATE: Process DB0 Exit\n");
}
inline void p9_cme_pstate_register()
{
uint32_t done = 0;
+ uint32_t cme_flags = in32(CME_LCL_FLAGS);
G_register_in_progress = 1;
//Quad Manager sends register message to PGPE
if (G_cme_pstate_record.qmFlag)
{
//Clear EISR[DB0_C0/1]
- if (G_cme_flags & BIT32(CME_FLAGS_CORE0_GOOD))
- {
- out32_sh(CME_LCL_EISR_CLR, BIT64SH(36));
- }
- else
- {
- out32_sh(CME_LCL_EISR_CLR, BIT64SH(37));
- }
+ out32_sh(CME_LCL_EISR_CLR, BITS64SH(36, 2));
//Send type4(ack doorbell)
ppm_pig_t ppmPigData;
ppmPigData.value = 0;
ppmPigData.fields.req_intr_type = 4;
ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_QUAD_MGR_AVAILABLE;
- send_pig_packet(ppmPigData.value, G_cme_pstate_record.cmeMaskGoodCore);
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
- PK_TRACE_INF("DB_TH: Register Msg Sent\n");
+ PK_TRACE_INF("PSTATE: Register Msg Sent\n");
- if (G_cme_flags & BIT32(CME_FLAGS_WAIT_ON_PSTATE_START)) //Poll on DB0
+ if (cme_flags & BIT32(CME_FLAGS_WAIT_ON_PSTATE_START)) //Poll on DB0
{
- PK_TRACE_INF("DB_TH: Wait on Pstate Start\n");
+ PK_TRACE_INF("PSTATE: Wait on Pstate Start\n");
//Wait until PGPE has set DB0_PROCESSING_ENABLE. This is important as
//PGPE might send DB0 to other quads as part of processing registration
@@ -607,25 +538,21 @@ inline void p9_cme_pstate_register()
//PGPE has set DB0_PROCESSING_ENABLE
while(!(in32(CME_LCL_SRTCH0) & BIT32(CME_SCRATCH_DB0_PROCESSING_ENABLE)));
+ PK_TRACE_INF("PSTATE: DB0 Processing is Enabled\n");
+
//PGPE will send Pmin, Pmax and Pstate Start Doorbells
//Pstate Start is the last DB0
while(!done)
{
- //Wait until DB0 is written again
- if (G_cme_flags & BIT32(CME_FLAGS_CORE0_GOOD))
- {
- while(!(in32_sh(CME_LCL_EISR) & BIT64SH(36))) {}
+ uint32_t db0_check = G_cme_pstate_record.firstGoodCoreMask << SHIFT64SH(37);
- out32_sh(CME_LCL_EISR_CLR, BIT64SH(36));
- CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C0, G_dbData.value);
- }
- else
- {
- while(!(in32_sh(CME_LCL_EISR) & BIT64SH(37))) {}
+ //Wait until DB0 is written again (looking only at the first good CPPM)
- out32_sh(CME_LCL_EISR_CLR, BIT64SH(37));
- CME_GETSCOM(CPPM_CMEDB0, CME_MASK_C1, G_dbData.value);
- }
+ while(!(in32_sh(CME_LCL_EISR) & db0_check)) {}
+
+ out32_sh(CME_LCL_EISR_CLR, db0_check);
+
+ CME_GETSCOM(CPPM_CMEDB0, G_cme_pstate_record.firstGoodCoreMask, G_dbData.value);
//Process DB0
if((G_dbData.fields.cme_message_number0 == MSGID_DB0_START_PSTATE_BROADCAST))
@@ -646,22 +573,24 @@ inline void p9_cme_pstate_register()
{
uint32_t msgCnt = 0;
- if (G_cme_flags & BIT32(CME_FLAGS_WAIT_ON_PSTATE_START))
+ if (cme_flags & BIT32(CME_FLAGS_WAIT_ON_PSTATE_START))
{
//PGPE sends Pmin, Pmax, and Pstate start DB0, so
//total of three
- PK_TRACE_INF("DB_TH: Wait on Pstate Start\n");
+ PK_TRACE_INF("PSTATE: Wait on Pstate Start\n");
while(msgCnt != 3)
{
PK_TRACE_INF("DB_TH: Sib Register MsgCnt=0x%xt", msgCnt);
p9_cme_pstate_sibling_lock_and_intercme_protocol(1);
msgCnt++;
+ PK_TRACE_INF("PSTATE: Sib Register MsgCnt=%d\n", msgCnt);
}
}
}
G_register_in_progress = 0;
+ PK_TRACE_INF("PSTATE: Register Done\n");
}
//
@@ -669,21 +598,13 @@ inline void p9_cme_pstate_register()
//
void p9_cme_pstate_db0_start()
{
- PK_TRACE_INF("DB_TH: DB0 Start Enter\n");
+ PK_TRACE_INF("PSTATE: DB0 Start Enter\n");
ppm_pig_t ppmPigData;
p9_cme_pstate_update();
-
//Clear EISR[DB0_C0/1] to prevent another interrupt
- if (G_cme_flags & BIT32(CME_FLAGS_CORE0_GOOD))
- {
- out32_sh(CME_LCL_EISR_CLR, BIT32(4));
- }
- else
- {
- out32_sh(CME_LCL_EISR_CLR, BIT32(5));
- }
+ out32_sh(CME_LCL_EISR_CLR, BITS64SH(36, 2));
//Prepare PPM type4 payload for ACK/NACK for PGPE
//Send NACK, if any errors. Otherwise, send ACK
@@ -700,29 +621,28 @@ void p9_cme_pstate_db0_start()
out32(CME_LCL_FLAGS_OR, BIT32(24));//Set Pstates Enabled
- //Clear Pending PMCR interrupts and Enable PMCR Interrupts (for good cores)
- g_eimr_override |= BITS64(34, 2);
- g_eimr_override &= ~(uint64_t)(G_cme_record.core_enabled << 28);
+ //Enable PMCR Interrupts (for good cores) when this task is done
+ g_eimr_override &= ~(uint64_t)(G_cme_record.core_enabled << SHIFT64(35));
//Clear Core GPMMR RESET_STATE_INDICATOR bit to show pstates have started
CME_PUTSCOM(PPM_GPMMR_CLR, G_cme_record.core_enabled, BIT64(15));
}
//Send type4(ack doorbell)
- send_pig_packet(ppmPigData.value, G_cme_pstate_record.cmeMaskGoodCore);
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
//Reset G_update_analog_error
G_update_analog_error = 0;
- PK_TRACE_INF("DB_TH: DB0 Start Exit\n");
+ PK_TRACE_INF("PSTATE: DB0 Start Exit\n");
}
//
//Doorbell0 Global Broadcast
//
-void p9_cme_pstate_db0_glb_bcast(cppm_cmedb0_t dbData)
+void p9_cme_pstate_db0_glb_bcast()
{
- PK_TRACE_INF("DB_TH: DB0 GlbBcast Enter\n");
+ PK_TRACE_INF("PSTATE: DB0 GlbBcast Enter\n");
ppm_pig_t ppmPigData;
p9_cme_pstate_update();
@@ -742,9 +662,9 @@ void p9_cme_pstate_db0_glb_bcast(cppm_cmedb0_t dbData)
}
//Send type4(ack doorbell)
- send_pig_packet(ppmPigData.value, G_cme_pstate_record.cmeMaskGoodCore);
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
G_update_analog_error = 0;
- PK_TRACE_INF("DB_TH: DB0 GlbBcast Exit\n");
+ PK_TRACE_INF("PSTATE: DB0 GlbBcast Exit\n");
}
//
@@ -752,7 +672,7 @@ void p9_cme_pstate_db0_glb_bcast(cppm_cmedb0_t dbData)
//
inline void p9_cme_pstate_db0_stop()
{
- PK_TRACE_INF("DB_TH: DB0 Stop Enter\n");
+ PK_TRACE_INF("PSTATE: DB0 Stop Enter\n");
ppm_pig_t ppmPigData;
out32(CME_LCL_FLAGS_CLR, BIT32(24));//Set Pstates Disabled
@@ -763,27 +683,30 @@ inline void p9_cme_pstate_db0_stop()
//PGPE will update the LMCR[0] before sending the STOP PSTATE Doorbell.
//Here we update the PMSR to indicate that Pstates are no longer honored accordingly.
- p9_cme_pstate_pmsr_updt(G_cme_record.core_enabled);
+ p9_cme_pstate_pmsr_updt();
p9_cme_pstate_notify_sib(); //Notify sibling
//Send type4(ack doorbell)
ppmPigData.value = 0;
ppmPigData.fields.req_intr_type = 4;
ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_PSTATE_SUSPENDED;
- send_pig_packet(ppmPigData.value, G_cme_pstate_record.cmeMaskGoodCore);
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
//Set Core GPMMR RESET_STATE_INDICATOR bit to show pstates have stopped
CME_PUTSCOM(PPM_GPMMR_OR, G_cme_record.core_enabled, BIT64(15));
- PK_TRACE_INF("DB_TH: DB0 Stop Exit\n");
+ PK_TRACE_INF("PSTATE: DB0 Stop Exit\n");
}
-inline void p9_cme_pstate_db0_clip_bcast()
+void p9_cme_pstate_db0_clip_bcast()
{
- PK_TRACE_INF("DB_TH: DB0 Clip Enter\n");
+ PK_TRACE_INF("PSTATE: DB0 Clip Enter\n");
+
ppm_pig_t ppmPigData;
+
uint32_t dbBit8_15 = (G_dbData.value & BITS64(8, 8)) >> SHIFT64(15);
+
uint32_t dbQuadValue = (G_dbData.value >> (in32(CME_LCL_SRTCH0) &
(BITS32(CME_SCRATCH_LOCAL_PSTATE_IDX_START,
CME_SCRATCH_LOCAL_PSTATE_IDX_LENGTH)))) & 0xFF;
@@ -797,7 +720,7 @@ inline void p9_cme_pstate_db0_clip_bcast()
G_cme_pstate_record.pmax = dbQuadValue;
}
- PK_TRACE_INF("DB_TH: Pmin=0x%x,Pmax=0x%x", G_cme_pstate_record.pmin, G_cme_pstate_record.pmax);
+ PK_TRACE_INF("PSTATE: Pmin=0x%x,Pmax=0x%x", G_cme_pstate_record.pmin, G_cme_pstate_record.pmax);
if(G_cme_pstate_record.siblingCMEFlag)
{
@@ -805,21 +728,21 @@ inline void p9_cme_pstate_db0_clip_bcast()
intercme_msg_send(0, IMT_LOCK_SIBLING);
}
- p9_cme_pstate_pmsr_updt(G_cme_record.core_enabled);
+ p9_cme_pstate_pmsr_updt();
p9_cme_pstate_notify_sib(); //Notify sibling
//Send type4(ack doorbell)
ppmPigData.value = 0;
ppmPigData.fields.req_intr_type = 4;
ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_PSTATE_PROTO_ACK;
- send_pig_packet(ppmPigData.value, G_cme_pstate_record.cmeMaskGoodCore);
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
- PK_TRACE_INF("DB_TH: DB0 Clip Exit\n");
+ PK_TRACE_INF("PSTATE: DB0 Clip Exit\n");
}
inline void p9_cme_pstate_db0_pmsr_updt()
{
- PK_TRACE_INF("DB_TH: DB0 Pmsr Updt Enter\n");
+ PK_TRACE_INF("PSTATE: DB0 Pmsr Updt Enter\n");
ppm_pig_t ppmPigData;
uint32_t dbBit8_15 = (G_dbData.value & BITS64(8, 8)) >> SHIFT64(15);
@@ -839,7 +762,7 @@ inline void p9_cme_pstate_db0_pmsr_updt()
break;
}
- p9_cme_pstate_pmsr_updt(G_cme_record.core_enabled);
+ p9_cme_pstate_pmsr_updt();
p9_cme_pstate_notify_sib(); //Notify sibling
@@ -847,17 +770,17 @@ inline void p9_cme_pstate_db0_pmsr_updt()
ppmPigData.value = 0;
ppmPigData.fields.req_intr_type = 4;
ppmPigData.fields.req_intr_payload = MSGID_PCB_TYPE4_ACK_PSTATE_SUSPENDED;
- send_pig_packet(ppmPigData.value, G_cme_pstate_record.cmeMaskGoodCore);
+ send_pig_packet(ppmPigData.value, G_cme_pstate_record.firstGoodCoreMask);
//Set Core GPMMR RESET_STATE_INDICATOR bit to show pstates have stopped
CME_PUTSCOM(PPM_GPMMR_OR, G_cme_record.core_enabled, BIT64(15));
- PK_TRACE_INF("DB_TH: DB0 Safe Mode Exit\n");
+ PK_TRACE_INF("PSTATE: DB0 Safe Mode Exit\n");
}
void p9_cme_pstate_notify_sib()
{
- PK_TRACE_INF("DB_TH: Notify Enter\n");
+ PK_TRACE_INF("PSTATE: Notify Enter\n");
//Notify sibling CME(if any)
if(G_cme_pstate_record.siblingCMEFlag)
@@ -874,27 +797,25 @@ void p9_cme_pstate_notify_sib()
}
-//
-//p9_cme_pstate_freq_update
-//
-inline void p9_cme_pstate_freq_update()
+inline void p9_cme_pstate_freq_update(uint32_t cme_flags)
{
- if(G_cme_flags & BIT32(CME_FLAGS_FREQ_UPDT_DISABLE))
+ if(cme_flags & BIT32(CME_FLAGS_FREQ_UPDT_DISABLE))
{
- PK_TRACE_INF("DB_TH: Freq Updt Disabled\n");
+ PK_TRACE_INF("PSTATE: Freq Updt Disabled\n");
}
else
{
- PK_TRACE_INF("DB_TH: Freq Updt Enter\n");
- PK_TRACE_INF("DB_TH: Dpll0=0x%x\n", G_lppb->dpll_pstate0_value);
- PK_TRACE_INF("DB_TH: Hdr=0x%x, LPPB=0x%x\n", (uint32_t)G_cmeHeader, (uint32_t)G_lppb);
+ PK_TRACE_INF("PSTATE: Freq Updt Enter\n");
+ PK_TRACE_INF("PSTATE: Dpll0=0x%x\n", G_lppb->dpll_pstate0_value);
+ PK_TRACE_INF("PSTATE: Hdr=0x%x, LPPB=0x%x\n", (uint32_t)G_cmeHeader, (uint32_t)G_lppb);
+
//Adjust DPLL
qppm_dpll_freq_t dpllFreq;
//Write new value of DPLL using INTERPPM
//Currently, fmax, fmin and fmult are all written with the same value
dpllFreq.value = 0;
- dpllFreq.fields.fmax = G_lppb->dpll_pstate0_value - G_next_pstate;
+ dpllFreq.fields.fmax = G_lppb->dpll_pstate0_value - G_cme_pstate_record.nextPstate;
dpllFreq.fields.fmult = dpllFreq.fields.fmax;
dpllFreq.fields.fmin = dpllFreq.fields.fmax;
@@ -906,73 +827,26 @@ inline void p9_cme_pstate_freq_update()
ippm_write(QPPM_DPLL_FREQ, dpllFreq.value);
- /*
- // DPLL Modes
- // enable_fmin enable_fmax enable_jump
- // DPLL Mode 2 0 0 0
- // DPLL Mode 3 0 0 1
- // DPLL Mode 4 X 1 0
- // DPLL Mode 4 1 X 0
- // DPLL Mode 3.5 0 1 1
- // DPLL Mode 5 1 X 1
- // TODO Future Attributes
- // DROOP_PROTECT -> DPLL Mode 3
- // DROOP_PROTECT_OVERVOLT -> DPLL Mode 3.5
- // DYNAMIC -> DPLL Mode 4
- // DYNAMIC_PROTECT -> DPLL Mode 5
-
- uint32_t cme_flags = in32(CME_LCL_FLAGS);
- data64_t scom_data = { 0 };
-
- // DPLL Mode 2
- if(!(cme_flags & BIT32(CME_FLAGS_VDM_OPERABLE)))
- {
- PK_TRACE_INF("Poll on DPLL_STAT[freq_change=0]");
-
- // ... to indicate that the DPLL is safely either at the new frequency
- // or in droop protection below the new frequency
- do
- {
- ippm_read(QPPM_DPLL_STAT, &scom_data.value);
- }
- while((scom_data.words.lower & BIT32(29)));
- }
-
- // DPLL Mode 3
- if(cme_flags & BIT32(CME_FLAGS_VDM_OPERABLE))
- {
-
- PK_TRACE_INF("Poll on DPLL_STAT[update_complete=1]");
- // ... to indicate that the DPLL has sampled the newly requested
- // frequency into its internal registers as a target,
- // but may not yet be there
-
- do
- {
- ippm_read(QPPM_DPLL_STAT, &scom_data.value);
- }
- while(!(scom_data.words.lower & BIT32(28)));
- }*/
G_update_analog_error = poll_dpll_stat();
- PK_TRACE_INF("DB_TH: Freq Updt Exit\n");
+ PK_TRACE_INF("PSTATE: Freq Updt Exit\n");
}
}
inline void p9_cme_pstate_update_analog()
{
- // Get the current state of CME flags
- G_cme_flags = in32(CME_LCL_FLAGS);
-
do
{
+
+ uint32_t cme_flags = in32(CME_LCL_FLAGS);
+
#ifdef USE_CME_VDM_FEATURE
// if increasing voltage (decreasing Pstate) then change VDM threshold settings before changing frequency
- if((G_cme_flags & BIT32(CME_FLAGS_VDM_OPERABLE))
- && G_next_pstate < G_cme_pstate_record.quadPstate)
+ if((cme_flags & BIT32(CME_FLAGS_VDM_OPERABLE))
+ && G_cme_pstate_record.nextPstate < G_cme_pstate_record.quadPstate)
{
- G_update_analog_error = p9_cme_vdm_update(G_next_pstate);
+ G_update_analog_error = p9_cme_vdm_update(G_cme_pstate_record.nextPstate);
}
if (G_update_analog_error)
@@ -983,18 +857,15 @@ inline void p9_cme_pstate_update_analog()
#endif //USE_CME_VDM_FEATURE
#ifdef USE_CME_RESCLK_FEATURE
- // protect entire IF BLOCK in a critical section
- // in case a stop11 entry happens during Pstate change
- uint32_t rescurr = (G_cme_flags & BIT32(CME_FLAGS_RCLK_OPERABLE))
+ uint32_t rescurr = (cme_flags & BIT32(CME_FLAGS_RCLK_OPERABLE))
? G_cme_pstate_record.resclkData.common_resclk_idx
: 0;
- uint32_t resnext = (G_cme_flags & BIT32(CME_FLAGS_RCLK_OPERABLE))
- ? p9_cme_resclk_get_index(G_next_pstate)
+ uint32_t resnext = (cme_flags & BIT32(CME_FLAGS_RCLK_OPERABLE))
+ ? p9_cme_resclk_get_index(G_cme_pstate_record.nextPstate)
: 0;
-
if(resnext < rescurr)
{
p9_cme_resclk_update(ANALOG_COMMON, resnext, rescurr);
@@ -1002,12 +873,13 @@ inline void p9_cme_pstate_update_analog()
#endif//USE_CME_RESCLK_FEATURE
- p9_cme_pstate_freq_update();
+ p9_cme_pstate_freq_update(cme_flags);
+ //If error changing DPLL freq, skip the code below
if (G_update_analog_error)
{
break;
- } //If error skip the code below
+ }
#ifdef USE_CME_RESCLK_FEATURE
@@ -1021,10 +893,15 @@ inline void p9_cme_pstate_update_analog()
#ifdef USE_CME_VDM_FEATURE
// if decreasing voltage (increasing Pstate) then change VDM threshold settings after changing frequency
- if((G_cme_flags & BIT32(CME_FLAGS_VDM_OPERABLE))
- && G_next_pstate >= G_cme_pstate_record.quadPstate)
+ if((cme_flags & BIT32(CME_FLAGS_VDM_OPERABLE))
+ && G_cme_pstate_record.nextPstate >= G_cme_pstate_record.quadPstate)
{
- G_update_analog_error = p9_cme_vdm_update(G_next_pstate);
+ G_update_analog_error = p9_cme_vdm_update(G_cme_pstate_record.nextPstate);
+
+ if (G_update_analog_error)
+ {
+ break;
+ }
}
#endif//USE_CME_VDM_FEATURE
@@ -1037,41 +914,40 @@ void p9_cme_pstate_update()
{
PkMachineContext ctx;
- PK_TRACE_INF("DB_TH: Pstate Updt Enter");
+ PK_TRACE_INF("PSTATE: Pstate Updt Enter");
- G_next_pstate = (G_dbData.value >> (in32(CME_LCL_SRTCH0) &
- (BITS32(CME_SCRATCH_LOCAL_PSTATE_IDX_START,
- CME_SCRATCH_LOCAL_PSTATE_IDX_LENGTH)))) & 0xFF;
+ G_cme_pstate_record.nextPstate = (G_dbData.value >> (in32(CME_LCL_SRTCH0) &
+ (BITS32(CME_SCRATCH_LOCAL_PSTATE_IDX_START,
+ CME_SCRATCH_LOCAL_PSTATE_IDX_LENGTH)))) & 0xFF;
G_cme_pstate_record.globalPstate = (G_dbData.value & BITS64(8, 8))
>> SHIFT64(15);
- if(G_next_pstate != G_cme_pstate_record.quadPstate ||
+ if((G_cme_pstate_record.nextPstate != G_cme_pstate_record.quadPstate) ||
G_register_in_progress)
{
if(G_cme_pstate_record.siblingCMEFlag)
{
// "Lock" the sibling until the pstate transition is complete
intercme_msg_send(0, IMT_LOCK_SIBLING);
- // The Sibling is a "pumpkin" from this point forward until calling
- // p9_cme_pstate_notify_sib()
+ // The Sibling is a "pumpkin" from this point forward until
+ // we call p9_cme_pstate_notify_sib()
}
-
- PK_TRACE_INF("DB_TH: DBData=0x%08x%08x\n", G_dbData.value >> 32,
+ PK_TRACE_INF("PSTATE: DBData=0x%08x%08x\n", G_dbData.value >> 32,
G_dbData.value);
- p9_cme_pstate_pmsr_updt_in_progress(G_cme_record.core_enabled);
+ p9_cme_pstate_pmsr_updt_in_progress();
pk_critical_section_enter(&ctx);
p9_cme_pstate_update_analog();
- //Update quadPstate only no error
+ //Update quadPstate only if no error
if(!G_update_analog_error)
{
// Must update quadPstate before calling PMSR update
- G_cme_pstate_record.quadPstate = G_next_pstate;
+ G_cme_pstate_record.quadPstate = G_cme_pstate_record.nextPstate;
}
else
{
@@ -1081,9 +957,9 @@ void p9_cme_pstate_update()
pk_critical_section_exit(&ctx);
}
- p9_cme_pstate_pmsr_updt(G_cme_record.core_enabled);
+ p9_cme_pstate_pmsr_updt();
- p9_cme_pstate_notify_sib(); // Notify Sibling
+ p9_cme_pstate_notify_sib();
- PK_TRACE_INF("DB_TH: Pstate Updt Exit");
+ PK_TRACE_INF("PSTATE: Pstate Updt Exit");
}
OpenPOWER on IntegriCloud