Skip to content

Commit

Permalink
update p9_l2_flush HWP to build against current EKB
Browse files Browse the repository at this point in the history
Change-Id: Ie1d7b341e96b1b7aa3fa9b126ba2c4d5f8e65006
Original-Change-Id: Ib72f244c1a8a9033acc59d6c6cc36fe0fa519373
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/20991
Tested-by: Jenkins Server
Reviewed-by: STEPHEN M. CPREK <smcprek@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/47174
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
  • Loading branch information
jjmcgill authored and dcrowell77 committed Oct 5, 2017
1 parent 4b9c63c commit 2df39d4
Show file tree
Hide file tree
Showing 2 changed files with 428 additions and 0 deletions.
305 changes: 305 additions & 0 deletions src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.C
@@ -0,0 +1,305 @@
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.C $ */
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2015,2017 */
/* [+] 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 */
///
/// @file p9_l2_flush.H
/// @brief Flush the P9 L2 cache (FAPI)
///
/// *HWP HWP Owner : Benjamin Gass <bgass@us.ibm.com>
/// *HWP FW Owner : Bilicon Patil <bilpatil@in.ibm.com>
/// *HWP Team : Quad
/// *HWP Consumed by : FSP
/// *HWP Level : 2
///

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <p9_quad_scom_addresses.H>
#include <p9_l2_flush.H>

//------------------------------------------------------------------------------
// Constant definitions
//------------------------------------------------------------------------------

// L2 Purge Engine Command Register bit/field definitions
enum
{
PURGE_CMD_TRIGGER_BIT = 0,
PURGE_CMD_REG_BUSY = 9,
PURGE_CMD_PRGSM_BUSY_ON_THIS_BIT = 10,
PURGE_CMD_PRGSM_BUSY_BIT = 11,
PURGE_CMD_ERR_BIT = 29,
PURGE_CMD_TYPE_BIT = 1,
PURGE_CMD_MEM_BIT = 17,
PURGE_CMD_BANK_BIT = 28,
PURGE_CMD_CGC_BIT = 20
};

// L2 Purge Engine Command Register bit/field Lengths
enum
{
PURGE_CMD_TYPE_BIT_LENGTH = 4,
PURGE_CMD_MEM_BIT_LENGTH = 3,
PURGE_CMD_BANK_BIT_LENGTH = 1,
PURGE_CMD_CGC_BIT_LENGTH = 8
};

// polling constants
enum
{
P9_L2_FLUSH_HW_NS_DELAY = 10000, // unit is nano seconds
P9_L2_FLUSH_SIM_CYCLE_DELAY = 12000, // unit is cycles
P9_L2_FLUSH_MAX_POLLS = 200 // unit is cycles
};

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

//------------------------------------------------------------------------------
///
/// @brief l2_flush: Utility subroutine to start flush and check the status
/// @param[in] i_target Ex target
/// @param[in] i_purgeData Structure having values for MEM, CGC, BANK
/// passed by the user
/// @return FAPI2_RC_SUCCESS if purge operation was started,
/// RC_P9_L2_FLUSH_PURGE_REQ_OUTSTANDING if a prior purge
/// operation has not yet completed
/// else FAPI getscom/putscom return code for failing operation
//------------------------------------------------------------------------------
fapi2::ReturnCode l2_flush(const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target,
const p9core::purgeData_t& i_purgeData);

