summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Hale <adam.samuel.hale@ibm.com>2017-06-01 14:38:07 -0500
committerJoshua Hunsberger <jahunsbe@us.ibm.com>2017-10-23 17:45:33 -0500
commitd57f2dcda5d972658a2b93d4a6923c262a60e8ed (patch)
tree955e956e76cc9248eca7618ef3e14ffe46a5a419
parentb03e899df8aa67236c6c54a4295911c9366c74cd (diff)
downloadtalos-hcode-d57f2dcda5d972658a2b93d4a6923c262a60e8ed.tar.gz
talos-hcode-d57f2dcda5d972658a2b93d4a6923c262a60e8ed.zip
PGPE Core Throttle Control
Change-Id: Ia53e80231d50594ceba8bf807c2883cf5196d3ae Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/41272 Reviewed-by: Michael S. Floyd <mfloyd@us.ibm.com> Reviewed-by: RAHUL BATRA <rbatra@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c127
-rw-r--r--import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h2
2 files changed, 111 insertions, 18 deletions
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c
index ad2f2ab6..8ec65ed6 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_fit.c
@@ -26,11 +26,19 @@
#include "p9_pgpe_gppb.h"
#include "p9_pgpe_header.h"
-uint8_t G_fit_count_threshold;
-uint8_t G_fit_count;
+#define THROTTLE_SCOM_MULTICAST_READ_OR 0x41010A9E
+#define THROTTLE_SCOM_MULTICAST_READ_AND 0x49010A9E
+#define THROTTLE_SCOM_MULTICAST_WRITE 0x69010A9E
+
+uint32_t G_orig_throttle; //original value of throttle SCOM before manipulation
+uint32_t G_throttleOn; //is throttling currently enabled
+uint32_t G_throttleCount; //how long has throttle been in current state
+
+uint32_t G_beacon_count_threshold;
+uint32_t G_beacon_count;
+
extern GlobalPstateParmBlock* G_gppb;
extern PgpeHeader_t* G_pgpe_header_data;
-
//
//Local function declarations
//
@@ -41,7 +49,6 @@ void p9_pgpe_fit_handler(void* arg, PkIrqId irq);
//
//We set fit_count_threshold based on nest frequency
//and also enable and setup the fit handler
-//
void p9_pgpe_fit_init()
{
// uint16_t freq = G_gppb->nest_frequency_mhz;
@@ -50,7 +57,7 @@ void p9_pgpe_fit_init()
//Set fit count threshold
//\todo Set fit_count threshold correctly RTC: 173170
/*
- G_fit_count_threshold = (freq < 1049) ? 7 :
+ G_beacon_count_threshold = (freq < 1049) ? 7 :
(freq < 1180) ? 8 :
(freq < 1311) ? 9 :
(freq < 1442) ? 10 :
@@ -68,33 +75,117 @@ void p9_pgpe_fit_init()
(freq < 3015) ? 22 :
(freq < 3146) ? 23 : 24;*/
- G_fit_count_threshold = 2;
+ G_throttleCount = 0;
+ G_beacon_count = 0;
+ G_beacon_count_threshold = 2;
ppe42_fit_setup(p9_pgpe_fit_handler, NULL);
}
-//
-//p9_pgpe_fit_handler
-//
-//This is a periodic FIT Handler whose period is determined
-//by GPE_TIMER_SELECT register
-//
+
+__attribute__((always_inline)) inline void handle_core_throttle()
+{
+ do
+ {
+ uint32_t config = in32(OCB_OCCS2); //bits 16-18 in OCC Scratch Register 2
+ uint32_t run = (config >> 14) & 0x3; //this looks at the inject and enable bits, if either are high we run
+
+ if(run) //Currently running
+ {
+ uint32_t value = mfmsr();
+
+ if(G_throttleCount == 0) //when throttle control enabled, read current state of throttle SCOM before manipulation
+ {
+ mtmsr(value | 0x20000000); //don't cause halt if all cores offline
+ G_orig_throttle = in64(THROTTLE_SCOM_MULTICAST_READ_AND) >> 32;
+ uint32_t fail = (((mfmsr() >> 20) & 0x7) == 2); //if all cores online
+ mtmsr(value);
+
+ if(fail)
+ {
+ break;
+ }
+ }
+
+ uint32_t throttleData = G_orig_throttle;
+ uint32_t inject = run & 0x1; //Inject is bit 17, if this is high we run one throttle burst then turn off
+ uint32_t type = (config >> 13) & 0x1; //type is bit 18, this determines which kind of throttling we do
+ uint32_t mask = type ? 0x10000000 : 0x80000000;
+ uint32_t pgpe_throttle_assert = G_pgpe_header_data->g_pgpe_throttle_assert;
+ uint32_t pgpe_throttle_deassert = G_pgpe_header_data->g_pgpe_throttle_deassert;
+
+ //if currently off, we don't desire always off, this is the first evaluation since become enabled, we are in always on,
+ //or we (re enabled and have reached the count, then we turn throttling on (if both assert and deassert are 0 this statement fails)
+ if(!G_throttleOn && pgpe_throttle_assert != 0 &&
+ (G_throttleCount == 0 || pgpe_throttle_deassert == 0 || pgpe_throttle_deassert == G_throttleCount))
+ {
+ G_throttleOn = 1;
+ G_throttleCount = 0;
+ throttleData |= mask; //data for start throttle
+
+ }
+ //if currently on and we desire always off or we don't desire always on and have reached the count,
+ //then we turn it off (if both assert and deassert are 0 this statement true)
+ else if(G_throttleOn &&
+ (pgpe_throttle_assert == 0 || ( pgpe_throttle_deassert != 0 && pgpe_throttle_assert == G_throttleCount)))
+ {
+ G_throttleOn = 0;
+ G_throttleCount = 0;
+ throttleData &= ~mask; //data for stop throttle
+
+ if(inject == 1)
+ {
+ out32(OCB_OCCS2, (config & 0xFFFFBFFF)); //write out to indicate inject has finished
+ }
+ }
+
+ if(G_throttleCount == 0)
+ {
+ mtmsr(value | 0x20000000); //don't cause halt if all cores offline
+ out64(THROTTLE_SCOM_MULTICAST_WRITE, ((uint64_t) throttleData << 32)); //apply new throttle SCOM setting
+ mtmsr(value);
+ }
+
+ G_throttleCount++; //count always incremented, it is impossible to reach a count of 0 while enabled
+ }
+ else if(G_throttleCount != 0)
+ {
+ G_throttleCount = 0;
+ uint32_t value = mfmsr();
+ mtmsr(value | 0x20000000); //don't cause halt if all cores offline
+ G_throttleOn = 0;
+ out64(THROTTLE_SCOM_MULTICAST_WRITE, ((uint64_t) G_orig_throttle << 32)); //restore throttle scom to original state
+ mtmsr(value);
+ }
+ }
+ while(0);
+}
+
//PGPE beacon needs to be written every 2ms. However, we
//set the FIT interrupt period smaller than that, and
-//update PGPE beacon only when we have seen "G_fit_count_threshold"
+//update PGPE beacon only when we have seen "G_beacon_count_threshold"
//number of FIT interrupts
-//
-void p9_pgpe_fit_handler(void* arg, PkIrqId irq)
+__attribute__((always_inline)) inline void handle_occ_beacon()
{
- if (G_fit_count == G_fit_count_threshold)
+ if (G_beacon_count == G_beacon_count_threshold)
{
//write to SRAM
*(G_pgpe_header_data->g_pgpe_beacon_addr) = *(G_pgpe_header_data->g_pgpe_beacon_addr) + 1;
- G_fit_count = 0;
+ G_beacon_count = 0;
}
else
{
- G_fit_count++;
+ G_beacon_count++;
}
+}
+//p9_pgpe_fit_handler
+//
+//This is a periodic FIT Handler whose period is determined
+//by GPE_TIMER_SELECT register
+void p9_pgpe_fit_handler(void* arg, PkIrqId irq)
+{
+ mtmsr(PPE42_MSR_INITIAL);
+ handle_occ_beacon();
+ handle_core_throttle();
}
diff --git a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h
index 1dea8e2c..e88f7b79 100644
--- a/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h
+++ b/import/chips/p9/procedures/ppe_closed/pgpe/pstate_gpe/p9_pgpe_header.h
@@ -57,6 +57,8 @@ typedef struct
uint32_t* g_req_active_quad_addr; //Requested Active Quads Address
uint32_t* g_wof_table_addr; // WOF Table Address
uint32_t g_wof_table_length; // WOF Table Length
+ uint32_t g_pgpe_throttle_assert;
+ uint32_t g_pgpe_throttle_deassert;
} PgpeHeader_t;
void p9_pgpe_header_init();
OpenPOWER on IntegriCloud