diff options
Diffstat (limited to 'src/usr/occ/p8_pmc_force_vsafe.C')
-rw-r--r-- | src/usr/occ/p8_pmc_force_vsafe.C | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/src/usr/occ/p8_pmc_force_vsafe.C b/src/usr/occ/p8_pmc_force_vsafe.C new file mode 100644 index 000000000..3bd59b986 --- /dev/null +++ b/src/usr/occ/p8_pmc_force_vsafe.C @@ -0,0 +1,517 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/occ/p8_pmc_force_vsafe.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,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 */ +// $Id: p8_pmc_force_vsafe.C,v 1.18 2014/04/24 16:54:18 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/p8_pmc_force_vsafe.C,v $ +//------------------------------------------------------------------------------ +// *! (C) Copyright International Business Machines Corp. 2011 +// *! All Rights Reserved -- Property of IBM +// *! *** *** +//------------------------------------------------------------------------------ +// *! OWNER NAME: Joe Procwriter Email: asmartpersion@xx.ibm.com +// *! +// *! General Description: Forces the PMC to VSAFE mode +// *! +// *! The purpose of this procedure is to ...... +// *! +// *! High-level procedure flow: +// *! o Do thing 1 +// *! o Do thing 2 +// *! o Do thing 3 +// *! o Check if all went well +// *! o If so celebrate +// *! o Else write logs, set bad return code +// *! +// *! Procedure Prereq: +// *! o System clocks are running +// *! +// buildfapiprcd -e ../../xml/error_info/p8_force_vsafe_errors.xml,../../xml/error_info/p8_pstate_registers.xml p8_pmc_force_vsafe.C + +// ----------------------------------------------------------------------------- +// Write a voltage value into +// PVSAFE - PMC_PARAMETER_REG1 +// Actually, this value will be been written outside this procedure by the OCC pstate installation routine after the p8_build_pstate runs to build +// the Pstate superstructure. We had identified a HWP ATTR (ATTR_PM_PVSAFE_PSTATE) to be used by p8_pmc_init to set this up originally but we're +// going away from that approach so that we have all things about Pstates being done in one place (the OCC pstate installation routine). +// So, this step should not exist in the p8_pmc_force_vsafe procedure; rather, you should write a value into the hardware with a script that +// represents what the OCC pstate install routine would have done + +// ------------------ +// | Procedure Starts | +// ------------------ +// | +// | +// V +// Write into PMC_OCC_HEARTBEAT_REG +// PMC_OCC_HEARTBEAT_TIME - Write the field to 0 to cause an immediate heartbeat loss. +// PMC_OCC_HEARTBEAT_EN - this bit needs to be 1 to acually cause the 0 time value to trigger the heartbeat loss. +// | +// | +// V +// POLL PMC_STATUS_REG (8) +// VOLT_CHG_ONGOING (bit 8) Yes... this bit needs to be 0 to indicate that the voltage controller is at its target. + +// 1.3V Turbo to 0.8V (most of the supported range) in 25mV steps (the eVRM step size with iVRMs enabled) is 20 steps which, at 12.5mV/5us rate +// (a modest time), yields 8us. Given this an error case, we need a conservative time. So let's set the timeout at 100us for the lab. +// To test the timeout, clear PMC.PMC_MODE_REG (3) (with a script) so that the PMC won't respond. + + + + +// Check that the other bits in PMC_STATUS_REG do not indicate errors (eg they should be all zeros). If any are 1 +// | ^ +// | | +// V | +// timeout ------ + +// ---------------------------------------------------------------------- +// Flowchart Ends +// ---------------------------------------------------------------------- + +// ---------------------------------------------------------------------- +// Includes +// ---------------------------------------------------------------------- +#include <fapi.H> +#include "p8_scom_addresses.H" + +extern "C" { + +using namespace fapi; + +// ---------------------------------------------------------------------- +// Constant definitions +// ---------------------------------------------------------------------- + + +// ---------------------------------------------------------------------- +// Global variables +// ---------------------------------------------------------------------- + + +// ---------------------------------------------------------------------- +// Function prototypes +// ---------------------------------------------------------------------- + + +// ---------------------------------------------------------------------- +// Function definitions +// ---------------------------------------------------------------------- + + +// function: xxx +/// \param[in] i_target Chip target +// returns: ECMD_SUCCESS if something good happens, +// BAD_RETURN_CODE otherwise +fapi::ReturnCode +p8_pmc_force_vsafe( const fapi::Target& i_target, + const fapi::Target& i_dcm_target) +{ + fapi::ReturnCode rc; + ecmdDataBufferBase data(64); + ecmdDataBufferBase pmcstatusreg(64); + uint32_t e_rc = 0; + + // maximum number of status poll attempts to make before giving up + const uint32_t MAX_POLL_ATTEMPTS = 0x200; + + uint32_t count = 0; + uint16_t pvsafe = 0; + bool l_set; + uint16_t pstate_target = 0; + uint16_t pstate_step_target = 0; + uint16_t pstate_actual = 0; + uint8_t DONE_FLAG = 0; + uint8_t pmc_error = 0; + uint8_t intchp_error = 0; + uint8_t any_error = 0; + uint8_t any_ongoing = 0; + uint8_t dummy = 0; + + FAPI_INF("p8_pmc_force_vsafe start to primary target %s", + i_target.toEcmdString()); + + do + { + // ****************************************************************** + // - PMC_MODE_REG checking + // ****************************************************************** + rc = fapiGetScom(i_target, PMC_MODE_REG_0x00062000, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_MODE_REG_0x00062000) failed."); + break; + } + + + if ( (data.isBitClear(0) && data.isBitClear(1) )) + { + FAPI_INF("PMC is not in HARDWARE or FIRMWARE AUCTION MODE so hardware mechanism cannot be used."); + break; + } + + if ( ( data.isBitClear(3) )) + { + FAPI_ERR("PMC is disabled for Voltage changes"); + const fapi::Target & CHIP = i_target; + const uint64_t & PMCMODE = data.getDoubleWord(0); + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_VOLTAGE_CHANGE_MODE_ERR); + break; + } + + if ( ( !data.isBitClear(5) )) + { + FAPI_ERR("PMC is disabled PMC_MASTER_SEQUENCER"); + const fapi::Target & CHIP = i_target; + const uint64_t & PMCMODE = data.getDoubleWord(0); + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_MST_SEQUENCER_STATE_ERR); + break; + } + + // **************************************************************************** + // - PMC_STATE_MONITOR_AND_CTRL_REG PMC_PARAMETER_REG1 before the psafe + // **************************************************************************** + + rc = fapiGetScom(i_target, PMC_PARAMETER_REG1_0x00062006, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_PARAMETER_REG1_0x00062006) failed."); + break; + } + + e_rc |= data.extractToRight( &pvsafe,22,8); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + + rc = fapiGetScom(i_target, PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002) failed."); + break; + } + + e_rc |= data.extractToRight( &pstate_target,0,8); + e_rc |= data.extractToRight( &pstate_step_target,8,8); + e_rc |= data.extractToRight( &pstate_actual,16,8); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + + FAPI_INF(" voltage values before the hearbeat loss " ); + FAPI_INF(" pvsafe => %x , ptarget => %x , pstarget => %x ,pactual => %x " , pvsafe , pstate_target ,pstate_step_target , pstate_actual); + + // ****************************************************************** + // - SEE PMC_STATUS_REG if debug_mode ==1 + // ****************************************************************** + + rc = fapiGetScom(i_target, PMC_STATUS_REG_0x00062009, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_STATUS_REG_0x00062009) failed."); + break; + } + FAPI_DBG(" debug_mode : status_b4_heartbeat_loss => 0x%16llx", data.getDoubleWord(0)); + + l_set = data.isBitSet(0); + FAPI_DBG(" pstate_processing_is_susp => %x ", l_set ) ; + l_set = data.isBitSet(1); + FAPI_DBG(" gpsa_bdcst_error => %x ", l_set ); + + e_rc = data.extractToRight( &dummy,2,3); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + FAPI_DBG(" gpsa_bdcst_resp_info => %x ", dummy ); + l_set = data.isBitSet(5); + FAPI_DBG(" gpsa_vchg_error => %x ", l_set ); + l_set = data.isBitSet(6); + FAPI_DBG(" gpsa_timeout_error => %x ", l_set ); + l_set = data.isBitSet(7); + FAPI_DBG(" gpsa_chg_ongoing => %x ", l_set ); + l_set = data.isBitSet(8); + FAPI_DBG(" volt_chg_ongoing => %x ", l_set ); + l_set = data.isBitSet(9); + FAPI_DBG(" brd_cst_ongoing => %x ", l_set ); + l_set = data.isBitSet(10); + FAPI_DBG(" gpsa_table_error => %x ", l_set ); + l_set = data.isBitSet(11); + FAPI_DBG(" pstate_interchip_error => %x ", l_set ); + l_set = data.isBitSet(12); + FAPI_DBG(" istate_processing_is_susp => %x ", l_set ); + + + // ****************************************************************** + // - PMC_OCC_HEARTBEAT_REG + // ****************************************************************** + + FAPI_INF("Forcing PMC Heartbeat loss "); + + e_rc |= data.flushTo0(); + e_rc |= data.setBit(16); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + + rc = fapiPutScom(i_target, PMC_OCC_HEARTBEAT_REG_0x00062066, data ); + if (rc) + { + FAPI_ERR("fapiPutScom(PMC_OCC_HEARTBEAT_REG_0x00062066) failed."); + break; + } + + // delay to reduce number of polling loops + rc = fapiDelay(1000, 1000); + + // ****************************************************************** + // POLL for PMC_STATUS_REG --> BIT_8 to go to 0 or any errors + // ****************************************************************** + FAPI_DBG("Start polling for ongoing to go low ... "); + // Loop only if count is less thean poll attempts and DONE_FLAG = 0 and no error + for(count=0; ((count<=MAX_POLL_ATTEMPTS) && (DONE_FLAG == 0) && (any_error == 0)); count++) + { + rc = fapiGetScom(i_target, PMC_STATUS_REG_0x00062009, pmcstatusreg ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_STATUS_REG_0x00062009) failed."); + break; + } + + FAPI_DBG(" PMC Status poll => 0x%16llx", pmcstatusreg.getDoubleWord(0)); + + pmc_error = ( pmcstatusreg.isBitSet(1) || // GPSA_BDCST_ERROR + pmcstatusreg.isBitSet(5) || // GPSA_VCHG_ERROR + pmcstatusreg.isBitSet(6) || // GPSA_TIMEOUT_ERROR + pmcstatusreg.isBitSet(10) || // GPS_TABLE_ERROR + pmcstatusreg.isBitSet(12) ); // ISTATE_PROCESSING_IS_SUSPENDED + + any_ongoing = ( pmcstatusreg.isBitSet(7) || // GPSA_CHG_ONGOING + pmcstatusreg.isBitSet(8) || // VOLT_CHG_ONGOING + pmcstatusreg.isBitSet(9) ); // BRD_CST_ONGOING + + + // If there is an interchip error, determine if it is expected or not + // Unexpected: gpsa_timeout or ECC UE error + if (pmcstatusreg.isBitSet(11)) // PSTATE_INTERCHIP_ERROR + { + rc = fapiGetScom(i_target, PMC_INTCHP_STATUS_REG_0x00062013, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_STATUS_REG_0x00062009) failed."); + break; + } + + intchp_error = (data.isBitSet(18) || // GPSA_TIMEOUT_ERROR + data.isBitSet(19) ); // ECC UE ERROR + } + + any_error = (pmc_error || intchp_error); + + // log status if voltage change has any error + // Due to SW258130 + // This block only dumps any detected hw error status + // without taking out an error log and stop the reset flow. + // Since this procedure is only used by p8_pm_prep_for_reset + // we will and should be able to recover from such hardware errors + // by going through occ reset flow, thus no FAPI error logged. + // Also since if hardware error occurs, there is no need to check + // for pstate ongoing or pstate equals to pvsafe due to possible + // hardware stuck; therefore, this if/else logic remains. + if (any_error) + { + // dump individual error status + FAPI_INF(" PMC_STATUS_REG upon Error"); + if (pmcstatusreg.isBitSet(0)) + FAPI_INF(" pstate_processing_is_susp active"); + if (pmcstatusreg.isBitSet(1)) + FAPI_INF(" gpsa_bdcst_error active"); + + e_rc = pmcstatusreg.extractToRight( &dummy,2,3); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + if (dummy) + FAPI_INF(" gpsa_bdcst_resp_info is non-zero => %x ", dummy ); + + if (pmcstatusreg.isBitSet(5)) + FAPI_INF(" gpsa_vchg_error active"); + if (pmcstatusreg.isBitSet(6)) + FAPI_INF(" gpsa_timeout_error active"); + if (pmcstatusreg.isBitSet(7)) + FAPI_INF(" gpsa_chg_ongoing active"); + if (pmcstatusreg.isBitSet(8)) + FAPI_INF(" volt_chg_ongoing active"); + if (pmcstatusreg.isBitSet(9)) + FAPI_INF(" brd_cst_ongoing active"); + if (pmcstatusreg.isBitSet(10)) + FAPI_INF(" gpsa_table_error active"); + if (pmcstatusreg.isBitSet(11)) + FAPI_INF(" pstate_interchip_error active"); + if (pmcstatusreg.isBitSet(12)) + FAPI_INF(" istate_processing_is_susp active"); + + FAPI_INF("Status dumpped with PMC on-going deassertion during safe voltage movement, now continue on reset"); + } // end of status log if + else if (any_ongoing == 0) + { + // Voltage change done (not on-going) and not errors + FAPI_INF("PMC completed performing safe mode transition"); + l_set = pmcstatusreg.isBitSet(0); + if (l_set) FAPI_INF(" pstate_processing_is_susp => %x ", l_set ) ; + + l_set = pmcstatusreg.isBitSet(1); + if (l_set) FAPI_INF(" gpsa_bdcst_error => %x ", l_set ); + + e_rc = pmcstatusreg.extractToRight( &dummy,2,3); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + if (l_set) FAPI_INF(" gpsa_bdcst_resp_info => %x ", dummy ); + + l_set = pmcstatusreg.isBitSet(5); + if (l_set) FAPI_INF(" gpsa_vchg_error => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(6); + if (l_set) FAPI_INF(" gpsa_timeout_error => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(7); + if (l_set) FAPI_INF(" gpsa_chg_ongoing => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(8); + if (l_set) FAPI_INF(" volt_chg_ongoing => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(9); + if (l_set) FAPI_INF(" brd_cst_ongoing => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(10); + if (l_set) FAPI_INF(" gpsa_table_error => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(11); + if (l_set) FAPI_INF(" pstate_interchip_error => %x ", l_set ); + + l_set = pmcstatusreg.isBitSet(12); + if (l_set) FAPI_INF(" istate_processing_is_susp => %x ", l_set ); + + + rc = fapiGetScom(i_target, PMC_PARAMETER_REG1_0x00062006, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_PARAMETER_REG1_0x00062006) failed."); + break; + } + + e_rc = data.extractToRight( &pvsafe,22,8); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + + rc = fapiGetScom(i_target, PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002, data ); + if (rc) + { + FAPI_ERR("fapiGetScom(PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002) failed."); + break; + } + + e_rc |= data.extractToRight( &pstate_target,0,8); + e_rc |= data.extractToRight( &pstate_step_target,8,8); + e_rc |= data.extractToRight( &pstate_actual,16,8); + if (e_rc) + { + rc.setEcmdError(e_rc); + break; + } + FAPI_INF(" pvsafe => %x , ptarget => %x , pstarget => %x ,pactual => %x " , pvsafe , pstate_target ,pstate_step_target , pstate_actual); + + // Check that PVSAFE Pstate (in PMC Parameter Reg1) is the value + // in the voltage stepper in the following fields of + // PMC_STATE_MONITOR_AND_CRTL_REG + // 0:7 - Global Pstate Target + // 8:15 - Global Pstate Step Target + // 16:23 - Global Pstate Actual + // if the above do not match, post an error + if (pstate_target != pvsafe || pstate_step_target != pvsafe || pstate_actual != pvsafe ) + { + FAPI_ERR("Pstate monitor and control register targets did not match"); + const fapi::Target & THISCHIP = i_target; + const fapi::Target & DCMCHIP = i_dcm_target; + const uint64_t & PSTATETARGET = (uint64_t)pstate_target; + const uint64_t & PSTATESTEPTARGET = (uint64_t)pstate_step_target; + const uint64_t & PSTATEACTUAL = (uint64_t)pstate_actual; + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_PSTATE_MONITOR_ERR); + break; + } + DONE_FLAG = 1; + } + else // voltage change is ongoing so wait and then poll again + { + + // wait for 1 millisecond in hardware + rc = fapiDelay(1000*1000, 20000000); + if (rc) + { + FAPI_ERR("fapi delay ends up with error"); + break; + } + } + } // For loop + // Inner loop error check + if (!rc.ok()) + { + break; + } + + // Check if the above loop timed out + if (count>=MAX_POLL_ATTEMPTS) + { + FAPI_ERR("Timed out wait for voltage change on-going to drop"); + const uint64_t & PSTATETARGET = (uint64_t)pstate_target; + const uint64_t & PSTATESTEPTARGET = (uint64_t)pstate_step_target; + const uint64_t & PSTATEACTUAL = (uint64_t)pstate_actual; + const fapi::Target & THISCHIP = i_target; + const fapi::Target & DCMCHIP = i_dcm_target; + FAPI_SET_HWP_ERROR(rc, RC_PROCPM_VLT_TIMEOUT); + break; + } + + } while(0); + + FAPI_INF("p8_pmc_force_vsafe end ...."); + + return rc ; +} // Procedure + +} //end extern C |