Skip to content

Commit

Permalink
Update quad power off so HB can call it on Slave Quads
Browse files Browse the repository at this point in the history
Previously this HWP was only being called by the SBE down the MPIPL
but we also need to call it during HB to power down the slave quads.
There is a tricky workaround in this HWP where we need to save off
some ring data EQ pointers for the PB. On the SBE we just saved
the rings in global variables but we cannot do that in HB because
the Hcode would not have access to the global varibles. Instead
we will write the ring data to the OCC SRAM to do this I will
just pass the data out of the hwp via an out param
The same ring data is fetch during cache_initf procedure to init

Change-Id: I4f20cd8dd9ca1b53604db1bc3020c0d57bbd1172
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/36828
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Matt K. Light <mklight@us.ibm.com>
Reviewed-by: RAJA DAS <rajadas2@in.ibm.com>
Reviewed-by: YUE DU <daviddu@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/37978
Reviewed-by: Hostboot Team <hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
  • Loading branch information
crgeddes committed Mar 23, 2017
1 parent 3f78eca commit ae07790
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 133 deletions.
34 changes: 14 additions & 20 deletions src/import/chips/p9/procedures/hwp/pm/p9_quad_power_off.C
Expand Up @@ -49,14 +49,11 @@
#include <p9_quad_power_off.H>
#include <p9_block_wakeup_intr.H>


// ----------------------------------------------------------------------
// Function definitions
// ----------------------------------------------------------------------


#ifdef __PPE__
uint64_t G_ring_save[8] = {0, 0, 0, 0, 0, 0, 0, 0};

// {0, 0},
// {5039, 0xE000000000000000}, //3
// {5100, 0xC1E061FFED5F0000}, //29
Expand All @@ -67,40 +64,38 @@ uint64_t G_ring_save[8] = {0, 0, 0, 0, 0, 0, 0, 0};
// {6282, 0xE000000000000000}, //3
// {6343, 0xC1E061FFED5F0000}, //29
// {17871, 0} //128
const uint64_t G_ring_index[10] =

static const uint64_t RING_INDEX[10] =
{
0, 5039, 5100, 5664, 5725, 5973, 6034, 6282, 6343, 17871,
};
#endif


// Procedure p9_quad_power_off entry point, comments in header
fapi2::ReturnCode p9_quad_power_off(
const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target)
const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
uint64_t* o_ring_save_data)
{
fapi2::buffer<uint64_t> l_data64;
constexpr uint64_t l_rawData = 0x1100000000000000ULL; // Bit 3 & 7 are set to be manipulated
constexpr uint32_t MAX_CORE_PER_QUAD = 4;
fapi2::ReturnCode rc = fapi2::FAPI2_RC_SUCCESS;
uint32_t l_cnt = 0;
#ifdef __PPE__
uint8_t l_isMpipl = 0;
uint8_t l_isRingSaveMpipl = 0;
const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_chip =
i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_MPIPL, FAPI_SYSTEM, l_isMpipl), "fapiGetAttribute of ATTR_IS_MPIPL failed!");
FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_RING_SAVE_MPIPL, l_chip, l_isRingSaveMpipl),
"fapiGetAttribute of ATTR_CHIP_EC_FEATURE_RING_SAVE_MPIPL failed");
#endif
uint8_t l_isMpipl = 0;
uint8_t l_isRingSaveMpipl = 0;
const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;

FAPI_INF("p9_quad_power_off: Entering...");

// Print chiplet position
FAPI_INF("Quad power off chiplet no.%d", i_target.getChipletNumber());

#ifdef __PPE__
FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_MPIPL, FAPI_SYSTEM, l_isMpipl), "fapiGetAttribute of ATTR_IS_MPIPL failed!");
FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_RING_SAVE_MPIPL, l_chip, l_isRingSaveMpipl),
"fapiGetAttribute of ATTR_CHIP_EC_FEATURE_RING_SAVE_MPIPL failed");


