summaryrefslogtreecommitdiffstats
path: root/src/occ_405/proc
diff options
context:
space:
mode:
authorWael El-Essawy <welessa@us.ibm.com>2016-12-09 18:28:26 -0600
committerWael El-Essawy <welessa@us.ibm.com>2017-01-27 12:00:02 -0500
commit360934dea9355e488206267d7f9fd9b1c753cf16 (patch)
treed5fb9e4ae46b9b9afe9adca7b1e0ac72e5d7219a /src/occ_405/proc
parentc35e73bb81af40e6cca73b35ea8db61a8f17f5a8 (diff)
downloadtalos-occ-360934dea9355e488206267d7f9fd9b1c753cf16.tar.gz
talos-occ-360934dea9355e488206267d7f9fd9b1c753cf16.zip
Pstates Support in OCC
1. Initialize Pstates global parameters (G_proc_fmax, G_proc_fmin, G_khz_per_pstate and G_proc_pmin from the OCC Pstate Parameter Block) 2. When frequency config data packet is received and OCC is NOT already in Active state: Send IPC command to PGPE to set pState clips to be wide open from min frequency to turbo First verify min/max frequency from TMGT is within what PGPE allows saved in G_proc_fmax and G_proc_fmin if not within bounds trace and clip to G_proc_fmax/fmin) 3. Transition to active state: Send IPC command to PGPE to start pState protocol (give correct data for OCC vs OPAL in control of Pstates) and if OPAL system update OPAL shared memory with Pstate information. 4. amec_slv_freq_smh(): Send IPC command to PGPE to set requested pState (PowerVM) or set clips (OPAL). 5. Address all the TODO/TEMP/#if 0 in amec_freq.c either remove or add RTC# for when it will be addressed Change-Id: Ic323321b8c66945732a6b7345ad85d6f41a62edd RTC: 130201 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33704 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Reviewed-by: Andres A. Lugo-Reyes <aalugore@us.ibm.com> Reviewed-by: Wael El-Essawy <welessa@us.ibm.com>
Diffstat (limited to 'src/occ_405/proc')
-rwxr-xr-xsrc/occ_405/proc/proc_data.c9
-rwxr-xr-xsrc/occ_405/proc/proc_data_control.c287
-rwxr-xr-xsrc/occ_405/proc/proc_data_control.h27
-rwxr-xr-xsrc/occ_405/proc/proc_pstate.c245
-rwxr-xr-xsrc/occ_405/proc/proc_pstate.h37
5 files changed, 282 insertions, 323 deletions
diff --git a/src/occ_405/proc/proc_data.c b/src/occ_405/proc/proc_data.c
index 0a0b528..4de6925 100755
--- a/src/occ_405/proc/proc_data.c
+++ b/src/occ_405/proc/proc_data.c
@@ -35,6 +35,7 @@
#include "apss.h"
#include "state.h"
#include "proc_data_control.h"
+#include "pgpe_interface.h"
#include "cmdh_fsp.h"
#include "sensor.h"
@@ -319,7 +320,8 @@ void proc_core_init( void )
// cores are present and configured. The Core Configuration Status Register
// has this information, so we will need to read it over OCI.
uint64_t l_ccsr_val = in64(OCB_CCSR);
- MAIN_TRAC_INFO("proc_core_init: CCSR read 0x%08X%08X", (uint32_t) (l_ccsr_val>>32), (uint32_t) l_ccsr_val);
+ MAIN_TRAC_INFO("proc_core_init: CCSR read 0x%08X%08X",
+ (uint32_t) (l_ccsr_val>>32), (uint32_t) l_ccsr_val);
G_present_hw_cores = ((uint32_t) (l_ccsr_val >> 32)) & HW_CORES_MASK;
G_present_cores = G_present_hw_cores;
@@ -405,9 +407,8 @@ void proc_core_init( void )
} while(0);
- // Initialize the core data control structures at the same time
-// TEMP/TODO: Needs to be re-enabled when the data control task is enabled
-// proc_core_data_control_init();
+ // Initialize the core data control at the same time
+ init_pgpe_ipcs();
return;
}
diff --git a/src/occ_405/proc/proc_data_control.c b/src/occ_405/proc/proc_data_control.c
index c68b422..38165ac 100755
--- a/src/occ_405/proc/proc_data_control.c
+++ b/src/occ_405/proc/proc_data_control.c
@@ -24,6 +24,7 @@
/* IBM_PROLOG_END_TAG */
#include "proc_data.h"
+#include "proc_data_control.h"
#include "occhw_async.h"
#include "threadSch.h"
#include "pmc_register_addresses.h"
@@ -35,231 +36,147 @@
#include "apss.h"
#include "state.h"
#include "occ_sys_config.h"
+#include "p9_pstates_common.h"
+#include "pgpe_interface.h"
+#include "rtls_service_codes.h"
-// Pore flex request for GPE job. The initialization will be done one time
-// during pore flex create.
-PoreFlex G_core_data_control_req;
+// The the GPE parameter fields for PGPE IPC calls.
+extern GPE_BUFFER(ipcmsg_clip_update_t* G_clip_update_parms_ptr);
+extern GPE_BUFFER(ipcmsg_set_pmcr_t* G_pmcr_set_parms_ptr);
-// Global double buffering for core data control
-GPE_BUFFER(PcbsPstateRegs G_core_data_control_a[MAX_NUM_HW_CORES]) = {{{0}}};
-GPE_BUFFER(PcbsPstateRegs G_core_data_control_b[MAX_NUM_HW_CORES]) = {{{0}}};
-
-// Pointer to the core data control that will be used by GPE engine.
-GPE_BUFFER(PcbsPstateRegs * G_core_data_control_gpewrite_ptr) = { &G_core_data_control_a[0] };
-
-// Pointer to the core data control that will be written to by the OCC FW.
-GPE_BUFFER(PcbsPstateRegs * G_core_data_control_occwrite_ptr) = { &G_core_data_control_b[0] };
+extern GpeRequest G_clip_update_req;
+extern GpeRequest G_pmcr_set_req;
-// The Gpe parameter fields are set up each time before the GPE starts.
-GPE_BUFFER(GpeSetPstatesParms G_core_data_control_parms);
+// create gpe request for GPE job. The initialization will be done one time
+// during gpe request create.
+GpeRequest G_core_data_control_req;
-// Function Specification
-//
-// Name: proc_set_pstate
-//
-// Description: Function to demonstrate setting Pstates to all cores
-// Should only be run from RTL
-//
-// End Function Specification
-void proc_set_pstate_all(Pstate i_pstate)
-{
- uint8_t l_chiplet = 0;
+// Global double buffering for core data control
+GPE_BUFFER(PstatesClips G_quads_data_control[2]) = {{{{0}}}};
- for(; l_chiplet<MAX_NUM_HW_CORES; l_chiplet++)
- {
- set_chiplet_pstate(G_core_data_control_occwrite_ptr,
- l_chiplet,
- i_pstate,
- i_pstate);
- }
+// Pointer to the core data control that will be written to by the OCC FW.
+GPE_BUFFER(PstatesClips* G_core_data_control_occwrite_ptr) = { &G_quads_data_control[0] };
- PROC_DBG("Setting Pstates to %d\n",i_pstate);
-}
+// Pointer to the core data control that will be used by GPE engine.
+GPE_BUFFER(PstatesClips* G_core_data_control_gpewrite_ptr) = { &G_quads_data_control[1] };
// Function Specification
//
-// Name: proc_set_core_pstate
+// Name: task_core_data_control
//
-// Description: Function to demonstrate setting Pstates to all cores
-// Should only be run from RTL
+// Description: Control quad actuation for all configured cores on every tick.
//
// End Function Specification
-void proc_set_core_pstate(Pstate i_pstate, uint8_t i_core)
+void task_core_data_control( task_t * i_task )
{
- set_chiplet_pstate(G_core_data_control_occwrite_ptr,
- CORE_OCC2HW(i_core),
- i_pstate,
- i_pstate);
-}
+ errlHndl_t err = NULL; //Error handler
+ PstatesClips* l_temp = NULL;
-// Function Specification
-//
-// Name: proc_set_core_bounds
-//
-// Description: Function to set core pmin/pmax
-// Should only be run from RTL
-//
-// End Function Specification
-void proc_set_core_bounds(Pstate i_pmin, Pstate i_pmax, uint8_t i_core)
-{
- Pstate l_pmax;
- uint8_t l_hw_core = CORE_OCC2HW(i_core);
+/////////////////////////////////////////////////////////////////
- //don't allow pmax to be set lower than pmin
- if(i_pmax < i_pmin)
- {
- l_pmax = i_pmin;
- }
- else
+ // perform Pstate/clip control if previous IPC call completed successfully
+ // if not idle, ignore cycle
+ // if an error was returned, log an error, and request reset
+ if(G_sysConfigData.system_type.kvm) // OPAL system
{
- l_pmax = i_pmax;
- }
+ // confirm that the clip update IPC from last cycle
+ // has successfully completed on PGPE (with no errors)
+ if( async_request_is_idle(&G_clip_update_req.request) && //clip_update/widen_clip_ranges completed
+ (G_clip_update_parms_ptr->msg_cb.rc == PGPE_RC_SUCCESS) ) // with no errors
+ {
- set_chiplet_pmax(G_core_data_control_occwrite_ptr,
- l_hw_core,
- l_pmax);
- set_chiplet_pmin(G_core_data_control_occwrite_ptr,
- l_hw_core,
- i_pmin);
-}
+ //The previous OPAL PGPE request succeeded:
+ //1) swap gpewrite ptr with the occwrite ptr (double buffering).
+ l_temp = G_core_data_control_occwrite_ptr;
+ G_core_data_control_occwrite_ptr = G_core_data_control_gpewrite_ptr;
+ G_core_data_control_gpewrite_ptr = l_temp;
-// Function Specification
-//
-// Name: proc_core_data_control_init
-//
-// Description: Initializations needed for core data control task
-//
-// End Function Specification
-void proc_core_data_control_init( void )
-{
- errlHndl_t l_err = NULL; //Error handler
- tracDesc_t l_trace = NULL; //Temporary trace descriptor
- int rc = 0; //Return code
+ //2) Set clip values from gpewrite's quad clips data-structure
+ G_clip_update_parms_ptr = &G_core_data_control_gpewrite_ptr->clips;
- do
- {
- //FIXME: Need to change this to use PGPE queue
- //Initializes PoreFlex object for pstate control
- rc = pore_flex_create( &G_core_data_control_req, //gpe_req for the task
- &G_pore_gpe0_queue, //queue
- gpe_set_pstates, //entry point
- (uint32_t) &G_core_data_control_parms, //parm for the task
- SSX_WAIT_FOREVER, //no timeout
- NULL, //callback
- NULL, //callback argument
- 0 ); //options
- if( rc )
+ //call PGPE IPC function to update the clips
+ pgpe_clip_update();
+ }
+ else if(G_clip_update_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS)
{
- //If fail to create pore flex object then there is a problem.
- TRAC_ERR("Fail to create core control poreFlex object[0x%x]", rc );
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("task_core_data_control: clip update IPC task returned an error, %d",
+ G_clip_update_parms_ptr->msg_cb.rc);
/*
* @errortype
- * @moduleid PROC_CORE_INIT_MOD
- * @reasoncode SSX_GENERIC_FAILURE
- * @userdata1 pore_flex_create return code
- * @userdata4 ERC_PROC_CONTROL_INIT_FAILURE
- * @devdesc Failure to create poreflex object
+ * @moduleid RTLS_TASK_CORE_DATA_CONTROL_MOD
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 rc
+ * @userdata2 idle?
+ * @userdata4 ERC_PGPE_UNSUCCESSFULL
+ * @devdesc pgpe clip update returned an error
*/
- l_err = createErrl(
- PROC_CORE_INIT_MOD, //modId
- SSX_GENERIC_FAILURE, //reasoncode
- ERC_PROC_CONTROL_INIT_FAILURE, //Extended reason code
- ERRL_SEV_PREDICTIVE, //Severity
- l_trace, //TODO: create l_trace //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- rc, //userdata1
- 0 //userdata2
- );
-
- // commit error log
- REQUEST_RESET(l_err); //$gm006
- break;
+ err = createErrl(
+ RTLS_TASK_CORE_DATA_CONTROL_MOD, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_UNSUCCESSFULL, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ G_clip_update_parms_ptr->msg_cb.rc, //Userdata1
+ async_request_is_idle(&G_clip_update_req.request) //Userdata2
+ );
}
-
- } while(0);
-}
-
-// Function Specification
-//
-// Name: task_core_data_control
-//
-// Description: Control core actuation for all configured cores on every tick.
-//
-// End Function Specification
-void task_core_data_control( task_t * i_task )
-{
-//TEMP/TODO: proc_core_data_control_init needs to be called from proc_core_init()
-// when this task is enabled for it to function properly.
- errlHndl_t l_err = NULL; //Error handler
- tracDesc_t l_trace = NULL; //Temporary trace descriptor
- int rc = 0; //Return code
- PcbsPstateRegs * l_temp = NULL;
-
- do
+ }
+ else
{
-
- //Check to see if the previous GPE request still running
- if( !(async_request_is_idle(&G_core_data_control_req.request)) )
+ // NON OPAL System, OCC owns PMCR:
+ if( async_request_is_idle(&G_pmcr_set_req.request) && // PMCR IPC from last TICK completed
+ (G_pmcr_set_parms_ptr->msg_cb.rc == PGPE_RC_SUCCESS) ) // with no errors
{
- break;
- }
+ //The previous Non-OPAL PGPE request succeeded:
- //Check to see if the previosuly GPE request has been succeeded
- if( async_request_completed(&G_core_data_control_req.request) )
- {
- //If the previous GPE request succeeded then swap the
- //gpewrite ptr with the occwrite ptr.
+ //1) swap gpewrite ptr with the occwrite ptr (double buffering).
l_temp = G_core_data_control_occwrite_ptr;
+ G_core_data_control_occwrite_ptr = G_core_data_control_gpewrite_ptr;
G_core_data_control_gpewrite_ptr = l_temp;
- }
- //Setup the core data control parms
- G_core_data_control_parms.config = (uint64_t) (((uint64_t) G_present_hw_cores) << 32);
- if(G_sysConfigData.system_type.kvm)
- {
- //Set the chiplet bounds (pmax/pmin) only on opal
- G_core_data_control_parms.select = GPE_SET_PSTATES_PMBR;
- }
- else
- {
- //Set the chiplet pstate request on non-opal systems
- G_core_data_control_parms.select = GPE_SET_PSTATES_PMCR;
- }
-
- G_core_data_control_parms.regs = (uint32_t) G_core_data_control_gpewrite_ptr;
+ //2) Set Pstate values from gpewrite's quad pstates data-structure
+ G_pmcr_set_parms_ptr = &G_core_data_control_gpewrite_ptr->pstates;
- rc = pore_flex_schedule( &G_core_data_control_req );
- if( rc != 0 )
+ //call PGPE IPC function to update Pstates
+ pgpe_pmcr_set();
+ }
+ else if(G_pmcr_set_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS)
{
- TRAC_ERR("Failed PoreFlex schedule core data control [%x] \n", rc);
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("task_core_data_control: pstate update IPC task returned an error, %d",
+ G_pmcr_set_parms_ptr->msg_cb.rc);
/*
* @errortype
- * @moduleid PROC_TASK_CORE_DATA_MOD
- * @reasoncode SSX_GENERIC_FAILURE
- * @userdata1 pore_flex_schedule return code
- * @userdata4 ERC_PROC_CONTROL_TASK_FAILURE
- * @devdesc Failure to schedule poreflex object
+ * @moduleid RTLS_TASK_CORE_DATA_CONTROL_MOD
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 rc
+ * @userdata4 ERC_PGPE_UNSUCCESSFULL
+ * @devdesc pgpe PMCR set returned an error
*/
- l_err = createErrl(
- PROC_TASK_CORE_DATA_MOD, //modId
- SSX_GENERIC_FAILURE, //reasoncode
- ERC_PROC_CONTROL_TASK_FAILURE, //Extended reason code
- ERRL_SEV_PREDICTIVE, //Severity
- l_trace, //TODO: create l_trace //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- rc, //userdata1
- 0 //userdata2
- );
-
- // commit error log
- REQUEST_RESET(l_err);
- break;
+ err = createErrl(
+ RTLS_TASK_CORE_DATA_CONTROL_MOD, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_UNSUCCESSFULL, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ G_pmcr_set_parms_ptr->msg_cb.rc, //Userdata1
+ 0 //Userdata2
+ );
}
- } while(0);
+ }
+
+ if(err)
+ {
+ // commit error log
+ REQUEST_RESET(err);
+ }
return;
}
diff --git a/src/occ_405/proc/proc_data_control.h b/src/occ_405/proc/proc_data_control.h
index ec65c2f..4188c08 100755
--- a/src/occ_405/proc/proc_data_control.h
+++ b/src/occ_405/proc/proc_data_control.h
@@ -30,21 +30,26 @@
#include <ssx.h>
#include "rtls.h"
#include "p9_pstates_common.h"
+#include "pstate_pgpe_occ_api.h"
-//#include "gpe_control.h"
+/// Per-quad Pstate/Clip control data-structure
+///
+/// Firmware maintains a copy of PstateClipStruct structures - with an entry
+/// for each quad on the chip - and updates the pstate/clip fields in place.
+/// The PGPE IPC procedures (MSGID_405_SET_PMCR and MSGID_405_CLIPS)
+/// are run periodically to update the core psates or clips control values
+/// from this data structure. The array can (should) be cleared initially.
+typedef struct {
-// Initialze the structures used by the GPE
-void proc_core_data_control_init( void );
+ /// The Pstate control values
+ ipcmsg_set_pmcr_t pstates;
-// Task that sets the PMCR, PMBR, PMICR
-void task_core_data_control( task_t * i_task );
+ /// The clipping values
+ ipcmsg_clip_update_t clips;
-// Function to demonstrate setting Pstates to all cores
-void proc_set_pstate_all(Pstate i_pstate);
+} PstatesClips;
-// Function to demonstrate setting Pstates one core
-void proc_set_core_pstate(Pstate i_pstate, uint8_t i_core);
+// Task that sets the PMCR, PMBR, PMICR
+void task_core_data_control( task_t * i_task );
-// Sets the Pmin/Pmax clip values for one core
-void proc_set_core_bounds(Pstate i_pmin, Pstate i_pmax, uint8_t i_core);
#endif
diff --git a/src/occ_405/proc/proc_pstate.c b/src/occ_405/proc/proc_pstate.c
index d63c96f..15b66d8 100755
--- a/src/occ_405/proc/proc_pstate.c
+++ b/src/occ_405/proc/proc_pstate.c
@@ -40,30 +40,28 @@
#include <common.h>
#include <amec_oversub.h>
#include <amec_sys.h>
+#include <pstate_pgpe_occ_api.h>
+#include <p9_pstates_occ.h>
//OPAL processor and memory throttle reason coming from the frequency voting boxes.
extern opal_proc_voting_reason_t G_amec_opal_proc_throt_reason;
extern opal_mem_voting_reason_t G_amec_opal_mem_throt_reason;
-// Holds Fmax for ease of proc_freq2pstate calculation
-uint32_t G_proc_fmax = 0;
+//Global OCC Pstate Parameters Block Structure
+extern OCCPstateParmBlock G_oppb;
-// Holds Fmin for ease of proc_freq2pstate calculation
-uint32_t G_proc_fmin = 0;
+//Holds Fmax for ease of proc_freq2pstate calculation = max(fturbo,futurbo)
+uint16_t G_proc_fmax_mhz;
-// Holds frequency steps between consequtive Pstates
-uint32_t G_khz_per_pstate = 0;
+// A global variable indicating whether the pstates have been enabled.
+// initialized to PSTATES_DISABLED, turns to PSTATES_ENABLED only after
+// the PGPE IPC that enable pstates completes successfully. While the IPC
+// task is still running, this variable be set to PSTATES_IN_TRANSITION
+pstateStatus G_proc_pstate_status = PSTATES_DISABLED;
-// Holds Pmax for ease of proc_freq2pstate calculation
-uint8_t G_proc_pmax = 0;
-// Holds Pmin for ease of proc_freq2pstate calculation
-uint8_t G_proc_pmin = 0;
-
-// Holds a flag indicating whether the pstates have been enabled.
-// initialized to FALSE, turns TRUE only after the PGPE IPC that
-// enable pstates completes successfully.
-bool G_proc_pstate_enabled = FALSE;
+// A Global parameter indicating the owner of the PMCR.
+PMCR_OWNER G_proc_pmcr_owner = G_sysConfigData.system_type.kvm? PMCR_OWNER_HOST: PMCR_OWNER_HOST;
// OPAL Dynamic data, updated whenever any OCC G_opal_table.dynamic parameter change
DMA_BUFFER( opal_dynamic_table_t G_opal_dynamic_table ) = {{0}};
@@ -81,7 +79,7 @@ DMA_BUFFER( opal_static_table_t G_opal_static_table ) = {{0}};
// End Function Specification
bool proc_is_hwpstate_enabled(void)
{
- return ( G_proc_pstate_enabled ? TRUE : FALSE);
+ return ( G_proc_pstate_status == PSTATES_ENABLED ? TRUE : FALSE);
}
// Function Specification
@@ -93,20 +91,16 @@ bool proc_is_hwpstate_enabled(void)
// End Function Specification
uint32_t proc_pstate2freq(Pstate i_pstate)
{
- // If passed in Pstate is lower than Pmin, just use Pmin
- if(i_pstate < G_proc_pmin)
- {
- i_pstate = G_proc_pmin;
- }
-
- // If passed in Pstate is greater than Pmax, just use Pmax
- else if (i_pstate > G_proc_pmax)
+ // The higher the pstate number, the lower the frequency:
+ // If passed in Pstate is lower than Pmin (higher pstate value),
+ // just use Pmin.
+ if(i_pstate > G_oppb.pstate_min)
{
- i_pstate = G_proc_pmax;
+ i_pstate = G_oppb.pstate_min;
}
// Calculate Frequency in kHz based on Pstate
- return (G_proc_fmin + (G_proc_pmin - i_pstate) * G_khz_per_pstate);
+ return ( G_oppb.frequency_max_khz - (i_pstate * G_oppb.frequency_step_khz));
}
// Function Specification
@@ -135,29 +129,21 @@ Pstate proc_freq2pstate(uint32_t i_freq_mhz)
l_freq_khz = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY] * 1000;
}
- if(l_freq_khz < G_proc_fmax)
+ if(l_freq_khz < G_proc_fmax_mhz * 1000)
{
// First, calculate the delta between passed in freq, and Pmin
- l_temp_freq = l_freq_khz - G_proc_fmin;
-
- // Check if the passed in frequency is lower than Minimum Frequency
- if(l_freq_khz <= G_proc_fmin)
- {
- // We need to substract a full step (minus 1) to make sure we
- // are keeping things safe
- l_temp_freq -= (G_khz_per_pstate - 1);
- }
+ l_temp_freq = l_freq_khz - G_oppb.frequency_min_khz;
// Next, calculate how many Pstate steps there are in that delta
- l_temp_pstate = l_temp_freq / (int32_t) G_khz_per_pstate;
+ l_temp_pstate = l_temp_freq / (int32_t) G_oppb.frequency_step_khz;
// Lastly, calculate Pstate, by adding delta Pstate steps to Pmin
- l_pstate = G_proc_pmin - l_temp_pstate;
+ l_pstate = G_oppb.pstate_min - l_temp_pstate;
}
else
{
// Freq is higher than maximum frequency -- return Pmax
- l_pstate = G_proc_pmax;
+ l_pstate = PMAX + (G_oppb.frequency_max_khz - G_proc_fmax_mhz*1000)/G_oppb.frequency_step_khz;
}
}
while(0);
@@ -183,11 +169,13 @@ void proc_pstate_kvm_setup()
break;
}
+ TRAC_INFO("proc_pstate_kvm_setup: populate static OPAL data");
+
// Initialize the opal table in SRAM (sets valid bit)
- populate_static_opal_data();
+ populate_opal_static_data();
// copy sram image into mainstore HOMER
- populate_opal_tbl_to_mem();
+ populate_opal_tbl_to_mem(OPAL_STATIC);
TRAC_IMP("proc_pstate_kvm_setup: RUNNING IN KVM MODE");
}while(0);
@@ -195,12 +183,12 @@ void proc_pstate_kvm_setup()
// Function Specification
//
-// Name: populate_dynamic_opal_data
+// Name: populate_opal_dynamic_data
//
// Description: populate the dynamic data entries in the OPAL table
//
// End Function Specification
-void populate_dynamic_opal_data()
+void populate_opal_dynamic_data()
{
memset(&G_opal_dynamic_table, 0, sizeof(G_opal_dynamic_table));
@@ -228,18 +216,33 @@ void populate_dynamic_opal_data()
// Function Specification
//
-// Name: populate_static_opal_data
+// Name: populate_opal_static_data
//
// Description: populate the static configuration entries,
// the generated pstates table, and maximum pstates
// for all possible number of active cores.
//
// End Function Specification
-void populate_static_opal_data()
+void populate_opal_static_data()
{
- memset(&G_opal_dynamic_table, 0, sizeof(G_opal_dynamic_table));
+ // clear all entries of the OPAL static table
+ memset(&G_opal_static_table, 0, sizeof(G_opal_static_table));
+
+ populate_opal_static_config_data();
+ populate_opal_static_pstates_data();
+}
+
+// Function Specification
+//
+// Name: populate_opal_static_config_data
+//
+// Description: populate the static configuration entries,
+//
+// End Function Specification
+void populate_opal_static_config_data(void)
+{
// Static OPAL configuration data
G_opal_static_table.config.valid = 1;
G_opal_static_table.config.version = 0x90;
@@ -247,43 +250,90 @@ void populate_static_opal_data()
G_opal_static_table.config.pmin = pmin_rail();
G_opal_static_table.config.pnominal = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]);
G_opal_static_table.config.pturbo = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]);
- G_opal_static_table.config.puturbo = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_UTURBO]);
+ G_opal_static_table.config.puturbo = proc_freq2pstate(G_proc_fmax_mhz);
+}
+
+// Function Specification
+//
+// Name: populate_opal_static_data
+//
+// Description: populate the generated pstates table, and maximum
+// pstates for all possible number of active cores.
+//
+// End Function Specification
+void populate_opal_static_pstates_data(void)
+{
+ uint16_t i; // loop variable
+ for (i=0; i <= G_oppb.pstate_min; i++)
+ {
+ G_opal_static_table.pstates[i].pstate = i; // pstate number
+ G_opal_static_table.pstates[i].flag = 0; // flag is reserved for future use
+ G_opal_static_table.pstates[i].freq_khz = proc_pstate2freq(i); // pstate's frequency
+ }
- // TODO - RTC:130201 generate pstates table & Max pstates for var #cores
+ for (i=0; i<MAX_NUM_CORES; i++)
+ {
+ // TODO - RTC:130216 fix entries for WOF systems
+ G_opal_static_table.max_pstate[i] = G_opal_static_table.config.pturbo;
+ }
}
// Function Specification
//
// Name: populate_opal_tbl_to_mem
//
-// Description:
+// Description: use the upload copy engine to copy OPAL
+// OPAL table's static/dynamic entries to main memory.
//
// End Function Specification
-void populate_opal_tbl_to_mem()
+void populate_opal_tbl_to_mem(opalDataType opal_data_type)
{
int l_ssxrc = SSX_OK;
uint32_t l_reasonCode = 0;
uint32_t l_extReasonCode = 0;
+ uint32_t mainstore_address;
+ uint32_t sram_address;
+ size_t block_size;
+
+ if(opal_data_type == OPAL_STATIC)
+ {
+ mainstore_address = OPAL_STATIC_ADDRESS_HOMER;
+ sram_address = (uint32_t) &G_opal_static_table;
+ block_size = (size_t) sizeof(G_opal_static_table);
+ }
+ else if(opal_data_type == OPAL_DYNAMIC)
+ {
+ mainstore_address = OPAL_DYNAMIC_ADDRESS_HOMER;
+ sram_address =(uint32_t) &G_opal_dynamic_table;
+ block_size = (size_t) sizeof(G_opal_dynamic_table);
+ }
+ else
+ {
+ TRAC_ERR("populate_opal_tbl_to_mem: Invalid OPAL Table data type");
+ return;
+ }
+
do
{
BceRequest pba_copy;
// Set up copy request
l_ssxrc = bce_request_create(
- &pba_copy, // block copy object
- &G_pba_bcue_queue, // sram to mainstore copy engine
- OPAL_DYNAMIC_ADDRESS_HOMER, // mainstore address
- (uint32_t) &G_opal_dynamic_table, // sram starting address
- (size_t) sizeof(G_opal_dynamic_table), // size of copy
- SSX_WAIT_FOREVER, // no timeout
- NULL, // call back
- NULL, // call back arguments
- ASYNC_REQUEST_BLOCKING // callback mask
+ &pba_copy, // block copy object
+ &G_pba_bcue_queue, // sram to mainstore copy engine
+ mainstore_address, // mainstore address
+ sram_address, // sram starting address
+ block_size, // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // call back
+ NULL, // call back arguments
+ ASYNC_REQUEST_BLOCKING // callback mask
);
if(l_ssxrc != SSX_OK)
{
- TRAC_ERR("populate_opal_tbl_to_mem: PBA request create failure rc=[%08X]", -l_ssxrc);
+ TRAC_ERR("populate_opal_tbl_to_mem: PBA request create failure rc=[%08X]",
+ -l_ssxrc);
/*
* @errortype
* @moduleid MAIN_STATE_TRANSITION_MID
@@ -302,7 +352,8 @@ void populate_opal_tbl_to_mem()
if(l_ssxrc != SSX_OK)
{
- TRAC_ERR("populate_opal_tbl_to_mem: PBA request schedule failure rc=[%08X]", -l_ssxrc);
+ TRAC_ERR("populate_opal_tbl_to_mem: PBA request schedule failure rc=[%08X]",
+ -l_ssxrc);
/*
* @errortype
* @moduleid MAIN_STATE_TRANSITION_MID
@@ -319,14 +370,14 @@ void populate_opal_tbl_to_mem()
if ( l_ssxrc != SSX_OK )
{
- errlHndl_t l_errl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
- l_reasonCode, //reasoncode
- l_extReasonCode, //Extended reason code
- ERRL_SEV_UNRECOVERABLE, //Severity
- NULL, //Trace Buf
- 0, //Trace Size
- -l_ssxrc, //userdata1
- 0); //userdata2
+ errlHndl_t l_errl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ l_reasonCode, //reasoncode
+ l_extReasonCode, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ 0, //Trace Size
+ -l_ssxrc, //userdata1
+ 0); //userdata2
// Callout firmware
addCalloutToErrl(l_errl,
@@ -338,45 +389,6 @@ void populate_opal_tbl_to_mem()
}
}
-// Function Specification
-//
-// Name: proc_pstate_initialize
-//
-// Description: initialize Global variables required for
-// the proc_freq2pstate function.
-//
-// End Function Specification
-void proc_pstate_initialize(void)
-{
- // RTC:130201
- // @TODO: Schedule a PGPE IPC to enable pstates. This will also tell
- // PGPE how to set PMCR mode register (OCC control pstates or OPAL).
-
- // the call back IPC function that gets executed after this IPC finishes
- // sets the G_proc_pstate_enabled flag to true, so that the OCC is then
- // able to switch to the active state.
-
- // @TODO: FIXME - TEMP Hack to enable Active State, until PGPE is ready
- G_proc_pstate_enabled = 1;
-
-
- // Set up Key Globals for use by proc_freq2pstate functions
- // @TODO - FIXME ==> move to initialization code, reading from parameter block
- G_proc_fmax = 4322500;
- G_proc_fmin = 2028250;
- G_khz_per_pstate = 33250;
- G_proc_pmax = 0;
- G_proc_pmin = G_proc_pmax + ((G_proc_fmax - G_proc_fmin)/G_khz_per_pstate);
-
- // Set globals used by amec for pcap calculation
- // could have used G_khz_per_pstate in PCAP calculations
- // instead, but using a separate varaible speeds up PCAP related
- // calculations significantly, by eliminating division operations.
- G_mhz_per_pstate = G_khz_per_pstate/1000;
-
- TRAC_INFO("proc_pstate_initialize: Pstate Key globals initialized to default values");
-
-}
// Function Specification
//
@@ -429,14 +441,14 @@ void check_for_opal_updates(void)
// End Function Specification
void update_dynamic_opal_data (void)
{
+ TRAC_INFO("update_dynamic_opal_data: populate dynamic OPAL data");
+
// Initialize the opal table in SRAM (sets valid bit)
- populate_dynamic_opal_data();
+ populate_opal_dynamic_data();
// copy sram image into mainstore HOMER
- populate_opal_tbl_to_mem();
- TRAC_IMP("update_dynamic_opal_data: update dynamic OPAL data");
-
-
+ populate_opal_tbl_to_mem(OPAL_DYNAMIC);
+ TRAC_IMP("update_dynamic_opal_data: updated dynamic OPAL data");
}
@@ -451,14 +463,15 @@ void update_dynamic_opal_data (void)
// End Function Specification
uint8_t pmin_rail(void)
{
- uint8_t configMinPstate = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]);
+ uint8_t configMinPstate =
+ proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]);
- if(configMinPstate < G_proc_pmin)
+ if(configMinPstate < G_oppb.pstate_min)
{
return configMinPstate;
}
else
{
- return G_proc_pmin;
+ return G_oppb.pstate_min;
}
}
diff --git a/src/occ_405/proc/proc_pstate.h b/src/occ_405/proc/proc_pstate.h
index 962c71a..b552237 100755
--- a/src/occ_405/proc/proc_pstate.h
+++ b/src/occ_405/proc/proc_pstate.h
@@ -39,6 +39,25 @@
//#include "gpsm.h"
//#include "pstates.h"
+// The pstate associated with highest possible frequency
+// is always 0 in POWER9.
+#define PMAX 0
+
+typedef enum
+{
+ PSTATES_IN_TRANSITION = -1,
+ PSTATES_DISABLED = 0,
+ PSTATES_ENABLED = 1,
+} pstateStatus;
+
+
+typedef enum
+{
+ OPAL_STATIC = 0,
+ OPAL_DYNAMIC = 1,
+} opalDataType;
+
+
typedef struct __attribute__ ((packed))
{
uint8_t valid;
@@ -100,9 +119,7 @@ typedef struct __attribute__ ((packed))
extern uint32_t G_mhz_per_pstate;
extern opal_dynamic_table_t G_opal_dynamic_table;
-
-// Initialize PState Key parameters
-void proc_pstate_initialize(void);
+extern opal_static_table_t G_opal_static_table;
// Helper function to translate from Frequency to nearest Pstate
Pstate proc_freq2pstate(uint32_t i_freq_mhz);
@@ -115,13 +132,19 @@ Pstate proc_freq2pstate(uint32_t i_freq_mhz);
inline bool proc_is_hwpstate_enabled(void);
// Copy pstate data to opal table
-void populate_dynamic_opal_data(void);
+void populate_opal_dynamic_data(void);
// Copy all opal static data to opal table
-void populate_static_opal_data(void);
+void populate_opal_static_data(void);
+
+// Copy pstates sections of opal static data to opal table
+void populate_opal_static_pstates_data(void);
+
+// Copy config section of opal static data to opal table
+void populate_opal_static_config_data(void);
-// Copy opal table to mainstore memory at OPAL_OFFSET_HOMER
-void populate_opal_tbl_to_mem(void);
+// Copy opal static/dynamic table to mainstore memory at OPAL_OFFSET_HOMER
+void populate_opal_tbl_to_mem(opalDataType opal_data_type);
// Check if opal table needs update
void check_for_opal_updates(void);
OpenPOWER on IntegriCloud