summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/ipc_func_ids.h12
-rw-r--r--src/include/p9_pstates_occ.h2
-rwxr-xr-xsrc/occ_405/Makefile3
-rwxr-xr-xsrc/occ_405/amec/amec_data.c37
-rwxr-xr-xsrc/occ_405/amec/amec_freq.c76
-rwxr-xr-xsrc/occ_405/amec/amec_sys.h2
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c73
-rwxr-xr-xsrc/occ_405/homer.h4
-rw-r--r--src/occ_405/img_defs.mk1
-rwxr-xr-xsrc/occ_405/incl/comp_ids.h5
-rwxr-xr-xsrc/occ_405/incl/occ_common.h3
-rwxr-xr-xsrc/occ_405/main.c356
-rw-r--r--src/occ_405/occLinkInputFile2
-rw-r--r--src/occ_405/occ_service_codes.h19
-rwxr-xr-xsrc/occ_405/occ_sys_config.h1
-rw-r--r--src/occ_405/pgpe/pgpe_interface.c812
-rw-r--r--src/occ_405/pgpe/pgpe_interface.h45
-rw-r--r--src/occ_405/pgpe/pgpe_service_codes.h46
-rw-r--r--src/occ_405/pgpe/pgpe_shared.h (renamed from src/occ_405/pgpe_shared.h)33
-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
-rwxr-xr-xsrc/occ_405/pss/apss.c2
-rwxr-xr-xsrc/occ_405/rtls/rtls.h8
-rwxr-xr-xsrc/occ_405/rtls/rtls_service_codes.h13
-rwxr-xr-xsrc/occ_405/rtls/rtls_tables.c35
-rwxr-xr-xsrc/occ_405/state.c106
-rwxr-xr-xsrc/occ_405/timer/timer.c8
-rw-r--r--src/occ_405/topfiles.mk2
31 files changed, 1843 insertions, 468 deletions
diff --git a/src/common/ipc_func_ids.h b/src/common/ipc_func_ids.h
index 72193b5..da2285e 100644
--- a/src/common/ipc_func_ids.h
+++ b/src/common/ipc_func_ids.h
@@ -73,12 +73,12 @@ IPC_FUNCIDS_TABLE_START
//Functions that are only supported by GPE2 should be defined here
//These function ID's can only be sent to GPE2 (PGPE)
IPC_FUNCIDS_ST_START(OCCHW_INST_ID_GPE2)
- IPC_FUNC_ID(IPC_PGPE_INVALID_FUNCID)
- IPC_FUNC_ID(IPC_PGPE_START_SUSPEND_FUNCID)
- IPC_FUNC_ID(IPC_PGPE_CLIPS_FUNCID)
- IPC_FUNC_ID(IPC_PGPE_SET_PMCR_FUNCID)
- IPC_FUNC_ID(IPC_PGPE_WOF_CONTROL_FUNCID)
- IPC_FUNC_ID(IPC_PGPE_WOF_VFRT_FUNCID)
+ IPC_FUNC_ID(IPC_MSGID_405_INVALID)
+ IPC_FUNC_ID(IPC_MSGID_405_START_SUSPEND)
+ IPC_FUNC_ID(IPC_MSGID_405_CLIPS)
+ IPC_FUNC_ID(IPC_MSGID_405_SET_PMCR)
+ IPC_FUNC_ID(IPC_MSGID_405_WOF_CONTROL)
+ IPC_FUNC_ID(IPC_MSGID_405_WOF_VFRT)
IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE2)
//Functions that are only supported by GPE3 should be defined here
diff --git a/src/include/p9_pstates_occ.h b/src/include/p9_pstates_occ.h
index d3fa62b..e69e500 100644
--- a/src/include/p9_pstates_occ.h
+++ b/src/include/p9_pstates_occ.h
@@ -168,6 +168,8 @@ typedef struct
// Minimum Pstate; Maximum is always 0.
uint32_t pstate_min; // Comes from PowerSave #V point after biases
+ // TODO: Temporary hack untill interface is finalized.
+ uint8_t pad[88]; // total size = 0xE00, devisible by 128
} OCCPstateParmBlock;
diff --git a/src/occ_405/Makefile b/src/occ_405/Makefile
index 3fb1250..f64a319 100755
--- a/src/occ_405/Makefile
+++ b/src/occ_405/Makefile
@@ -69,7 +69,8 @@ LIB_DIRS = -L$(OBJDIR) \
-L$(OBJDIR)/firdata \
-L$(OBJDIR)/cent \
-L$(OBJDIR)/mem \
- -L$(OBJDIR)/wof
+ -L$(OBJDIR)/wof \
+ -L$(OBJDIR)/pgpe
#default target is to make a binary application image
.PHONY : all
diff --git a/src/occ_405/amec/amec_data.c b/src/occ_405/amec/amec_data.c
index 6663cdc..05d60b9 100755
--- a/src/occ_405/amec/amec_data.c
+++ b/src/occ_405/amec/amec_data.c
@@ -47,6 +47,8 @@
#include <amec_sensors_fw.h>
#include <amec_data.h>
#include <amec_freq.h>
+#include <pgpe_interface.h>
+#include <p9_pstates_occ.h>
//*************************************************************************
// Externs
@@ -64,8 +66,9 @@
// Globals
//*************************************************************************
extern uint8_t G_occ_interrupt_type;
-extern uint32_t G_proc_fmin;
-extern uint32_t G_proc_fmax;
+
+//max(fturbo,futurbo)
+extern uint16_t G_proc_fmax_mhz;
//*************************************************************************
// Function Prototypes
@@ -98,16 +101,13 @@ errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode)
/* Code */
/*------------------------------------------------------------------------*/
- // If we're active we need to load this new range into DVFS MIN/MAX
- if(CURRENT_STATE() == OCC_STATE_ACTIVE)
- {
- // Use i_mode here since this function understands turbo
- l_err = amec_set_freq_range(i_mode);
+ // Load new range into DVFS MIN/MAX,
+ // Use i_mode here since this function understands turbo
+ l_err = amec_set_freq_range(i_mode);
- if(l_err)
- {
- //break;
- }
+ if(l_err)
+ {
+ //break;
}
// If we are in OpenPower environment with OPAL, load this new range into DVFS
@@ -115,14 +115,25 @@ errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode)
// in amec_set_freq_range() based on mode
if((G_occ_interrupt_type != FSP_SUPPORTED_OCC) && (G_sysConfigData.system_type.kvm))
{
- g_amec->sys.fmax = G_proc_fmax;
- g_amec->sys.fmin = G_proc_fmin; // = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]
+ g_amec->sys.fmax = G_proc_fmax_mhz;
+ g_amec->sys.fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
TRAC_INFO("AMEC_data_write_fcurr: New frequency range Fmin[%u] Fmax[%u]",
g_amec->sys.fmin,
g_amec->sys.fmax);
}
+ if(!l_err)
+ {
+ // set the clip bounds wide open (if not in active state)
+ // if not already in active mode, send IPC command to PGPE to set
+ // pStates clips wide open (pmin - pmax)
+ if(!IS_OCC_STATE_ACTIVE())
+ {
+ l_err = pgpe_widen_clip_ranges();
+ }
+ }
+
return l_err;
}
diff --git a/src/occ_405/amec/amec_freq.c b/src/occ_405/amec/amec_freq.c
index 7115b37..5dadfa7 100755
--- a/src/occ_405/amec/amec_freq.c
+++ b/src/occ_405/amec/amec_freq.c
@@ -56,6 +56,11 @@
extern uint8_t G_cent_temp_expired_bitmap;
extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap;
+extern uint16_t G_proc_fmax_mhz;
+
+extern GPE_BUFFER(PstatesClips* G_core_data_control_occwrite_ptr);
+
+
//*************************************************************************
// Defines/Enums
//*************************************************************************
@@ -67,12 +72,12 @@ extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap;
//*************************************************************************
// Globals
//*************************************************************************
-BOOLEAN G_non_dps_power_limited = FALSE;
+BOOLEAN G_non_dps_power_limited = FALSE;
opal_proc_voting_reason_t G_amec_opal_proc_throt_reason = NO_THROTTLE;
opal_mem_voting_reason_t G_amec_opal_mem_throt_reason = NO_MEM_THROTTLE;
-uint16_t G_time_until_freq_check = FREQ_CHG_CHECK_TIME;
+uint16_t G_time_until_freq_check = FREQ_CHG_CHECK_TIME;
//FFDC SCOM addresses as requested by Greg Still in defect SW247927
//If new SCOM addresses are added, update the size of the array.
@@ -162,7 +167,15 @@ errlHndl_t amec_set_freq_range(const OCC_MODE i_mode)
/*------------------------------------------------------------------------*/
// First set to Max Freq Range for this mode
- if( VALID_MODE(i_mode) )
+ // if no mode set yet default to the full range
+ if(i_mode == OCC_MODE_NOCHANGE)
+ {
+ l_freq_min = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
+
+ // Set Max frequency (ultra turbo freq if wof enabled, to turbo freq otherwise)
+ l_freq_max = G_proc_fmax_mhz;
+ }
+ else if( VALID_MODE(i_mode) ) // Set to Max Freq Range for this mode
{
l_freq_min = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
l_freq_max = G_sysConfigData.sys_mode_freq.table[i_mode];
@@ -573,39 +586,54 @@ void amec_slv_proc_voting_box(void)
// End Function Specification
void amec_slv_freq_smh(void)
{
-// RTC:130201
-// TODO/TEMP: Remove '#if 0' when/if needed. Currently does nothing and
-// causes warning of set but not used..
-#if 0
-
/*------------------------------------------------------------------------*/
/* Local Variables */
/*------------------------------------------------------------------------*/
- uint16_t k = 0;
- Pstate l_pstate[MAX_NUM_CORES];
+ uint8_t quad = 0; // loop through quads
+ uint8_t core_num = 0; // core ID
+ uint8_t core_idx = 0; // loop through cores within each quad
+ Pstate pmax = 0; // select the maximum pstate (minimum frequency)
+ // within each quad, initialize to 0
/*------------------------------------------------------------------------*/
/* Code */
/*------------------------------------------------------------------------*/
- for (k=0; k<MAX_NUM_CORES; k++)
+ // loop through all quads, get f_requests, translate to pstates
+ for (quad = 0; quad < MAX_QUADS; quad++)
{
- // Translate frequency requests into pstates
- l_pstate[k]= proc_freq2pstate(g_amec->proc[0].core[k].f_request);
- }
+ for (core_idx=0; core_idx<NUM_CORES_PER_QUAD; core_idx++) // scan quad cores
+ {
+ core_num = (quad*NUM_CORES_PER_QUAD) + core_idx; // loop through all cores
- // If this is an OPAL system, send PGPE an IPC to set clipping bounds
- // otherwise, set send PGPE an IPC to set pstates
+ if(pmax < proc_freq2pstate(g_amec->proc[0].core[core_num].f_request))
+ {
+ pmax = proc_freq2pstate(g_amec->proc[0].core[core_num].f_request);
+ }
+ }
- if(G_sysConfigData.system_type.kvm)
- {
- // Send IPC with G_proc_pmin and l_pstate to set pmin and pmax clips
- }
- else
- {
- // send an IPC with l_pstate to set pstates for all Cores
+ // set quad clip bounds/pstates based on system type
+ if(G_sysConfigData.system_type.kvm)
+ {
+ // update quad bounds on OPAL systems
+ G_core_data_control_occwrite_ptr->clips.ps_val_clip_min[quad] =
+ G_opal_static_table.config.pmin;
+ G_core_data_control_occwrite_ptr->clips.ps_val_clip_max[quad] = pmax;
+
+ PROC_DBG("Setting Quad %d's min-max clip bounds to %d-%d\n",
+ quad, G_opal_static_table.config.pmin, pmax);
+ }
+ else
+ {
+ // update quad pstate request on non-OPAL systems
+ G_core_data_control_occwrite_ptr->pstates.pmcr[quad] =
+ ((uint64_t) pmax << 48) +1; // Version 1 (Power9 format)
+
+ PROC_DBG("Setting Quad %d's Pstate to %d\n",quad, pmax);
+ }
+
+ pmax = 0; // initialize for next loop iteration
}
-#endif
}
diff --git a/src/occ_405/amec/amec_sys.h b/src/occ_405/amec/amec_sys.h
index d298c7f..bf2a003 100755
--- a/src/occ_405/amec/amec_sys.h
+++ b/src/occ_405/amec/amec_sys.h
@@ -337,8 +337,6 @@ typedef struct
uint16_t f_request;
// Reason for the frequency request generated by the voting box
uint32_t f_reason;
- // Current state of this core frequency state machine
- uint8_t f_sms;
} amec_core_t;
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
index d3e9a3f..30e2ea9 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
@@ -42,6 +42,7 @@
#include <centaur_data.h>
#include "dimm.h"
#include <avsbus.h>
+#include "p9_pstates_occ.h"
#define FREQ_FORMAT_PWR_MODE_NUM 6
#define FREQ_FORMAT_BASE_DATA_SZ (sizeof(cmdh_store_mode_freqs_t) - sizeof(cmdh_fsp_cmd_header_t))
@@ -67,12 +68,8 @@
extern uint8_t G_occ_interrupt_type;
-extern uint32_t G_proc_fmin;
-extern uint32_t G_proc_fmax;
-extern uint32_t G_khz_per_pstate;
-
-extern uint8_t G_proc_pmin;
-extern uint8_t G_proc_pmax;
+extern uint16_t G_proc_fmax_mhz; // Maximum frequency (uturbo if WOF enabled, otherwise turbo)
+extern OCCPstateParmBlock G_oppb; // OCC Pstate Parameters Block Structure
typedef struct data_req_table
{
@@ -284,39 +281,64 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
// Bytes 3-4 Nominal Frequency Point
l_freq = (l_buf[0] << 8 | l_buf[1]);
l_table[OCC_MODE_NOMINAL] = l_freq;
- CMDH_TRAC_INFO("Nominal frequency = %d", l_freq);
+ CMDH_TRAC_INFO("Nominal frequency = %d MHz", l_freq);
// Bytes 5-6 Turbo Frequency Point:
// also store for DPS modes
l_freq = (l_buf[2] << 8 | l_buf[3]);
+ // Verify that turbo frequency is <= G_proc_fmax_mhz
+ if(l_freq > G_proc_fmax_mhz)
+ {
+ CMDH_TRAC_ERR("Turbo Frequency[%d] (MHz)) is higher than "
+ "G_proc_fmax_mhz[%d], clip Turbo Frequency",
+ l_freq, G_proc_fmax_mhz);
+ l_freq = G_proc_fmax_mhz;
+ }
l_table[OCC_MODE_TURBO] = l_freq;
l_table[OCC_MODE_DYN_POWER_SAVE] = l_freq;
l_table[OCC_MODE_DYN_POWER_SAVE_FP] = l_freq;
- CMDH_TRAC_INFO("Turbo frequency = %d", l_freq);
+ CMDH_TRAC_INFO("Turbo frequency = %d MHz", l_freq);
// Bytes 7-8 Minimum Frequency Point
l_freq = (l_buf[4] << 8 | l_buf[5]);
+ // Verify that minimum frequency is >= G_oppb.frequency_min_khz
+ if(l_freq * 1000 < G_oppb.frequency_min_khz)
+ {
+ CMDH_TRAC_ERR("Minimum Frequency[%d] (Mhz) is lower than PGPE's "
+ "G_oppb.frequency_min_khz[%d], clip Minimum Frequency",
+ l_freq, G_oppb.frequency_min_khz);
+ l_freq = G_oppb.frequency_min_khz / 1000;
+ }
l_table[OCC_MODE_MIN_FREQUENCY] = l_freq;
- G_proc_fmin = l_freq;
- CMDH_TRAC_INFO("Minimum frequency = %d", l_freq);
+ CMDH_TRAC_INFO("Minimum frequency = %d MHz", l_freq);
// Bytes 9-10 Ultr Turbo Frequency Point
l_freq = (l_buf[6] << 8 | l_buf[7]);
- if(l_freq)
+ // Verify that ultra turbo frequency is <= G_proc_fmax_mhz
+ if(l_freq > G_proc_fmax_mhz)
+ {
+ CMDH_TRAC_ERR("Ultra Turbo Frequency[%d] (MHz) is higher than PGPE's "
+ "Max freq (G_proc_fmax_mhz[%d]) clip Ultra Turbo Frequency",
+ l_freq, G_proc_fmax_mhz);
+ l_freq = G_proc_fmax_mhz;
+ }
+ l_table[OCC_MODE_UTURBO] = l_freq;
+ CMDH_TRAC_INFO("UT frequency = %d MHz", l_freq);
+
+ // clip G_proc_fmax_mhz to TMGT's MAX(turbo, ultra turbo) frequency point
+ if(l_table[OCC_MODE_UTURBO] > l_table[OCC_MODE_TURBO])
{
- G_proc_fmax = l_freq;
+ G_proc_fmax_mhz = l_table[OCC_MODE_UTURBO];
}
- else // If Ultra Turbo Frequency Point = 0, Fmax = Turbo Frequency
+ else
{
- G_proc_fmax = l_table[OCC_MODE_TURBO];
+ G_proc_fmax_mhz = l_table[OCC_MODE_TURBO];
}
- l_table[OCC_MODE_UTURBO] = l_freq;
- CMDH_TRAC_INFO("UT frequency = %d", l_freq);
// Bytes 11-12 Static Power Save Frequency Point
l_freq = (l_buf[8] << 8 | l_buf[9]);
l_table[OCC_MODE_PWRSAVE] = l_freq;
- CMDH_TRAC_INFO("Static Power Save frequency = %d", l_freq);
+ CMDH_TRAC_INFO("Static Power Save frequency = %d MHz", l_freq);
// Bytes 13-14 FFO Frequency Point
l_freq = (l_buf[10] << 8 | l_buf[11]);
@@ -324,19 +346,19 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
{
// Check and make sure that FFO freq is within valid range
const uint16_t l_req_freq = l_freq;
- if (l_freq < G_proc_fmin)
+ if (l_freq < l_table[OCC_MODE_MIN_FREQUENCY])
{
- l_freq = G_proc_fmin;
+ l_freq = l_table[OCC_MODE_MIN_FREQUENCY];
}
- else if (l_freq > G_proc_fmax)
+ else if (l_freq > G_proc_fmax_mhz)
{
- l_freq = G_proc_fmax;
+ l_freq = G_proc_fmax_mhz;
}
// Log an error if we could not honor the requested FFO frequency, but keep going.
if (l_req_freq != l_freq)
{
- TRAC_ERR("FFO Frequency out of range. requested %d, but using %d",
+ TRAC_ERR("FFO Frequency out of range. requested %d MHz, but using %d MHz",
l_req_freq, l_freq);
/* @
* @errortype
@@ -360,10 +382,7 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
}
}
l_table[OCC_MODE_FFO] = l_freq;
- CMDH_TRAC_INFO("FFO Frequency = %d", l_freq);
-
- // Calculate minimum Pstate:
- G_proc_pmin = G_proc_pmax + ((G_proc_fmax - G_proc_fmin)/G_khz_per_pstate);
+ CMDH_TRAC_INFO("FFO Frequency = %d Mhz", l_freq);
// inconsistent Frequency Points?
if((l_table[OCC_MODE_UTURBO] < l_table[OCC_MODE_TURBO] && l_table[OCC_MODE_UTURBO]) ||
@@ -2091,6 +2110,8 @@ errlHndl_t DATA_store_cnfgdata (const cmdh_fsp_cmd_t * i_cmd_ptr,
l_errlHndl = data_store_freq_data(i_cmd_ptr , o_rsp_ptr);
if(NULL == l_errlHndl)
{
+ // New Frequency config data packet received with no error logs: set the
+ // DATA_MASK_FREQ_PRESENT to flag that we received the frequency from TMGT
l_new_data = DATA_MASK_FREQ_PRESENT;
}
break;
diff --git a/src/occ_405/homer.h b/src/occ_405/homer.h
index f276c67..b634701 100755
--- a/src/occ_405/homer.h
+++ b/src/occ_405/homer.h
@@ -54,6 +54,10 @@
#define OCC_HTMGT_RSP_OFFSET_HOMER 0x000E1000
#define OCC_HTMGT_RSP_ADDRESS_HOMER (HOMER_BASE_ADDRESS+OCC_HTMGT_RSP_OFFSET_HOMER)
+// PPMR Header space
+#define PPMR_OFFSET_HOMER 0x00300000 // PPMR image HOMER offset
+#define PPMR_ADDRESS_HOMER (HOMER_BASE_ADDRESS+PPMR_OFFSET_HOMER) // PPMR image memory address
+
// Version(s) of HOMER host data currently supported
typedef enum homer_version
diff --git a/src/occ_405/img_defs.mk b/src/occ_405/img_defs.mk
index abdef45..9dea1eb 100644
--- a/src/occ_405/img_defs.mk
+++ b/src/occ_405/img_defs.mk
@@ -240,6 +240,7 @@ APP_INCLUDES = -I$(IMAGE_SRCDIR)/rtls \
-I$(IMAGE_SRCDIR)/lock \
-I$(IMAGE_SRCDIR)/wof \
-I$(IMAGE_SRCDIR)/../common \
+ -I$(IMAGE_SRCDIR)/pgpe \
INCLUDES += $(IMG_INCLUDES) $(GLOBAL_INCLUDES) $(APP_INCLUDES) \
-I$(SSX_SRCDIR)/ssx -I$(SSX_SRCDIR)/ppc32 -I$(SSX_SRCDIR)/ppc405 \
diff --git a/src/occ_405/incl/comp_ids.h b/src/occ_405/incl/comp_ids.h
index 893b9f9..e6270d6 100755
--- a/src/occ_405/incl/comp_ids.h
+++ b/src/occ_405/incl/comp_ids.h
@@ -91,5 +91,10 @@
// Workload Optimize Frequency
#define WOF_COMP_ID 0x1100
#define WOF_COMP_NAME "WOF"
+
+// PGPE Interface
+#define PGPE_COMP_ID 0x1200
+#define PGPE_COMP_NAME "PGPE"
+
#endif
diff --git a/src/occ_405/incl/occ_common.h b/src/occ_405/incl/occ_common.h
index 2dc0c9f..eadcd95 100755
--- a/src/occ_405/incl/occ_common.h
+++ b/src/occ_405/incl/occ_common.h
@@ -261,7 +261,8 @@ enum
NEST_DTS_INITIALIZED = 0x0700,
CENTAUR_INITIALIZED = 0x07ff,
SLAVE_OCC_INITIALIZED = 0x08ff,
- PGPE_IMAGE_HEADER_READ = 0x098f,
+ PGPE_IMAGE_HEADER_READ = 0x094f,
+ PPMR_IMAGE_HEADER_READ = 0x098f,
WATCHDOG_INITIALIZED = 0x09ff,
RTL_TIMER_INITIALIZED = 0x0aff,
SEMS_AND_TIMERS_INITIALIZED = 0x0bff,
diff --git a/src/occ_405/main.c b/src/occ_405/main.c
index fdbe9f3..e4eaf6e 100755
--- a/src/occ_405/main.c
+++ b/src/occ_405/main.c
@@ -59,6 +59,7 @@
#include "occhw_shared_data.h"
#include <pgpe_shared.h>
#include <gpe_register_addresses.h>
+#include <p9_pstates_occ.h>
extern uint32_t __ssx_boot; // Function address is 32 bits
extern uint32_t G_occ_phantom_critical_count;
@@ -78,8 +79,13 @@ extern uint32_t G_pgpe_beacon_address;
IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,ID_NUM_INVALID);
// PGPE Image Header Parameters
-uint32_t G_pgpe_sram_address;
-uint32_t G_pgpe_sram_sz;
+uint32_t G_pgpe_shared_sram_address = 0;
+uint32_t G_pgpe_shared_sram_sz = 0;
+
+ppmr_header_t G_ppmr_header; // PPMR Header layout format
+OCCPstateParmBlock G_oppb; // OCC Pstate Parameters Block Structure
+extern uint16_t G_proc_fmax_mhz; // max(turbo,uturbo) frequencies
+
//Set main thread timer for one second
#define MAIN_THRD_TIMER_SLICE ((SsxInterval) SSX_SECONDS(1))
@@ -119,6 +125,7 @@ extern uint8_t g_trac_err_buffer[];
void pmc_hw_error_isr(void *private, SsxIrqId irq, int priority);
void create_tlb_entry(uint32_t address, uint32_t size);
+void read_oppb_params(const OCCPstateParmBlock* occ_ppb);
//Macro creates a 'bridge' handler that converts the initial fast-mode to full
//mode interrupt handler
@@ -404,8 +411,9 @@ void create_tlb_entry(uint32_t address, uint32_t size)
tlb_entry_size = PAGE_ALIGNED_SIZE(size);
}
+
#if PPC405_MMU_SUPPORT
- // define DTLB for PGPE image header
+ // define DTLB for page aligned address and size
l_rc = ppc405_mmu_map(
tlb_entry_address,
tlb_entry_address,
@@ -465,33 +473,308 @@ void create_tlb_entry(uint32_t address, uint32_t size)
void read_pgpe_header(void)
{
+ uint64_t magic_number;
+ errlHndl_t l_err;
// define DTLB for the PGPE image header
create_tlb_entry(PGPE_HEADER_ADDR, PGPE_HEADER_SZ);
- // Read PGPE Beacon address from PGPE image header
- G_pgpe_beacon_address = in32(PGPE_BEACON_ADDR_PTR);
+ // verify the validity of the magic number
+ magic_number = in64(PGPE_HEADER_ADDR);
+ if(PGPE_MAGIC_NUMBER != magic_number)
+ {
+ // The Magic number is invalid .. Invalid or corrupt PGPE image header
+ MAIN_TRAC_ERR("Invalid PGPGE Magic number. Address[0x%08X], Magic Number[0x%08X%08X]",
+ PGPE_HEADER_ADDR, (uint32_t)(magic_number>>32), (uint32_t)magic_number);
+ /* @
+ * @errortype
+ * @moduleid READ_PGPE_HEADER
+ * @reasoncode INVALID_MAGIC_NUMBER
+ * @userdata1 Low order 32 bits of retrieved PGPE magic number
+ * @userdata2 Hight order 32 bits of retrieved PGPE magic number
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX semaphore related failure
+ */
- MAIN_TRAC_IMP("Read PGPE Beacon Address[0x%08x]",
- G_pgpe_beacon_address);
+ l_err = createErrl(READ_PGPE_HEADER, //modId
+ INVALID_MAGIC_NUMBER, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ (uint32_t)magic_number, //userdata1
+ (uint32_t)(magic_number>>32)); //userdata2
- // Read OCC/PGPE Shared SRAM address and size
- G_pgpe_sram_address = in32(PGPE_SHARED_SRAM_ADDR_PTR);
- G_pgpe_sram_sz = in32(PGPE_SHARED_SRAM_SZ_PTR);
+ REQUEST_RESET(l_err);
- MAIN_TRAC_IMP("Read PGPE Shared SRAM Start Address[0x%08x], Size[0x%08x]",
- G_pgpe_sram_address, G_pgpe_sram_sz);
+ }
- // PGPE Beacon is not implemented in simics yet
- // the G_pgpe_sram_address and G_pgpe_sram_sz pointers don't
- // have the proper values yet.
- // @TODO: remove this condition when PGPE code is integrated. RTC: 163934
- if(!G_simics_environment)
+ if(l_err == NULL)
{
- // define DTLB for OCC/PGPE shared SRAM, which enables access
- // to OCC-PGPE Shared SRAM space, including pgpe_beacon
- create_tlb_entry(G_pgpe_sram_address, G_pgpe_sram_sz);
+ // Read PGPE Beacon address from PGPE image header
+ G_pgpe_beacon_address = in32(PGPE_BEACON_ADDR_PTR);
+
+ MAIN_TRAC_IMP("Read PGPE Beacon Address[0x%08x]",
+ G_pgpe_beacon_address);
+
+ // Read OCC/PGPE Shared SRAM address and size
+ G_pgpe_shared_sram_address = in32(PGPE_SHARED_SRAM_ADDR_PTR);
+ G_pgpe_shared_sram_sz = in32(PGPE_SHARED_SRAM_SZ_PTR);
+
+ MAIN_TRAC_IMP("Read PGPE Shared SRAM Start Address[0x%08x], Size[0x%08x]",
+ G_pgpe_shared_sram_address, G_pgpe_shared_sram_sz);
+
+ // PGPE Beacon is not implemented in simics yet
+ // the G_pgpe_shared_sram_address and G_pgpe_shared_sram_sz pointers don't
+ // have the proper values yet.
+ // @TODO: remove this condition when PGPE code is integrated. RTC: 163934
+ if(!G_simics_environment)
+ {
+ // define DTLB for OCC/PGPE shared SRAM, which enables access
+ // to OCC-PGPE Shared SRAM space, including pgpe_beacon
+ create_tlb_entry(G_pgpe_shared_sram_address, G_pgpe_shared_sram_sz);
+ }
}
+ return;
+}
+
+
+/*
+ * Function Specification
+ *
+ * Name: read_ppmr_header
+ *
+ * Description: read PPMR image header, and extract the
+ * OPPB HOMER offset and sturcture size..
+ *
+ * End Function Specification
+ */
+void read_ppmr_header(void)
+{
+ int l_ssxrc = SSX_OK;
+ uint32_t l_reasonCode = 0;
+ uint32_t l_extReasonCode = 0;
+
+ // error log parameters, if any
+ uint32_t userdata1 = 0;
+ uint32_t userdata2 = 0;
+
+ // create a DTLB entry for the PPMR image header
+ create_tlb_entry(PPMR_ADDRESS_HOMER, sizeof(ppmr_header_t));
+
+ do{
+ // use block copy engine to read the PPMR header
+ BceRequest pba_copy;
+
+ // Set up a copy request
+ l_ssxrc = bce_request_create(&pba_copy, // block copy object
+ &G_pba_bcde_queue, // mainstore to sram copy engine
+ PPMR_ADDRESS_HOMER, // mainstore address
+ (uint32_t) &G_ppmr_header, // sram starting address
+ (size_t) sizeof(G_ppmr_header), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // no call back
+ NULL, // no call back arguments
+ ASYNC_REQUEST_BLOCKING); // blocking request
+
+ if(l_ssxrc != SSX_OK)
+ {
+ MAIN_TRAC_ERR("read_ppmr_header: BCDE request create failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid READ_PPMR_HEADER
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata2 Internal function checkpoint
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc Failed to create BCDE request
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQUEST_CREATE_FAILURE;
+
+ userdata1 = (uint32_t)(-l_ssxrc);
+ break;
+ }
+
+ // Do actual copying
+ l_ssxrc = bce_request_schedule(&pba_copy);
+
+ if(l_ssxrc != SSX_OK)
+ {
+ MAIN_TRAC_ERR("read_ppmr_header: BCE request schedule failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid READ_PPMR_HEADER
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc Failed to read PPMR data by using BCDE
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE;
+
+ userdata1 = (uint32_t)(-l_ssxrc);
+ break;
+ }
+
+ if(G_ppmr_header.oppb_length != sizeof(OCCPstateParmBlock))
+ {
+ MAIN_TRAC_ERR("read_ppmr_header: OCCPstateParmBlock size mismatch:"
+ "PPMR header sz[0x%08x] PPMR struct sz[0x%08x]",
+ G_ppmr_header.oppb_length, sizeof(OCCPstateParmBlock));
+
+ /*
+ * @errortype
+ * @moduleid READ_PPMR_HEADER
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 G_ppmr_header.oppb_length
+ * @userdata2 sizeof(OCCPstateParmBlock)
+ * @userdata4 ERC_PGPE_PPMR_OPPB_SIZE_MISMATCH
+ * @devdesc PPMR's OPPB size mismatches data structure's
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE;
+
+ userdata1 = G_ppmr_header.oppb_length;
+ userdata2 = sizeof(OCCPstateParmBlock);
+ break;
+ }
+
+
+
+ } while (0);
+
+ if ( l_reasonCode )
+ {
+ errlHndl_t l_errl = createErrl(READ_PPMR_HEADER, //modId
+ l_reasonCode, //reasoncode
+ l_extReasonCode, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ 0, //Trace Size
+ userdata1, //userdata1
+ userdata2); //userdata2
+
+ // Callout firmware
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ REQUEST_RESET(l_errl);
+
+ return;
+ }
+
+ // Read OCC pstates parameter block
+ read_oppb_params((OCCPstateParmBlock*)G_ppmr_header.oppb_offset);
+}
+
+/*
+ * Function Specification
+ *
+ * Name: read_oppb_params
+ *
+ * Description: Read the OCC Pstates Parameter Block,
+ * and initializa Pstates Global Variables.
+ *
+ * End Function Specification
+ */
+void read_oppb_params(const OCCPstateParmBlock* oppb_offset)
+{
+ int l_ssxrc = SSX_OK;
+ uint32_t l_reasonCode = 0;
+ uint32_t l_extReasonCode = 0;
+
+ create_tlb_entry( ((uint32_t)oppb_offset + (uint32_t)PPMR_ADDRESS_HOMER),
+ sizeof(OCCPstateParmBlock));
+
+ do{
+ // use block copy engine to read the PPMR header
+ BceRequest pba_copy;
+
+ // Set up a copy request
+ l_ssxrc = bce_request_create(&pba_copy, // block copy object
+ &G_pba_bcde_queue, // mainstore to sram copy engine
+ (uint32_t)PPMR_ADDRESS_HOMER +
+ (uint32_t)oppb_offset, // mainstore address
+ (uint32_t) &G_oppb, // sram starting address
+ (size_t) sizeof(OCCPstateParmBlock), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // no call back
+ NULL, // no call back arguments
+ ASYNC_REQUEST_BLOCKING); // blocking request
+
+ if(l_ssxrc != SSX_OK)
+ {
+ CMDH_TRAC_ERR("read_oppb_params: BCDE request create failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid READ_OPPB_PARAMS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata2 Internal function checkpoint
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc Failed to create BCDE request
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQUEST_CREATE_FAILURE;
+ break;
+ }
+
+ // Do actual copying
+ l_ssxrc = bce_request_schedule(&pba_copy);
+
+ if(l_ssxrc != SSX_OK)
+ {
+ CMDH_TRAC_ERR("read_oppb_params: BCE request schedule failure rc=[%08X]", -l_ssxrc);
+ /*
+ * @errortype
+ * @moduleid READ_OPPB_PARAMS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 RC for BCE block-copy engine
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc Failed to read PPMR data by using BCDE
+ */
+ l_reasonCode = SSX_GENERIC_FAILURE;
+ l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE;
+ break;
+ }
+ } while (0);
+
+ if ( l_ssxrc != SSX_OK )
+ {
+ errlHndl_t l_errl = createErrl(READ_OPPB_PARAMS, //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,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ REQUEST_RESET(l_errl);
+
+ return;
+ }
+
+ // Copy over max frequency into G_proc_fmax_mhz
+ G_proc_fmax_mhz = G_oppb.frequency_max_khz / 1000;
+
+
+ // Used by amec for pcap calculation could use G_oppb.frequency_step_khz
+ // in PCAP calculationsinstead, but using a separate varaible speeds
+ // up PCAP relatedcalculations significantly, by eliminating slow
+ // division operations.
+ G_mhz_per_pstate = G_oppb.frequency_step_khz/1000;
+
+ TRAC_INFO("read_oppb_params: OCC Pstates Parameter Block read successfully");
}
/*
@@ -971,11 +1254,44 @@ void Main_thread_routine(void *private)
slave_occ_init();
CHECKPOINT(SLAVE_OCC_INITIALIZED);
+ // @TODO: remove this precompile directive check when PGPE code is integrated.
+ /// RTC: 163934
+#ifndef PGPE_SUPPORT
+ extern pstateStatus G_proc_pstate_status;
+ // TEMP Hack to enable Active State, until PGPE is ready
+ G_proc_pstate_status = PSTATES_ENABLED;
+
+
+ // Temp hack to Set up Key Globals for use by proc_freq2pstate functions
+ G_oppb.frequency_max_khz = 4322500;
+ G_oppb.frequency_min_khz = 2028250;
+ G_oppb.frequency_step_khz = 16667;
+ G_oppb.pstate_min = PMAX +
+ ((G_oppb.frequency_max_khz - G_oppb.frequency_min_khz)/G_oppb.frequency_step_khz);
+
+ G_proc_fmax_mhz = G_oppb.frequency_max_khz / 1000;
+
+
+ // Set globals used by amec for pcap calculation
+ // could have used G_oppb.frequency_step_khz in PCAP calculations
+ // instead, but using a separate varaible speeds up PCAP related
+ // calculations significantly, by eliminating division operations.
+ G_mhz_per_pstate = G_oppb.frequency_step_khz/1000;
+
+ TRAC_INFO("Main_thread_routine: Pstate Key globals initialized to default values");
+
+#else
// Read PGPE header file, extract OCC/PGPE Shared SRAM address and size,
// Read other global parameters, e.g. G_pgpe_beacon_address, etc.
read_pgpe_header();
CHECKPOINT(PGPE_IMAGE_HEADER_READ);
+ // Read PPMR header, extract OCC pstates parameter block address and size,
+ // Read OCCC pstate parameter block.
+ read_ppmr_header();
+ CHECKPOINT(PPMR_IMAGE_HEADER_READ);
+#endif
+
// Initialize watchdog timers. This needs to be right before
// start rtl to make sure timer doesn't timeout. This timer is being
// reset from the rtl task.
diff --git a/src/occ_405/occLinkInputFile b/src/occ_405/occLinkInputFile
index 16dbd5f..21b5a3f 100644
--- a/src/occ_405/occLinkInputFile
+++ b/src/occ_405/occLinkInputFile
@@ -60,6 +60,7 @@ INPUT ( amec_amester.o
occhw_irq_init.o
occhw_ocb.o
occhw_pba.o
+ pgpe_interface.o
ppc405_boot.o
ppc405_breakpoint.o
ppc405_cache_core.o
@@ -73,6 +74,7 @@ INPUT ( amec_amester.o
ppc405_mmu_asm.o
ppc405_thread_init.o
proc_data.o
+ proc_data_control.o
proc_pstate.o
reset.o
rtls_tables.o
diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h
index b96ff0d..6633ba5 100644
--- a/src/occ_405/occ_service_codes.h
+++ b/src/occ_405/occ_service_codes.h
@@ -113,11 +113,17 @@ enum occReasonCode
DIMM_GPE_FAILURE = 0xD0,
MEMORY_INIT_FAILED = 0xD1,
DIMM_INVALID_STATE = 0xD2,
- PGPE_BEACON_TIMEOUT = 0xD3,
+
+ // PGPE Generic RC
+ PGPE_FAILURE = 0xD3,
+
/// GPE IPC TASK RCs
GPE_REQUEST_CREATE_FAILURE = 0xD4,
GPE_REQUEST_SCHEDULE_FAILURE = 0xD5,
GPE_REQUEST_TASK_TIMEOUT = 0xD6,
+ GPR_REQUEST_RC_FAILURE = 0xD7,
+
+ INVALID_MAGIC_NUMBER = 0xDA,
/// Success!
OCC_SUCCESS_REASON_CODE = 0xFF,
@@ -227,6 +233,13 @@ enum occExtReasonCode
ERC_AVSBUS_VDN_VOLTAGE_FAILURE = 0x00AC,
ERC_AVSBUS_VDN_CURRENT_FAILURE = 0x00AD,
+ ERC_PGPE_BEACON_TIMEOUT = 0x00B0,
+ ERC_PGPE_NOT_IDLE = 0x00B1,
+ ERC_PGPE_UNSUCCESSFULL = 0x00B2,
+ ERC_PGPE_START_FAILURE = 0x00B3,
+ ERC_PGPE_SUSPEND_FAILURE = 0x00B4,
+ ERC_PGPE_CLIP_FAILURE = 0x00B5,
+ ERC_PGPE_PPMR_OPPB_SIZE_MISMATCH = 0x00B6,
};
// Error log Module Ids
@@ -249,6 +262,10 @@ enum occModuleId
CMDH_DBUG_MID = MAIN_COMP_ID | 0x0f,
I2C_LOCK_UPDATE = MAIN_COMP_ID | 0x10,
CREATE_TLB_ENTRY = MAIN_COMP_ID | 0x11,
+ READ_PGPE_HEADER = MAIN_COMP_ID | 0x12,
+ READ_PPMR_HEADER = MAIN_COMP_ID | 0x13,
+ READ_OPPB_PARAMS = MAIN_COMP_ID | 0x14,
+ MAIN_SMGR_MID = MAIN_COMP_ID | 0x15,
};
enum occUserDataType
diff --git a/src/occ_405/occ_sys_config.h b/src/occ_405/occ_sys_config.h
index 9380cfb..6b85d7c 100755
--- a/src/occ_405/occ_sys_config.h
+++ b/src/occ_405/occ_sys_config.h
@@ -40,6 +40,7 @@
#define MAX_NUM_NODES 4
#define MAX_NUM_CORES 24
#define MAX_NUM_QUADS 6
+#define NUM_CORES_PER_QUAD 4
#define MAX_THREADS_PER_CORE 4
#define MAX_NUM_CHIP_MODULES 4
#define MAX_NUM_POWER_SUPPLIES 4
diff --git a/src/occ_405/pgpe/pgpe_interface.c b/src/occ_405/pgpe/pgpe_interface.c
new file mode 100644
index 0000000..bbdf801
--- /dev/null
+++ b/src/occ_405/pgpe/pgpe_interface.c
@@ -0,0 +1,812 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/pgpe/pgpe_interface.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
+/* [+] 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 "occ_common.h"
+#include "occhw_async.h"
+#include "pgpe_interface.h"
+#include "pstate_pgpe_occ_api.h"
+#include "occ_service_codes.h"
+#include "pgpe_service_codes.h"
+#include "trac.h"
+#include "state.h"
+#include "proc_pstate.h"
+#include "proc_data_control.h"
+#include "occ_sys_config.h"
+
+extern opal_static_table_t G_opal_static_table;
+
+extern pstateStatus G_proc_pstate_status;
+extern PMCR_OWNER G_proc_pmcr_owner;
+
+extern uint16_t G_proc_fmax_mhz;
+
+extern GPE_BUFFER(PstatesClips* G_core_data_control_gpewrite_ptr);
+extern GPE_BUFFER(PstatesClips* G_core_data_control_occwrite_ptr);
+
+// IPC GPE Requests
+GpeRequest G_clip_update_req;
+GpeRequest G_pmcr_set_req;
+GpeRequest G_start_suspend_req;
+GpeRequest G_wof_control_req;
+GpeRequest G_wof_vfrt_req;
+
+// The the GPE parameter fields for PGPE IPC calls.
+GPE_BUFFER(ipcmsg_clip_update_t* G_clip_update_parms_ptr);
+GPE_BUFFER(ipcmsg_set_pmcr_t* G_pmcr_set_parms_ptr);
+GPE_BUFFER(ipcmsg_start_suspend_t G_start_suspend_parms);
+GPE_BUFFER(ipcmsg_wof_control_t G_wof_control_parms);
+GPE_BUFFER(ipcmsg_wof_vfrt_t G_wof_vfrt_parms);
+
+
+// Function Specification
+//
+// Name: init_pgpe_ipcs
+//
+// Description: Create all PGPE IPC messages.
+//
+// End Function Specification
+
+errlHndl_t init_pgpe_ipcs(void)
+{
+ errlHndl_t err = NULL; // Error handler
+
+ //Set PMCR IPC task parameters to gpewrite's quad pstates data structure
+ G_pmcr_set_parms_ptr = &G_core_data_control_gpewrite_ptr->pstates;
+
+ //Set Clip IPC task parameters to gpewrite's quad pstates data structure
+ G_clip_update_parms_ptr = &G_core_data_control_gpewrite_ptr->clips;
+
+ do
+ {
+ err = pgpe_init_clips();
+ if(err)
+ {
+ break;
+ }
+ err = pgpe_init_pmcr();
+ if(err)
+ {
+ break;
+ }
+ err = pgpe_init_start_suspend();
+ if(err)
+ {
+ break;
+ }
+ err = pgpe_init_wof_control();
+ if(err)
+ {
+ break;
+ }
+ err = pgpe_init_wof_vfrt();
+ }while(0);
+
+ if(err)
+ {
+ REQUEST_RESET(err);
+ }
+
+ // Initialization used in the task_core_data_control for PGPE success
+ // checks made before the first clip/pstate IPC message to be ever sent
+ // from either of the two double buffers.
+ G_core_data_control_occwrite_ptr->clips.msg_cb.rc = PGPE_RC_SUCCESS;
+ G_core_data_control_occwrite_ptr->pstates.msg_cb.rc = PGPE_RC_SUCCESS;
+
+ G_core_data_control_gpewrite_ptr->clips.msg_cb.rc = PGPE_RC_SUCCESS;
+ G_core_data_control_gpewrite_ptr->pstates.msg_cb.rc = PGPE_RC_SUCCESS;
+
+
+ return(err);
+}
+
+
+// Function Specification
+//
+// Name: pgpe_init_clips
+//
+// Description: Create PGPE clip update IPC messages (non-blocking).
+//
+// End Function Specification
+
+errlHndl_t pgpe_init_clips(void)
+{
+ int rc; // return code
+ errlHndl_t err = NULL; // Error handler
+
+ do
+ {
+ //Initializes the GpeRequest object for pgpe clips setting IPC
+ rc = gpe_request_create(&G_clip_update_req, // GpeRequest for the task
+ &G_async_gpe_queue2, // Queue
+ IPC_MSGID_405_CLIPS, // Function ID
+ G_clip_update_parms_ptr, // Task parameters
+ SSX_WAIT_FOREVER, // Timeout (none)
+ NULL, // Callback
+ NULL, // Callback arguments
+ ASYNC_CALLBACK_IMMEDIATE ); // Options
+
+ if( rc )
+ {
+ // If we failed to create the GpeRequest then there is a serious problem.
+ MAIN_TRAC_ERR("pgpe_init_clips: Failure creating the "
+ "IPC_MSGID_405_CLIPS GpeRequest. [RC=0x%08x]", rc );
+
+ /*
+ * @errortype
+ * @moduleid PGPE_INIT_CLIPS_MOD
+ * @reasoncode GPE_REQUEST_CREATE_FAILURE
+ * @userdata1 gpe_request_create return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure to create clips GpeRequest object
+ */
+ err = createErrl(
+ PGPE_INIT_CLIPS_MOD, //ModId
+ GPE_REQUEST_CREATE_FAILURE, //Reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //Userdata1
+ 0 //Userdata2
+ );
+ }
+
+ } while (0);
+
+ return(err);
+}
+
+// Function Specification
+//
+// Name: pgpe_init_pmcr
+//
+// Description: Create PGPE PMCR set IPC messages (non-blocking).
+//
+// End Function Specification
+
+errlHndl_t pgpe_init_pmcr(void)
+{
+ int rc; // return code
+ errlHndl_t err = NULL; // Error handler
+
+ do
+ {
+ //Initializes the GpeRequest object for pgpe PMCR setting IPC
+ rc = gpe_request_create(&G_pmcr_set_req, // GpeRequest for the task
+ &G_async_gpe_queue2, // Queue
+ IPC_MSGID_405_SET_PMCR, // Function ID
+ G_pmcr_set_parms_ptr, // Task parameters
+ SSX_WAIT_FOREVER, // Timeout (none)
+ NULL, // Callback
+ NULL, // Callback arguments
+ ASYNC_CALLBACK_IMMEDIATE); // Options
+
+ if( rc )
+ {
+ // If we failed to create the GpeRequest then there is a serious problem.
+ MAIN_TRAC_ERR("pgpe_init_pmcr: Failure creating the "
+ "IPC_MSGID_405_SET_PMCR GpeRequest. [RC=0x%08x]",
+ rc );
+
+ /*
+ * @errortype
+ * @moduleid PGPE_INIT_PMCR_MOD
+ * @reasoncode GPE_REQUEST_CREATE_FAILURE
+ * @userdata1 gpe_request_create return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure to create pmcr GpeRequest object
+ */
+ err = createErrl(
+ PGPE_INIT_PMCR_MOD, //ModId
+ GPE_REQUEST_CREATE_FAILURE, //Reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //Userdata1
+ 0 //Userdata2
+ );
+ }
+
+ } while (0);
+
+ return(err);
+}
+
+// Function Specification
+//
+// Name: pgpe_init_start_suspend
+//
+// Description: Create PGPE start/suspend IPC messages (blocking).
+//
+// End Function Specification
+
+errlHndl_t pgpe_init_start_suspend(void)
+{
+ int rc; // return code
+ errlHndl_t err = NULL; // Error handler
+
+ do
+ {
+ //Initializes the GpeRequest object for pgpe start/suspend IPC
+ rc = gpe_request_create(&G_start_suspend_req, // GpeRequest for the task
+ &G_async_gpe_queue2, // Queue
+ IPC_MSGID_405_START_SUSPEND, // Function ID
+ &G_start_suspend_parms, // Task parameters
+ SSX_WAIT_FOREVER, // Timeout (none)
+ (AsyncRequestCallback)pgpe_start_suspend_callback, // Callback
+ NULL, // Callback arguments
+ ASYNC_CALLBACK_IMMEDIATE ); // Options
+
+ if( rc )
+ {
+ // If we failed to create the GpeRequest then there is a serious problem.
+ MAIN_TRAC_ERR("pgpe_init_start_suspend: Failure creating the "
+ "IPC_MSGID_405_START_SUSPEND GpeRequest. [RC=0x%08x]",
+ rc );
+
+ /*
+ * @errortype
+ * @moduleid PGPE_INIT_START_SUSPEND_MOD
+ * @reasoncode GPE_REQUEST_CREATE_FAILURE
+ * @userdata1 gpe_request_create return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure to create start_suspend GpeRequest object
+ */
+ err = createErrl(
+ PGPE_INIT_START_SUSPEND_MOD, //ModId
+ GPE_REQUEST_CREATE_FAILURE, //Reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //Userdata1
+ 0 //Userdata2
+ );
+ }
+
+ } while (0);
+
+ return(err);
+}
+
+
+// Function Specification
+//
+// Name: pgpe_init_wof_control
+//
+// Description: Create PGPE WOF control IPC messages (non-blocking).
+//
+// End Function Specification
+
+errlHndl_t pgpe_init_wof_control(void)
+{
+ int rc; // return code
+ errlHndl_t err = NULL; // Error handler
+
+ do
+ {
+ //Initializes the GpeRequest object for pgpe wof control IPC
+ rc = gpe_request_create(&G_wof_control_req, // GpeRequest for the task
+ &G_async_gpe_queue2, // Queue
+ IPC_MSGID_405_WOF_CONTROL, // Function ID
+ &G_wof_control_parms, // Task parameters
+ SSX_WAIT_FOREVER, // Timeout (none)
+ NULL, // Callback
+ NULL, // Callback arguments
+ ASYNC_CALLBACK_IMMEDIATE); // Options
+
+ if( rc )
+ {
+ // If we failed to create the GpeRequest then there is a serious problem.
+ MAIN_TRAC_ERR("pgpe_init_wof_control: Failure creating the "
+ "IPC_MSGID_405_WOF_CONTROL GpeRequest. [RC=0x%08x]",
+ rc );
+
+ /*
+ * @errortype
+ * @moduleid PGPE_INIT_WOF_CONTROL_MOD
+ * @reasoncode GPE_REQUEST_CREATE_FAILURE
+ * @userdata1 gpe_request_create return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure to create wof control GpeRequest object
+ */
+ err = createErrl(
+ PGPE_INIT_WOF_CONTROL_MOD, //ModId
+ GPE_REQUEST_CREATE_FAILURE, //Reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //Userdata1
+ 0 //Userdata2
+ );
+ }
+
+ } while (0);
+
+ return(err);
+}
+
+// Function Specification
+//
+// Name: pgpe_init_wof_vfrt
+//
+// Description: Create PGPE WOF vfrt IPC messages (non-blocking).
+//
+// End Function Specification
+
+errlHndl_t pgpe_init_wof_vfrt(void)
+{
+ int rc; // return code
+ errlHndl_t err = NULL; // Error handler
+
+ do
+ {
+ //Initializes the GpeRequest object for pgpe wof vfrt IPC
+ rc = gpe_request_create(&G_wof_vfrt_req, // GpeRequest for the task
+ &G_async_gpe_queue2, // Queue
+ IPC_MSGID_405_WOF_VFRT, // Function ID
+ &G_wof_vfrt_parms, // Task parameters
+ SSX_WAIT_FOREVER, // Timeout (none)
+ NULL, // Callback
+ NULL, // Callback arguments
+ ASYNC_CALLBACK_IMMEDIATE); // Options
+
+ if( rc )
+ {
+ // If we failed to create the GpeRequest then there is a serious problem.
+ MAIN_TRAC_ERR("pgpe_init_wof_vfrt: Failure creating the "
+ "IPC_MSGID_405_WOF_VFRT GpeRequest. [RC=0x%08x]",
+ rc );
+
+ /*
+ * @errortype
+ * @moduleid PGPE_INIT_WOF_VFRT_MOD
+ * @reasoncode GPE_REQUEST_CREATE_FAILURE
+ * @userdata1 gpe_request_create return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Failure to create wof control GpeRequest object
+ */
+ err = createErrl(
+ PGPE_INIT_WOF_VFRT_MOD, //ModId
+ GPE_REQUEST_CREATE_FAILURE, //Reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //Userdata1
+ 0 //Userdata2
+ );
+ }
+
+ } while (0);
+
+ return(err);
+}
+
+
+// Function Specification
+//
+// Name: pgpe_widen_clip_ranges
+//
+// Description: Wide open PGPE clip ranges. Since this IPC call
+// is non-blocking, this routine has to assure call
+// completion before checking the pgpe return value.
+//
+// End Function Specification
+
+errlHndl_t pgpe_widen_clip_ranges(void)
+{
+
+ errlHndl_t err = NULL; // Error handler
+ uint8_t i; // Loop variable
+
+ // Set clip bounds wide open
+ for(i=0; i<MAX_QUADS; i++)
+ {
+ // minimum pstate
+ G_clip_update_parms_ptr->ps_val_clip_min[i] = pmin_rail();
+
+ // maximum pstate:
+ G_clip_update_parms_ptr->ps_val_clip_max[i] = proc_freq2pstate(G_proc_fmax_mhz);
+ }
+
+ // Check that no previous clip update calls are still in progress
+ if(async_request_is_idle(&G_clip_update_req.request))
+ {
+ // will check for this IPC completion at transition to active state
+ err = pgpe_clip_update();
+ }
+ else
+ {
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("pgpe_widen_clip_ranges: clip update IPC task is not Idle");
+
+ // log an error
+ MAIN_TRAC_ERR("pgpe_widen_clip_ranges: clip update IPC is not Idle");
+
+ /*
+ * @errortype
+ * @moduleid PGPE_WIDEN_CLIP_RANGES_MOD
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 0
+ * @userdata4 ERC_PGPE_NOT_IDLE
+ * @devdesc pgpe clip update not idle
+ */
+ err = createErrl(
+ PGPE_WIDEN_CLIP_RANGES_MOD, //ModId
+ PGPE_FAILURE, //Reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //Userdata1
+ 0 //Userdata2
+ );
+ }
+
+ return(err);
+}
+
+// Function Specification
+//
+// Name: pgpe_clip_update
+//
+// Description: call PGPE IPC to update clip ranges. Since this IPC call is
+// non-blocking, the calling function needs to assure previous
+// call completion before calling this call.
+//
+// End Function Specification
+
+errlHndl_t pgpe_clip_update(void)
+{
+ int rc; // gpe schedule return code
+ errlHndl_t err = NULL; // Error handler
+
+ do
+ {
+ // Caller must check the completion of previous invocation of clip updates.
+ // This check is a safety feature in case caller didn't check IPC is idle.
+ if(!async_request_is_idle(&G_clip_update_req.request))
+ {
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("pgpe_clip_update: clip update IPC task is not Idle");
+
+ /*
+ * @errortype
+ * @moduleid PGPE_CLIP_UPDATE_MOD
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 0
+ * @userdata4 ERC_PGPE_NOT_IDLE
+ * @devdesc pgpe clip update not idle
+ */
+ err = createErrl(
+ PGPE_CLIP_UPDATE_MOD, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_NOT_IDLE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //Userdata1
+ 0 //Userdata2
+ );
+
+ break;
+ }
+
+ // @TODO: remove this precompile directive check when PGPE code is integrated.
+ // RTC: 163934
+#ifdef PGPE_SUPPORT
+ // Schedule PGPE clip update IPC task
+ rc = gpe_request_schedule(&G_clip_update_req);
+#else
+ G_start_suspend_parms.msg_cb.rc = PGPE_RC_SUCCESS;
+ rc = 0;
+#endif
+ // Confirm Successfull completion of PGPE clip update task
+ if(rc != 0)
+ {
+ //Error in scheduling pgpe clip update task
+ TRAC_ERR("pgpe_clip_update: Failed to schedule clip update pgpe task rc=%x",
+ rc);
+
+ /* @
+ * @errortype
+ * @moduleid PGPE_CLIP_UPDATE_MOD
+ * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE
+ * @userdata1 rc - gpe_request_schedule return code
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC Failed to schedule a GPE job for clip update
+ */
+ err = createErrl(
+ PGPE_CLIP_UPDATE_MOD, // modId
+ GPE_REQUEST_SCHEDULE_FAILURE, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ rc, // userdata1
+ 0 // userdata2
+ );
+
+ REQUEST_RESET(err); //This will add a firmware callout for us
+ }
+ }while(0);
+
+ return err;
+}
+
+
+// Function Specification
+//
+// Name: start_suspend_callback
+//
+// Description: callback function for the pgpe_start_suspend IPC function
+// gets called after the PGPE IPC enables/disables pstates.
+// Upon successful completion, it sets/clears the G_proc_pstate_status
+// flag to indicat whether it is enabled/disabled/in-transition.
+//
+// End Function Specification
+
+void pgpe_start_suspend_callback(void)
+{
+ int pgpe_rc; // pgpe return codes
+ errlHndl_t err = NULL; // Error handler
+
+ pgpe_rc = G_start_suspend_parms.msg_cb.rc;
+
+ do
+ {
+ // Confirm Successfull completion of PGPE clup update task
+ if(pgpe_rc != PGPE_RC_SUCCESS)
+ {
+ //Error in scheduling pgpe clip update task
+
+ /* @
+ * @errortype
+ * @moduleid PGPE_START_SUSPEND_CALLBACK_MOD
+ * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE
+ * @userdata1 pgpe_rc - PGPE return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC Failed to schedule a GPE job for start_suspend
+ */
+ err = createErrl(
+ PGPE_START_SUSPEND_CALLBACK_MOD, // modId
+ PGPE_FAILURE, // reasoncode
+ ERC_PGPE_UNSUCCESSFULL, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ pgpe_rc, // userdata1
+ 0 // userdata2
+ );
+
+ REQUEST_RESET(err); //This will add a firmware callout for us
+ break;
+ }
+ // task completed successfully
+ else
+ {
+ // this was a command to enable pstates
+ if(G_start_suspend_parms.action == PGPE_ACTION_PSTATE_START)
+ {
+ // Pstates are now enabled (enable Active State transition).
+ G_proc_pstate_status = PSTATES_ENABLED;
+ }
+ // this was a command to disable pstates
+ else if(G_start_suspend_parms.action == PGPE_ACTION_PSTATE_SUSPEND)
+ {
+ // Pstates are now disabled (disaable Active State transition).
+ G_proc_pstate_status = PSTATES_DISABLED;
+ }
+
+ G_proc_pmcr_owner = G_start_suspend_parms.pmcr_owner;
+ }
+
+ } while(0);
+
+}
+
+// Function Specification
+//
+// Name: pgpe_start_suspend
+//
+// Description: Schedule a PGPE IPC to enable/disable pstates. This will also tell
+// PGPE how to set PMCR mode register (OCC/OPAL control pstates).
+// when this IPC is successfully scheduled, it sets the G_proc_pstate_status
+// global variable to in-transition, a call back function
+// (pgpe_start_suspend_callback) will set it to the appropriate value upon
+// successfull completion.
+//
+// End Function Specification
+
+errlHndl_t pgpe_start_suspend(uint8_t action)
+{
+ PMCR_OWNER owner; // PMCR owner
+ int rc; // gpe schedule return codes
+ errlHndl_t err = NULL; // Error handler
+
+ // For now, we set PMCR ownership based on whether the system
+ // is OPAL system or not.
+ if(G_sysConfigData.system_type.kvm)
+ {
+ owner = PMCR_OWNER_HOST;
+ }
+ else
+ {
+ owner = PMCR_OWNER_OCC;
+ }
+
+ // set the IPC parameters
+ G_start_suspend_parms.action = action;
+ G_start_suspend_parms.pmcr_owner = owner;
+
+ // @TODO: remove this precompile directive check when PGPE code is integrated.
+ // RTC: 163934
+#ifdef PGPE_SUPPORT
+ // Schedule PGPE start_suspend task
+ rc = gpe_request_schedule(&G_start_suspend_req);
+#else
+ rc = 0;
+#endif
+
+ // couldn't schedule the IPC task?
+ if(rc != 0)
+ {
+ //Error in scheduling pgpe clip update task
+ TRAC_ERR("pgpe_start_suspend: Failed to schedule pgpe start_suspend task rc=%x",
+ rc);
+ /* @
+ * @errortype
+ * @moduleid PGPE_START_SUSPEND_MOD
+ * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE
+ * @userdata1 rc - gpe_request_schedule return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC Failed to schedule a GPE job for start_suspend
+ */
+ err = createErrl(
+ PGPE_START_SUSPEND_MOD, // modId
+ GPE_REQUEST_SCHEDULE_FAILURE, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ rc, // userdata1
+ 0 // userdata2
+ );
+
+ REQUEST_RESET(err); //This will add a firmware callout for us
+ }
+ // successfully scheduled, set the G_proc_pstate_status to indicate transition
+ else
+ {
+ G_proc_pstate_status = PSTATES_IN_TRANSITION;
+ }
+
+#ifndef PGPE_SUPPORT
+ pgpe_start_suspend_callback();
+#endif
+
+ return err;
+}
+
+
+// Function Specification
+//
+// Name: pgpe_pmcr_set
+//
+// Description: call PGPE IPC to set the PMCR with the pstate values.
+// Since this IPC call is non-blocking, the calling
+// function needs to assure previous call completion
+// before calling this call.
+//
+// End Function Specification
+
+errlHndl_t pgpe_pmcr_set(void)
+{
+ int rc; // gpe schedule return codes
+ errlHndl_t err = NULL; // Error handler
+
+ do
+ {
+ // Caller must check the completion of previous invocation of pmcr set IPC call.
+ // This check is a safety feature in case caller didn't check IPC is idle.
+ if(!async_request_is_idle(&G_pmcr_set_req.request))
+ {
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("pgpe_pmcr_set: clip update IPC task is not Idle");
+
+ /*
+ * @errortype
+ * @moduleid PGPE_PMCR_SET_MOD
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 0
+ * @userdata4 ERC_PGPE_NOT_IDLE
+ * @devdesc pgpe pmcr set not idle
+ */
+ err = createErrl(
+ PGPE_PMCR_SET_MOD, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_NOT_IDLE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //Userdata1
+ 0 //Userdata2
+ );
+
+ break;
+ }
+
+ // @TODO: remove this precompile directive check when PGPE code is integrated.
+ // RTC: 163934
+#ifdef PGPE_SUPPORT
+ // Schedule PGPE clip update IPC task
+ rc = gpe_request_schedule(&G_pmcr_set_req);
+#else
+ rc = 0;
+#endif
+
+ // Confirm Successfull completion of PGPE clup update task
+ if(rc != 0)
+ {
+ //Error in scheduling pgpe clip update task
+ TRAC_ERR("pgpe_pmcr_set: Failed to schedule PMCR setup pgpe task rc=%x",
+ rc);
+ }
+
+ if(rc != 0)
+ {
+ /* @
+ * @errortype
+ * @moduleid PGPE_PMCR_SET_MOD
+ * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE
+ * @userdata1 rc - gpe_request_schedule return code
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC Failed to schedule a GPE job for clip update
+ */
+ err = createErrl(
+ PGPE_PMCR_SET_MOD, // modId
+ GPE_REQUEST_SCHEDULE_FAILURE, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ rc, // userdata1
+ 0 // userdata2
+ );
+
+ REQUEST_RESET(err); //This will add a firmware callout for us
+ }
+ }
+ while(0);
+
+ return err;
+}
+
diff --git a/src/occ_405/pgpe/pgpe_interface.h b/src/occ_405/pgpe/pgpe_interface.h
new file mode 100644
index 0000000..a777f28
--- /dev/null
+++ b/src/occ_405/pgpe/pgpe_interface.h
@@ -0,0 +1,45 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/pgpe/pgpe_interface.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
+/* [+] 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 _PGPE_INTERFACE_H_
+#define _PGPE_INTERFACE_H_
+
+#include "errl.h"
+
+errlHndl_t init_pgpe_ipcs(void);
+
+errlHndl_t pgpe_init_clips(void);
+errlHndl_t pgpe_init_pmcr(void);
+errlHndl_t pgpe_init_start_suspend(void);
+errlHndl_t pgpe_init_wof_control(void);
+errlHndl_t pgpe_init_wof_vfrt(void);
+
+errlHndl_t pgpe_widen_clip_ranges(void);
+errlHndl_t pgpe_clip_update(void);
+errlHndl_t pgpe_pmcr_set(void);
+errlHndl_t pgpe_start_suspend(uint8_t action);
+void pgpe_start_suspend_callback(void);
+
+#endif /* #ifndef _PGPE_INTERFACE_H_ */
diff --git a/src/occ_405/pgpe/pgpe_service_codes.h b/src/occ_405/pgpe/pgpe_service_codes.h
new file mode 100644
index 0000000..2e66952
--- /dev/null
+++ b/src/occ_405/pgpe/pgpe_service_codes.h
@@ -0,0 +1,46 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/pgpe/pgpe_service_codes.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,2016 */
+/* [+] 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 _PGPE_SERVICE_CODES_H_
+#define _PGPE_SERVICE_CODES_H_
+
+#include <comp_ids.h>
+
+enum pgpeModuleId
+{
+ PGPE_INIT_CLIPS_MOD = PGPE_COMP_ID | 0x00,
+ PGPE_INIT_PMCR_MOD = PGPE_COMP_ID | 0x01,
+ PGPE_INIT_START_SUSPEND_MOD = PGPE_COMP_ID | 0x02,
+ PGPE_INIT_WOF_CONTROL_MOD = PGPE_COMP_ID | 0x03,
+ PGPE_INIT_WOF_VFRT_MOD = PGPE_COMP_ID | 0x04,
+ PGPE_CLIP_UPDATE_MOD = PGPE_COMP_ID | 0x05,
+ PGPE_START_SUSPEND_MOD = PGPE_COMP_ID | 0x06,
+ PGPE_PMCR_SET_MOD = PGPE_COMP_ID | 0x07,
+ PGPE_WIDEN_CLIP_RANGES_MOD = PGPE_COMP_ID | 0x08,
+ PGPE_START_SUSPEND_CALLBACK_MOD = PGPE_COMP_ID | 0x09,
+};
+
+
+#endif /* #ifndef _PGPE_SERVICE_CODES_H_ */
diff --git a/src/occ_405/pgpe_shared.h b/src/occ_405/pgpe/pgpe_shared.h
index 0dac88f..eb4b27a 100644
--- a/src/occ_405/pgpe_shared.h
+++ b/src/occ_405/pgpe/pgpe_shared.h
@@ -1,7 +1,7 @@
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
-/* $Source: src/occ_405/pgpe_shared.h $ */
+/* $Source: src/occ_405/pgpe/pgpe_shared.h $ */
/* */
/* OpenPOWER OnChipController Project */
/* */
@@ -26,6 +26,8 @@
#define PGPE_HEADER_ADDR 0xFFF20180 // 0xfff20000 + 0x180
#define PGPE_HEADER_SZ 96 // Size of PGPE Image header
+#define PGPE_MAGIC_NUMBER 0x5849502050475045ull // "XIP PGPE"
+
// Offset addresses of PGPE Header parameters (relative to start address)
#define PGPE_SHARED_SRAM_ADDR_OFFSET 0x0c
#define PGPE_SHARED_SRAM_SZ_OFFSET 0x14
@@ -40,3 +42,32 @@
// A pointer to PGPE Beacon Address
#define PGPE_BEACON_ADDR_PTR (PGPE_HEADER_ADDR + PGPE_BEACON_ADDR_OFFSET)
+
+// PMMR (Pstates PM region) in HOMMR
+#define PPMR_OPPM_ADDR_OFFSET 0x40 //offset of the OCC Pstates Parameter Block address in the PPMR header
+#define PPMR_OPPM_SZ_OFFSET 0x44 //offset of the OCC Pstates Parameter Block size in the PPMR header
+
+
+// This size must be a multiple of 128
+typedef struct __attribute__ ((packed))
+{
+ uint64_t magic_number;
+ uint32_t bc_offset;
+ uint32_t resserved;
+ uint32_t bl_offset;
+ uint32_t bl_length;
+ uint32_t build_date;;
+ uint32_t version;
+ uint8_t resvd_flag[8];
+ uint32_t pgpe_hcode_offset;
+ uint32_t pgpe_hcode_length;
+ uint32_t gppb_offset;
+ uint32_t gppb_length;
+ uint32_t lppb_offset;
+ uint32_t lppb_length;
+ uint32_t oppb_offset;
+ uint32_t oppb_length;
+ uint32_t pstables_offset;
+ uint32_t pstables_length;
+ uint8_t pad[48];
+} ppmr_header_t __attribute__ ((aligned (128)));
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);
diff --git a/src/occ_405/pss/apss.c b/src/occ_405/pss/apss.c
index e93b156..ae4d100 100755
--- a/src/occ_405/pss/apss.c
+++ b/src/occ_405/pss/apss.c
@@ -1097,7 +1097,7 @@ errlHndl_t initialize_apss(void)
//Create the request for measure start. Scheduling will happen in apss.c
gpe_request_create(&G_meas_start_request,
&G_async_gpe_queue0, // queue
- IPC_ST_APSS_START_PWR_MEAS_READ_FUNCID, // entry_point
+ IPC_ST_APSS_START_PWR_MEAS_READ_FUNCID, // entry_point
&G_gpe_start_pwr_meas_read_args, // entry_point arg
SSX_WAIT_FOREVER, // no timeout
NULL, // callback
diff --git a/src/occ_405/rtls/rtls.h b/src/occ_405/rtls/rtls.h
index 6da6825..8babaab 100755
--- a/src/occ_405/rtls/rtls.h
+++ b/src/occ_405/rtls/rtls.h
@@ -53,11 +53,11 @@ typedef enum {
TASK_ID_DCOM_TX_OUTBX,
TASK_ID_MISC_405_CHECKS, // Miscellaneous checks to be done by 405
TASK_ID_DCOM_PARSE_FW_MSG,
- TASK_ID_AMEC_SLAVE, // AMEC SMH tasks
- TASK_ID_AMEC_MASTER, // AMEC SMH tasks
-// TASK_ID_CORE_DATA_CONTROL, // TODO RTC: 163365
+ TASK_ID_AMEC_SLAVE, // AMEC SMH tasks
+ TASK_ID_AMEC_MASTER, // AMEC SMH tasks
+ TASK_ID_CORE_DATA_CONTROL,
// TASK_ID_GPU_SM, // GPU State Machine TODO RTC: 133824
- TASK_ID_DIMM_SM, // DIMM State Machine
+ TASK_ID_DIMM_SM, // DIMM State Machine
TASK_ID_MEMORY_CONTROL, // Memory (centaur/dimm) control task
TASK_ID_NEST_DTS,
TASK_END // This must always be the last enum in this list,
diff --git a/src/occ_405/rtls/rtls_service_codes.h b/src/occ_405/rtls/rtls_service_codes.h
index 5aab728..44f20d8 100755
--- a/src/occ_405/rtls/rtls_service_codes.h
+++ b/src/occ_405/rtls/rtls_service_codes.h
@@ -30,12 +30,13 @@
enum rtlsModuleId
{
- RTLS_OCB_INIT_MOD = RTLS_COMP_ID | 0x00,
- RTLS_DO_TICK_MOD = RTLS_COMP_ID | 0x01,
- RTLS_START_TASK_MOD = RTLS_COMP_ID | 0x02,
- RTLS_STOP_TASK_MOD = RTLS_COMP_ID | 0x03,
- RTLS_TASK_RUNABLE_MOD = RTLS_COMP_ID | 0x04,
- RTLS_SET_TASK_DATA_MOD = RTLS_COMP_ID | 0x05,
+ RTLS_OCB_INIT_MOD = RTLS_COMP_ID | 0x00,
+ RTLS_DO_TICK_MOD = RTLS_COMP_ID | 0x01,
+ RTLS_START_TASK_MOD = RTLS_COMP_ID | 0x02,
+ RTLS_STOP_TASK_MOD = RTLS_COMP_ID | 0x03,
+ RTLS_TASK_RUNABLE_MOD = RTLS_COMP_ID | 0x04,
+ RTLS_SET_TASK_DATA_MOD = RTLS_COMP_ID | 0x05,
+ RTLS_TASK_CORE_DATA_CONTROL_MOD = RTLS_COMP_ID | 0x06,
};
#endif /* #ifndef _RTLS_SERVICE_CODES_H_ */
diff --git a/src/occ_405/rtls/rtls_tables.c b/src/occ_405/rtls/rtls_tables.c
index b7b1a4c..fdcce40 100755
--- a/src/occ_405/rtls/rtls_tables.c
+++ b/src/occ_405/rtls/rtls_tables.c
@@ -113,8 +113,7 @@ task_t G_task_table[TASK_END] = {
{ FLAGS_DCOM_PARSE_OCC_FW_MSG, task_dcom_parse_occfwmsg, NULL }, // TASK_ID_DCOM_PARSE_FW_MSG
{ FLAGS_AMEC_SLAVE, task_amec_slave, NULL }, // TASK_ID_AMEC_SLAVE
{ FLAGS_AMEC_MASTER, task_amec_master, NULL }, // TASK_ID_AMEC_MASTER
-// TODO RTC: 163365 - /proc/ and /pss/ "TODO" cleanup
-// { FLAGS_CORE_DATA_CONTROL, task_core_data_control, NULL }, // TASK_ID_CORE_DATA_CONTROL
+ { FLAGS_CORE_DATA_CONTROL, task_core_data_control, NULL }, // TASK_ID_CORE_DATA_CONTROL
// TODO RTC: 133824 - New GPU interface via main memory and SMBUS
// { FLAGS_GPU_SM, task_gpu_sm, NULL }, // TASK_ID_GPU_SM
{ FLAGS_MEMORY_DATA, task_dimm_sm, NULL }, // TASK_ID_DIMM_SM
@@ -130,7 +129,7 @@ const uint8_t G_tick0_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -149,7 +148,7 @@ const uint8_t G_tick1_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -170,7 +169,7 @@ const uint8_t G_tick2_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -190,7 +189,7 @@ const uint8_t G_tick3_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -210,7 +209,7 @@ const uint8_t G_tick4_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -229,7 +228,7 @@ const uint8_t G_tick5_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -249,7 +248,7 @@ const uint8_t G_tick6_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -268,7 +267,7 @@ const uint8_t G_tick7_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -288,7 +287,7 @@ const uint8_t G_tick8_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -307,7 +306,7 @@ const uint8_t G_tick9_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -328,7 +327,7 @@ const uint8_t G_tick10_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -347,7 +346,7 @@ const uint8_t G_tick11_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -367,7 +366,7 @@ const uint8_t G_tick12_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -386,7 +385,7 @@ const uint8_t G_tick13_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -406,7 +405,7 @@ const uint8_t G_tick14_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
@@ -425,7 +424,7 @@ const uint8_t G_tick15_seq[] = {
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
TASK_ID_MEMORY_CONTROL,
- //TASK_ID_CORE_DATA_CONTROL,
+ TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_RX_OUTBX,
diff --git a/src/occ_405/state.c b/src/occ_405/state.c
index 956d06e..bac2de8 100755
--- a/src/occ_405/state.c
+++ b/src/occ_405/state.c
@@ -32,18 +32,23 @@
#include "state.h"
#include "dcom.h"
#include "occ_service_codes.h"
-#include "proc_pstate.h"
#include "cmdh_fsp_cmds_datacnfg.h"
#include "cmdh_fsp.h"
#include "proc_data.h"
#include "scom.h"
#include <fir_data_collect.h>
#include <dimm.h>
+#include "pgpe_interface.h"
+#include "pstate_pgpe_occ_api.h"
extern bool G_mem_monitoring_allowed;
extern task_t G_task_table[TASK_END]; // Global task table
extern bool G_simics_environment;
+extern GpeRequest G_clip_update_req;
+extern GPE_BUFFER(ipcmsg_clip_update_t* G_clip_update_parms_ptr);
+
+
// Maximum allowed value approx. 16.3 ms
#define PCBS_HEARBEAT_TIME_US 16320
@@ -141,9 +146,6 @@ errlHndl_t SMGR_standby_to_observation()
rtl_clr_run_mask_deferred(RTL_FLAG_STANDBY);
rtl_set_run_mask_deferred(RTL_FLAG_OBS);
- // Initialize key freq2pstate Global parameters
- proc_pstate_initialize();
-
// Set the actual STATE now that we have finished everything else
CURRENT_STATE() = OCC_STATE_OBSERVATION;
@@ -211,9 +213,9 @@ errlHndl_t SMGR_observation_to_standby()
// Function Specification
//
-// Name:
+// Name: SMGR_observation_to_active
//
-// Description:
+// Description: Transition from Observation state to Active state
//
// End Function Specification
errlHndl_t SMGR_observation_to_active()
@@ -223,19 +225,89 @@ errlHndl_t SMGR_observation_to_active()
int l_extRc = OCC_NO_EXTENDED_RC;
int l_rc = 0;
- // Pstates are enabled via an IPC call to PGPE once the OCC reaches the
- // observation state. We still have to check that the enable_pstates() IPC job
- // on the PGPE has completed before transitioning to active state. Otherwise,
- // we wait TBD seconds in case we are going directly from Standby to Active
- // (pstate init only happens in observation state, so it might not be
- // done yet...must call it in this while loop since it is done in this
- // same thread...)
- //
+ // confirm that the clip update IPC call to widen clip ranges
+ // has successfully completed on PGPE (with no errors)
+ if( !async_request_is_idle(&G_clip_update_req.request) ) //widen_clip_ranges didn't complete
+ {
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("SMGR: clip update IPC task is not Idle");
+
+ /*
+ * @errortype
+ * @moduleid MAIN_SMGR_MID
+ * @reasoncode PGPE_FAILURE
+ * @userdata4 ERC_PGPE_NOT_IDLE
+ * @devdesc pgpe clip update not idle
+ */
+ l_errlHndl = createErrl(
+ MAIN_SMGR_MID, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_NOT_IDLE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //Userdata1
+ 0 //Userdata2
+ );
+ // TODO now: REQUEST_RESET?
+ }
+ else if ( G_clip_update_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS ) // IPC task completed with errors
+ {
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("SMGR: clip update IPC task returned an error [0x%08X]",
+ G_clip_update_parms_ptr->msg_cb.rc);
+
+ /*
+ * @errortype
+ * @moduleid MAIN_SMGR_MID
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 PGPE clip update's rc
+ * @userdata4 ERC_PGPE_CLIP_FAILURE
+ * @devdesc pgpe clip update not idle
+ */
+ l_errlHndl = createErrl(
+ MAIN_SMGR_MID, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_CLIP_FAILURE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ G_clip_update_parms_ptr->msg_cb.rc, //Userdata1
+ 0 //Userdata2
+ );
+ // TODO now: REQUEST_RESET?
+ }
+
+ else // Clips wide opened with no errors, enable Pstates on PGPE
+ {
+
+ // Pstates are enabled via an IPC call to PGPE, which will
+ // set the G_proc_pstate_status flag
+
+ l_errlHndl = pgpe_start_suspend(PGPE_ACTION_PSTATE_START);
+
+ if(l_errlHndl)
+ {
+ TRAC_ERR("SMGR: Failed to switch to Active state because of a "
+ "failure to start the pstate protocol on PGPE.");
+ }
+ else
+ {
+ // Pstates enabled, update OPAL static table in main memory
+ if(G_sysConfigData.system_type.kvm)
+ {
+ // upon succesful enablement of Pstate protocol on
+ // PGPE update OPAL table with pstate information.
+ proc_pstate_kvm_setup();
+ }
+ }
+ }
+
// NOTE that this is really unnecessary if you follow the TMGT OCC
// Interface Spec, which tells you that you need to check for the "Active
// Ready" bit in the poll response before you go to active state.
// But since we have scenerios where TMGT isn't the one putting us in
- // active state (we are going there automatically) we needed to add this
+ // active state (we are going there automatically) we needed to add this.
// If we have all data we need to go to active state, but don't have pstates
// enabled yet...then we will do the aforementioned wait
@@ -253,8 +325,8 @@ errlHndl_t SMGR_observation_to_active()
{
TRAC_ERR("SMGR: Timeout waiting for Pstates to be enabled, "
"pmc_mode[%08x], chips_present[%02x], Cores Present [%08x]",
- in32(PMC_MODE_REG),
- G_sysConfigData.is_occ_present,
+ in32(PMC_MODE_REG),
+ G_sysConfigData.is_occ_present,
(uint32_t) ((in64(OCB_CCSR)) >> 32));
}
l_extRc = ERC_GENERIC_TIMEOUT;
diff --git a/src/occ_405/timer/timer.c b/src/occ_405/timer/timer.c
index ef42c5c..7893497 100755
--- a/src/occ_405/timer/timer.c
+++ b/src/occ_405/timer/timer.c
@@ -507,15 +507,15 @@ void check_pgpe_beacon(void)
/*
* @errortype
* @moduleid POKE_WD_TIMERS
- * @reasoncode INTERNAL_HW_FAILURE
+ * @reasoncode PGPE_FAILURE
* @userdata1 PGPE Beacon Value
* @userdata2 PGPE Beacon Address
- * @userdata4 PGPE_BEACON_TIMEOUT
+ * @userdata4 ERC_PGPE_BEACON_TIMEOUT
* @devdesc PGPE Beacon timeout
*/
l_err = createErrl(POKE_WD_TIMERS, // mod id
- PGPE_BEACON_TIMEOUT, // reason code
- OCC_NO_EXTENDED_RC, // Extended reason code
+ PGPE_FAILURE, // reason code
+ ERC_PGPE_BEACON_TIMEOUT, // Extended reason code
ERRL_SEV_UNRECOVERABLE, // severity
NULL, // trace buffer
0, // trace size
diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk
index c5c16a0..ed33ebf 100644
--- a/src/occ_405/topfiles.mk
+++ b/src/occ_405/topfiles.mk
@@ -72,7 +72,9 @@ TOP-C-SOURCES = amec/amec_analytics.c \
mode.c \
occ_sys_config.c \
occbuildname.c \
+ pgpe/pgpe_interface.c \
proc/proc_data.c \
+ proc/proc_data_control.c \
proc/proc_pstate.c \
pss/apss.c \
pss/avsbus.c \
OpenPOWER on IntegriCloud