if (l_isMpipl && l_isRingSaveMpipl)
{
Expand All @@ -123,7 +118,7 @@ fapi2::ReturnCode p9_quad_power_off(
{
uint64_t l_scandata = ((l_spin == 0) || (l_spin == 9)) ? 0x0 : (l_spin & 0x1) ?
0xE000000000000000 : 0xC1E061FFED5F0000;
l_data64.flush<0>().set((G_ring_index[l_spin] - G_ring_index[l_spin - 1]) << 32);
l_data64.flush<0>().set((RING_INDEX[l_spin] - RING_INDEX[l_spin - 1]) << 32);

FAPI_TRY(fapi2::putScom(i_target,
EQ_SCAN_LONG_ROTATE,
Expand Down Expand Up @@ -160,7 +155,7 @@ fapi2::ReturnCode p9_quad_power_off(
FAPI_TRY(fapi2::getScom(i_target,
EQ_SCAN64,
l_data64));
G_ring_save[l_spin - 1] = l_scandata & l_data64;
o_ring_save_data[l_spin - 1] = l_scandata & l_data64;
}
}

Expand All @@ -170,7 +165,6 @@ fapi2::ReturnCode p9_quad_power_off(
l_data64));
}

#endif

FAPI_DBG("Disabling bits 20/22/24/26 in EQ_QPPM_QPMMR_CLEAR, to gain access"
" to PFET controller, otherwise Quad Power off scom will fail");
Expand Down
15 changes: 7 additions & 8 deletions src/import/chips/p9/procedures/hwp/pm/p9_quad_power_off.H
Expand Up @@ -48,14 +48,10 @@
// Constant definitions
//------------------------------------------------------------------------------

#ifdef __PPE__
extern uint64_t G_ring_save[8];
extern const uint64_t G_ring_index[10];
#endif

// function pointer typedef definition for HWP call support
typedef fapi2::ReturnCode (*p9_quad_power_off_FP_t) (
const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target);
const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
uint64_t* o_ring_save_data);

extern "C"
{
Expand All @@ -66,12 +62,15 @@ extern "C"
/**
** @brief Power off the EQ including the functional cores associatated with it.
**
** @param[in] i_target Targe type EQ
** @param[in] i_target Targe type EQ
** @param[out] o_ring_save_data The ring data that tells the PB how to find the
** EQ will need to be saved away for when we p-on
**
** @return FAPI2_RC_SUCCESS if success, error otherwise
**/
fapi2::ReturnCode p9_quad_power_off (
const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target);
const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
uint64_t* o_ring_save_data);

} // extern "C"

Expand Down
161 changes: 56 additions & 105 deletions src/usr/isteps/istep06/host_discover_targets.C
Expand Up @@ -28,10 +28,8 @@
#include <map>
#include <vector>
#include <trace/interface.H>
#include <sys/misc.h>
#include <errl/errlentry.H>
#include <errl/errlmanager.H>
#include <errl/errludtarget.H>
#include <targeting/attrsync.H>
#include <targeting/namedtarget.H>
#include <targeting/common/utilFilter.H>
Expand All @@ -54,11 +52,13 @@
#include <fapi2/plat_hwp_invoker.H>
#include <fapi2/target.H>

#include <p9_cpu_special_wakeup.H>
#include <p9_query_core_access_state.H>
#include <p9_query_cache_access_state.H>
#include <p9_hcd_core_stopclocks.H>
#include <p9_hcd_cache_stopclocks.H>
#include <p9_pm_ocb_init.H>
#include <p9_pm_ocb_indir_setup_linear.H>
#include <p9_pm_ocb_indir_access.H>
#include <p9_hcd_common.H>
#include <p9_quad_power_off.H>

Expand All @@ -72,22 +72,17 @@ namespace ISTEP_06

#ifdef CONFIG_PRINT_SYSTEM_INFO

