summaryrefslogtreecommitdiffstats
path: root/src/usr/occ/p8_pmc_force_vsafe.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/occ/p8_pmc_force_vsafe.C')
-rw-r--r--src/usr/occ/p8_pmc_force_vsafe.C517
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
OpenPOWER on IntegriCloud