Skip to content

Commit

Permalink
Pstates Support in OCC
Browse files Browse the repository at this point in the history
1. Initialize Pstates global parameters (G_proc_fmax, G_proc_fmin,
G_khz_per_pstate and G_proc_pmin from the OCC Pstate Parameter
Block)

2. When frequency config data packet is received and OCC is NOT
already in Active state:  Send IPC command to PGPE to set pState
clips to be wide open from min frequency to turbo
First verify min/max frequency from TMGT is within what
PGPE allows saved in G_proc_fmax and G_proc_fmin if not
within bounds trace and clip to G_proc_fmax/fmin)

3. Transition to active state:  Send IPC command to PGPE to start
pState protocol (give correct data for OCC vs OPAL in control of
Pstates) and if OPAL system update OPAL shared memory with Pstate
information.

4. amec_slv_freq_smh():  Send IPC command to PGPE to set requested
pState (PowerVM) or set clips (OPAL).

5. Address all the TODO/TEMP/#if 0 in amec_freq.c  either remove
or add RTC# for when it will be addressed

Change-Id: Ic323321b8c66945732a6b7345ad85d6f41a62edd
RTC: 130201
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33704
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Reviewed-by: Andres A. Lugo-Reyes <aalugore@us.ibm.com>
Reviewed-by: Wael El-Essawy <welessa@us.ibm.com>
  • Loading branch information
essawy committed Jan 27, 2017
1 parent c35e73b commit 360934d
Show file tree
Hide file tree
Showing 31 changed files with 1,843 additions and 468 deletions.
12 changes: 6 additions & 6 deletions src/common/ipc_func_ids.h
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/include/p9_pstates_occ.h
Expand Up @@ -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;


Expand Down
3 changes: 2 additions & 1 deletion src/occ_405/Makefile
Expand Up @@ -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
Expand Down
37 changes: 24 additions & 13 deletions src/occ_405/amec/amec_data.c
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -98,31 +101,39 @@ 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
// min/max for AMEC component. PowerVM on BMC and FSP the min/max is set above
// 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;
}

Expand Down
76 changes: 52 additions & 24 deletions src/occ_405/amec/amec_freq.c
Expand Up @@ -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
//*************************************************************************
Expand All @@ -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.
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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
}


Expand Down
2 changes: 0 additions & 2 deletions src/occ_405/amec/amec_sys.h
Expand Up @@ -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;

Expand Down
73 changes: 47 additions & 26 deletions src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
Expand Up @@ -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))
Expand All @@ -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
{
Expand Down Expand Up @@ -284,59 +281,84 @@ 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]);
if (l_freq != 0)
{
// 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
Expand All @@ -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]) ||
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions src/occ_405/homer.h
Expand Up @@ -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
Expand Down

0 comments on commit 360934d

Please sign in to comment.