//Loop through list of targets and print out HUID and other key attributes if
//the target has it
//Loop through list of targets and print out HUID and other key attributes if the target has it
void print_target_list(TARGETING::TargetHandleList i_targetList)
{

for(auto & l_targ : i_targetList)
{
char * l_targetString =
l_targ->getAttr<TARGETING::ATTR_PHYS_PATH>().toString();

TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "%s", l_targetString);

free(l_targetString);
for(auto & l_targ : i_targetList)
{
TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "%s", l_targ->getAttr<TARGETING::ATTR_PHYS_PATH>().toString());

//Every target has a HUID so it is safe to assume this will return okay
//from getAttr
//Every target has a HUID so it is safe to assume this will return okay from getAttr
uint32_t l_huid = get_huid(l_targ );

//if output says DEAD then the attribute is not defined
Expand All @@ -97,8 +92,8 @@ void print_target_list(TARGETING::TargetHandleList i_targetList)
uint32_t l_fapi_pos = 0xDEAD;
uint32_t l_chip_unit = 0xDEAD;

//The rest of these attributes may or may not exist on the target, so
//only add them to the string if the attribute exists
//The rest of these attributes may or may not exist on the target, so only add them to the
//string if the attribute exists
TARGETING::AttributeTraits<TARGETING::ATTR_HWAS_STATE>::Type hwasState;
if(l_targ->tryGetAttr<TARGETING::ATTR_HWAS_STATE>(hwasState))
{
Expand Down Expand Up @@ -169,76 +164,23 @@ void print_system_info(void)
}
#endif

/**
* @brief Walk through the cores and ensure special wakeup is disabled
* from all srcs.
*
* @param[in/out] ISTEP_ERROR::IStepError
* Pass in the istep error so we can add errors to it
*
* @return bool
* True if no errors were found
* False if at least 1 error was found
*/
bool deassertSpecialWakeupOnCores(ISTEP_ERROR::IStepError & io_istepError)
{
errlHndl_t l_err = nullptr;
bool l_success = true;
// First disable special wakeup of all types for all cores
TARGETING::TargetHandleList l_coreTargetList;
TARGETING::getAllChiplets(l_coreTargetList, TARGETING::TYPE_CORE, true);

for(const auto & l_core : l_coreTargetList)
{
for(uint8_t l_src = 0; l_src < p9specialWakeup::SPW_ALL; l_src++)
{
FAPI_INVOKE_HWP(l_err, p9_cpu_special_wakeup_core, l_core,
p9specialWakeup::SPCWKUP_DISABLE,
p9specialWakeup::PROC_SPCWKUP_ENTITY(l_src));
if ( l_err )
{
TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
"ERROR : returned from p9_cpu_special_wakeup_core for core 0x%x for src 0x%x", TARGETING::get_huid(l_core), l_src );
l_success = false;
break;
}
else
{
TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
"disabled special wakeup for core 0x%x for src 0x%x", TARGETING::get_huid(l_core), l_src );
}
}
if(l_err)
{
// capture the target data in the elog
ERRORLOG::ErrlUserDetailsTarget(l_core).addToLog( l_err );
// add the err to the istep error
io_istepError.addErrorDetails(l_err);
//commit the error log (this will delete the err)
errlCommit(l_err, ISTEP_COMP_ID);
}
}

return l_success;
}

/**
* @brief loop through slave quads, make sure clocks are stopped
* (core and cache) and power them down
*
* @return errlHndl_t
*/
//loop through slave quads, make sure clocks are stopped (core and cache) and power them down
errlHndl_t powerDownSlaveQuads()
{
TARGETING::Target* l_sys_target = nullptr;
TARGETING::targetService().getTopLevelTarget(l_sys_target);
errlHndl_t l_err = nullptr;
errlHndl_t l_err = NULL;
const uint8_t SIZE_OF_RING_DATA_PER_EQ = 0x40;
const uint8_t NUM_ENTRIES_IN_RING_DATA = 0x8;
const uint32_t OCC_SRAM_RING_STASH_BAR = 0xFFF3FC00;
bool l_isMasterEq = false;
uint64_t l_ringData[8] = {0,0,0,0,0,0,0,0};
uint32_t l_ocb_buff_length_act = 0;
uint8_t l_quad_pos;
uint32_t l_ringStashAddr;
TARGETING::TargetHandleList l_eqTargetList;
getAllChiplets(l_eqTargetList, TARGETING::TYPE_EQ, true);
uint64_t EX_0_CME_SCOM_SICR_SCOM1 = 0x1001203E;
uint64_t CME_SCOM_SICR_PM_EXIT_C0_MASK = 0x0800000000000000;
size_t MASK_SIZE = sizeof(CME_SCOM_SICR_PM_EXIT_C0_MASK);


//Need to know who master is so we can skip them
uint8_t l_masterCoreId = TARGETING::getMasterCore()->getAttr<TARGETING::ATTR_CHIP_UNIT>();
Expand All @@ -248,6 +190,8 @@ errlHndl_t powerDownSlaveQuads()
{
l_isMasterEq = false;
fapi2::Target <fapi2::TARGET_TYPE_EQ> l_fapi_eq_target (l_eq_target);
fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_chip =
l_fapi_eq_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();
TARGETING::TargetHandleList l_coreTargetList;
TARGETING::getChildChiplets( l_coreTargetList,
l_eq_target,
Expand All @@ -266,23 +210,6 @@ errlHndl_t powerDownSlaveQuads()
//If this is the master quad, we have already power cycled so we dont need this
if(l_isMasterEq)
{
//TODO RTC:171340 Need to clear PM_EXIT bit in EX_0_CME_SCOM_SICR_SCOM1 reg for MPIPL
//deassert pm exit flag on master core (both ex targs to be safe)
TARGETING::TargetHandleList l_exChildren;
TARGETING::getChildChiplets( l_exChildren,
l_eq_target,
TARGETING::TYPE_EX,
true);

for(const auto & l_ex_child : l_exChildren)
{
// Clear bit 4 of CME_SCOM_SICR which sets PM_EXIT
l_err = deviceWrite(l_ex_child,
&CME_SCOM_SICR_PM_EXIT_C0_MASK,
MASK_SIZE,
DEVICE_SCOM_ADDRESS(EX_0_CME_SCOM_SICR_SCOM1)); //0x1001203E
}
//continue to next EQ
TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
"Found master, jumping to next EQ");
continue;
Expand Down Expand Up @@ -389,14 +316,41 @@ errlHndl_t powerDownSlaveQuads()
//Power down slave quad
FAPI_INVOKE_HWP(l_err,
p9_quad_power_off,
l_fapi_eq_target);
l_fapi_eq_target,
l_ringData);
if(l_err)
{
TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
"Error powering off EQ %d", l_eq_target->getAttr<TARGETING::ATTR_CHIP_UNIT>());
//Break from do-while
break;
}

FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_fapi_eq_target, l_quad_pos);