//------------------------------------------------------------------------------
///
/// @brief l2_flush_start: Utility subroutine to initiate L2 cache flush
/// via purge engine
/// @param[in] i_target Ex target
/// @param[in] i_regAddr The scom address to use
/// @param[in] i_purgeData Structure having values for MEM, CGC, BANK
/// passed by the user
/// @return FAPI2_RC_SUCCESS if purge operation was started,
/// RC_P9_L2_FLUSH_PURGE_REQ_OUTSTANDING if a prior purge
/// operation has not yet completed
/// else FAPI getscom/putscom return code for failing operation
//------------------------------------------------------------------------------
fapi2::ReturnCode l2_flush_start(
const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target,
const uint32_t i_regAddr,
const p9core::purgeData_t& i_purgeData)
{
fapi2::buffer<uint64_t> l_cmdReg;
fapi2::buffer<uint64_t> l_purgeCmd;
char l_targetStr[fapi2::MAX_ECMD_STRING_LEN];

FAPI_INF("l2_flush_start: Enter");

// ensure that purge engine is idle before starting flush
// poll Purge Engine status
FAPI_DBG("Reading L2 Purge Engine Command Register to check status");
FAPI_TRY(fapi2::getScom(i_target, i_regAddr, l_cmdReg));

// check to see if this reg is idle and ready to accept a new command
fapi2::toString(i_target, l_targetStr, fapi2::MAX_ECMD_STRING_LEN);
FAPI_ASSERT(!l_cmdReg.getBit<PURGE_CMD_REG_BUSY>(),
fapi2::P9_L2_FLUSH_PURGE_REQ_OUTSTANDING()
.set_TARGET(i_target)
.set_CMD_REG(l_cmdReg)
.set_CMD_REG_ADDR(i_regAddr),
"Previous purge request has not completed for target %s",
l_targetStr);

// write PURGE_CMD_TRIGGER bit in Purge Engine Command Register
// ensure PURGE_CMD_TYPE/MEM/CGC/BANK are clear to specify flush
// of entire cache
FAPI_DBG("Write L2 Purge Engine Command Register to initiate cache flush");
l_purgeCmd.insert<PURGE_CMD_TYPE_BIT,
PURGE_CMD_TYPE_BIT_LENGTH>(i_purgeData.iv_cmdType);

l_purgeCmd.insert<PURGE_CMD_MEM_BIT,
PURGE_CMD_MEM_BIT_LENGTH>(i_purgeData.iv_cmdMem);

l_purgeCmd.insert<PURGE_CMD_BANK_BIT,
PURGE_CMD_BANK_BIT_LENGTH>(i_purgeData.iv_cmdBank);

l_purgeCmd.insert<PURGE_CMD_CGC_BIT,
PURGE_CMD_CGC_BIT_LENGTH>(i_purgeData.iv_cmdCGC);

l_purgeCmd.setBit<PURGE_CMD_TRIGGER_BIT>();

FAPI_TRY(fapi2::putScom(i_target, i_regAddr, l_purgeCmd));

fapi_try_exit:
return fapi2::current_err;
}


//------------------------------------------------------------------------------
///
/// @brief l2_flush_check_status: Utility subroutine to poll L2 purge
/// engine status, looking for clean idle
/// state
/// @param[in] i_target EX chiplet target
/// @param[in] i_regAddr Purge engine register SCOM address
/// @return FAPI2_RC_SUCCESS if engine status returns as idle (with no errors)
/// before maximum number of polls has been reached
/// RC_P9_L2_FLUSH_CMD_ERROR
/// if purge command error reported,
/// RC_P9_L2_FLUSH_CMD_TIMEOUT
/// if purge operation did not complete prior to polling limit,
/// else FAPI getscom/putscom return code for failing operation
///
//------------------------------------------------------------------------------
fapi2::ReturnCode l2_flush_check_status(
const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target,
const uint32_t i_regAddr)
{
fapi2::buffer<uint64_t> l_cmdReg;
uint32_t l_polls = 1;

FAPI_INF("l2_flush_check_status: Enter");

while(1)
{
// poll Purge Engine status
FAPI_DBG("Reading L2 Purge Engine Command Register to check status");
FAPI_TRY(fapi2::getScom(i_target, i_regAddr, l_cmdReg));

// check state of PURGE_CMD_ERR
FAPI_ASSERT(!l_cmdReg.getBit<PURGE_CMD_ERR_BIT>(),
fapi2::P9_L2_FLUSH_CMD_ERROR()
.set_TARGET(i_target)
.set_CMD_REG(l_cmdReg)
.set_CMD_REG_ADDR(i_regAddr),
"Purge failed. PURGE_CMD_ERR_BIT set");

// check to see if this reg is idle and ready to accept a new command
if (!l_cmdReg.getBit<PURGE_CMD_REG_BUSY>())
{
FAPI_DBG("Purge engine idle");
break;
}

// engine busy, dump status
FAPI_DBG("Purge engine busy (reg_busy = %d, busy_on_this = %d,"
" sm_busy = %d)",
l_cmdReg.getBit<PURGE_CMD_REG_BUSY>(),
l_cmdReg.getBit<PURGE_CMD_PRGSM_BUSY_ON_THIS_BIT>(),
l_cmdReg.getBit<PURGE_CMD_PRGSM_BUSY_BIT>());

// check if loop count has expired
FAPI_ASSERT((l_polls < P9_L2_FLUSH_MAX_POLLS),
fapi2::P9_L2_FLUSH_CMD_TIMEOUT()
.set_TARGET(i_target)
.set_CMD_REG(l_cmdReg)
.set_CMD_REG_ADDR(i_regAddr)
.set_NUMBER_OF_ATTEMPTS(l_polls),
"Purge engine still busy after %d loops", l_polls);

// l_polls left, delay prior to next poll
FAPI_DBG("%d loops done, delaying before next poll", l_polls);

FAPI_TRY(fapi2::delay(P9_L2_FLUSH_HW_NS_DELAY,
P9_L2_FLUSH_SIM_CYCLE_DELAY),
"fapi delay Error");

l_polls++;
}

fapi_try_exit:
return fapi2::current_err;
}