l_ringStashAddr = OCC_SRAM_RING_STASH_BAR + (SIZE_OF_RING_DATA_PER_EQ * l_quad_pos);

// Setup use OCB channel 0 for placing ring data in SRAM
FAPI_INVOKE_HWP(l_err, p9_pm_ocb_indir_setup_linear, l_chip,
p9ocb::OCB_CHAN0,
p9ocb::OCB_TYPE_LINSTR,
l_ringStashAddr); // Bar

FAPI_INVOKE_HWP(l_err, p9_pm_ocb_indir_access,
l_chip,
p9ocb::OCB_CHAN0,
p9ocb::OCB_PUT,
NUM_ENTRIES_IN_RING_DATA,
true,
l_ringStashAddr,
l_ocb_buff_length_act,
l_ringData);

for(int x = 0; x < NUM_ENTRIES_IN_RING_DATA; x++)
{
FAPI_DBG("Wrote %lx to OCC SRAM addr: 0x%lx", l_ringData[x], l_ringStashAddr + (x * 8));
}

}while(0);

if(l_err)
Expand All @@ -416,11 +370,11 @@ void* host_discover_targets( void *io_pArgs )
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
"host_discover_targets entry" );

errlHndl_t l_err = nullptr;
errlHndl_t l_err = NULL;
ISTEP_ERROR::IStepError l_stepError;

// Check whether we're in MPIPL mode
TARGETING::Target* l_pTopLevel = nullptr;
TARGETING::Target* l_pTopLevel = NULL;
TARGETING::targetService().getTopLevelTarget( l_pTopLevel );
assert(l_pTopLevel, "host_discover_targets: no TopLevelTarget");

Expand All @@ -431,12 +385,9 @@ void* host_discover_targets( void *io_pArgs )
"information has already been loaded from memory"
"when the targeting service started");

//Make sure that all special wakeups are disabled
if(deassertSpecialWakeupOnCores(l_stepError))
{
//Need to power down the slave quads
l_err = powerDownSlaveQuads();
}
//Need to power down the slave quads
l_err = powerDownSlaveQuads();

}
else
{
Expand All @@ -450,7 +401,7 @@ void* host_discover_targets( void *io_pArgs )
// Now that all targets have completed presence detect and vpd access,
// invalidate PNOR::CENTAUR_VPD sections where all the targets sharing a
// VPD_REC_NUM are invalid.
if (nullptr == l_err) //discoverTargets worked
if (NULL == l_err) //discoverTargets worked
{
l_err = VPD::validateSharedPnorCache();
}
Expand Down

0 comments on commit ae07790

Please sign in to comment.