//------------------------------------------------------------------------------
// Hardware Procedure
//------------------------------------------------------------------------------
fapi2::ReturnCode l2_flush(const fapi2::Target<fapi2::TARGET_TYPE_EX>& i_target,
const p9core::purgeData_t& i_purgeData)
{
FAPI_DBG("i_purgeData.iv_cmdType: 0x%x", i_purgeData.iv_cmdType);
FAPI_DBG("i_purgeData.iv_cmdMem : 0x%x", i_purgeData.iv_cmdMem);
FAPI_DBG("i_purgeData.iv_cmdBank: 0x%x", i_purgeData.iv_cmdBank);
FAPI_DBG("i_purgeData.iv_cmdCGC : 0x%x", i_purgeData.iv_cmdCGC);

uint32_t l_regAddr = 0;
uint8_t l_platform = 0;

//Get the scom address to use for this platform
const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_EXECUTION_PLATFORM,
FAPI_SYSTEM,
l_platform),
"Error from FAPI_ATTR_GET for attribute ATTR_EXECUTION_PLATFORM");

if( l_platform == fapi2::ENUM_ATTR_EXECUTION_PLATFORM_FSP )
{
l_regAddr = EX_PRD_PURGE_CMD_REG;
}
else
{
FAPI_ASSERT(false,
fapi2::P9_L2_FLUSH_UNKNOWN_PLATFORM()
.set_TARGET(i_target)
.set_PLATFORM(l_platform),
"Unsupported l_platform %d", l_platform);
}

// initiate flush
FAPI_TRY(l2_flush_start(i_target, l_regAddr, i_purgeData));

// check that flush completes and the purge engine is idle
// before exiting
FAPI_TRY(l2_flush_check_status(i_target, l_regAddr));

fapi_try_exit:
FAPI_INF("l2_flush, Ex: Exit");
return fapi2::current_err;
}

fapi2::ReturnCode p9_l2_flush(const fapi2::Target < fapi2::TARGET_TYPE_CORE
| fapi2::TARGET_TYPE_EX >
&i_target,
const p9core::purgeData_t& i_purgeData)
{
FAPI_IMP("p9_l2_flush, Core|Ex 0x%lx: Enter", i_target.get());

fapi2::Target<fapi2::TARGET_TYPE_EX> l_exTarget;

if(i_target.getType() & fapi2::TARGET_TYPE_CORE)
{
l_exTarget = i_target.getParent<fapi2::TARGET_TYPE_EX>();
}
else
{
// We got an Ex target.
l_exTarget = i_target.get();
}

FAPI_TRY(l2_flush(l_exTarget, i_purgeData));

fapi_try_exit:
FAPI_IMP("p9_l2_flush, Core: Exit");
return fapi2::current_err;
}

0 comments on commit 2df39d4

Please sign in to comment.