diff options
author | Amit Kumar <akumar3@us.ibm.com> | 2017-06-13 17:11:26 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-09-29 16:06:23 -0400 |
commit | 22edf1585727cfa8b09b6f060651b446bdbe9fe3 (patch) | |
tree | eaf0a66abaf1d0d2d5ba0a0b68bfa58ccefd7676 /src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.H | |
parent | b850b557ea1199f9eed57f985ce93937012d4bbf (diff) | |
download | talos-hostboot-22edf1585727cfa8b09b6f060651b446bdbe9fe3.tar.gz talos-hostboot-22edf1585727cfa8b09b6f060651b446bdbe9fe3.zip |
PM Level 3 for multiple procedures
Commit itends to make following HWP level 3 ready
- p9_pm_pfet_control
- p9_pm_pfet_init
- p9_common_poweronoff
- p9_hcd_core_poweron
- p9_hcd_cache_chiplet_reset
- p9_hcd_cache_poweron
- p9_pm_set_homer_bar
- p9_query_stop_state
It also removes inclusion p9_common_poweronoff.C in C
files of many HWP.
Change-Id: I28a14ce4fe99630c4aa4a9044c2653763bbe35c5
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/41795
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
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: AMIT J. TENDOLKAR <amit.tendolkar@in.ibm.com>
Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/41798
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.H')
-rw-r--r-- | src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.H | 490 |
1 files changed, 489 insertions, 1 deletions
diff --git a/src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.H b/src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.H index 444cf23cc..f7442e13e 100644 --- a/src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.H +++ b/src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.H @@ -38,6 +38,8 @@ #define __P9_COMMON_POWERONOFF_H__ #include <fapi2.H> +#include <p9_quad_scom_addresses.H> +#include <p9_hcd_common.H> namespace p9power { @@ -133,10 +135,496 @@ typedef fapi2::ReturnCode (*p9_common_poweronoff_FP_t) ( /// @attritem ATTR_PFET_TIMING - EX target, uint32 /// /// @retval FAPI_RC_SUCCESS +#include "p9_hcd_common.H" + +//------------------------------------------------------------------------------ +// Constant Definitions: +//------------------------------------------------------------------------------ +// Define only address offset to be compatible with both core and cache domain + +const uint64_t NET_CTRL0_WOR[2] = { C_NET_CTRL0_WOR, + EQ_NET_CTRL0_WOR + }; + +const uint64_t PPM_PFCS[2] = { C_PPM_PFCS_SCOM, + EQ_PPM_PFCS_SCOM + }; + +const uint64_t PPM_PFCS_CLR[2] = { C_PPM_PFCS_SCOM1, + EQ_PPM_PFCS_SCOM1 + }; + +const uint64_t PPM_PFCS_OR[2] = { C_PPM_PFCS_SCOM2, + EQ_PPM_PFCS_SCOM2 + }; + +const uint64_t PPM_PFDLY[2] = { C_PPM_PFDLY, + EQ_PPM_PFDLY + }; + +const uint64_t PPM_PFSNS[2] = { C_PPM_PFSNS, + EQ_PPM_PFSNS + }; + +// With a PFET step delay of 250ns and 8 steps, the PFET controller needs ~2us to +// complete. A 500 delay keeps the SGPE off of the PCB bus to let other traffic +// through while potentially adding .5us to the STOP11 time. For this and the SBE +// usage of this (istep 4), this trade-off is acceptable. + +enum { FSM_IDLE_POLLING_HW_NS_DELAY = 500, + FSM_IDLE_POLLING_SIM_CYCLE_DELAY = 320000, + PFET_STATE_LENGTH = 2, + VXX_PG_SEL_LEN = 4 + }; + +enum pfetRegField { PFET_NOP = 0, + PFET_FORCE_VOFF = 1, + PFET_NOP_RESERVERD = 2, + PFET_FORCE_VON = 3 + }; + +enum pgStateOffset { PG_STATE_IDLE_OFFSET = 0, + PG_STATE_INC_OFFSET = 1, + PG_STATE_DEC_OFFSET = 2, + PG_STATE_WAIT_OFFSET = 3 + }; + + +enum PFCS_Bits { VDD_PFET_FORCE_STATE_BIT = 0, + VCS_PFET_FORCE_STATE_BIT = 2, + VDD_PFET_VAL_OVERRIDE_BIT = 4, + VDD_PFET_SEL_OVERRIDE_BIT = 5, + VCS_PFET_VAL_OVERRIDE_BIT = 6, + VCS_PFET_SEL_OVERRIDE_BIT = 7, + VDD_PFET_REGULATION_FINGER_EN_BIT = 8, + VDD_PFET_REGULATION_FINGER_VALUE_BIT = 9, + RESERVED1_BIT = 10, + VDD_PFET_ENABLE_VALUE_BIT = 12, + VDD_PFET_SEL_VALUE_BIT = 20, + VCS_PFET_ENABLE_VALUE_BIT = 24, + VCS_PFET_SEL_VALUE_BIT = 32, + RESERVED2_BIT = 36, + VDD_PG_STATE_BIT = 42, + VDD_PG_SEL_BIT = 46, + VCS_PG_STATE_BIT = 50, + VCS_PG_SEL_BIT = 54, + RESERVED3_BIT = 58 + }; + + +enum { VDD_PFETS_ENABLED_SENSE_BIT = 0, + VDD_PFETS_DISABLED_SENSE_BIT = 1, + VCS_PFETS_ENABLED_SENSE_BIT = 2, + VCS_PFETS_DISABLED_SENSE_BIT = 3 + }; + +enum { POWDN_DLY_BIT = 0, + POWUP_DLY_BIT = 4, + TP_VDD_PFET_ENABLE_ACTUAL_BIT = 16, + TP_VCS_PFET_ENABLE_ACTUAL_BIT = 24 + }; + +enum { POWDN_DLY_LENGTH = 4, + POWUP_DLY_LENGTH = 4, + TP_VDD_PFET_ENABLE_ACTUAL_LENGTH = 8, + TP_VCS_PFET_ENABLE_ACTUAL_LENGTH = 8 + }; + +// i_operation defines + + +//------------------------------------------------------------------------------ +// Procedure: +//------------------------------------------------------------------------------ template <fapi2::TargetType K> fapi2::ReturnCode p9_common_poweronoff( const fapi2::Target<K>& i_target, - const p9power::powerOperation_t i_operation); + const p9power::powerOperation_t i_operation) +{ + uint32_t l_loopsPerMs; + + FAPI_INF(">>p9_common_poweronoff: %d", i_operation); + uint32_t l_type = 0; // Assumes core + + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_parentProc = + i_target.template getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + if((i_target.getType() & fapi2::TARGET_TYPE_EQ)) + { + l_type = 1; + } + + uint8_t chipletPos = 0; + FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS, i_target, chipletPos ); + + fapi2::buffer<uint64_t> l_data; + fapi2::buffer<uint64_t> l_temp; // extractToRight seems the require space to write into. + + /////////////////////////////////////////////////////////////////////////// + // lambda functions for poweronoff procedure + /////////////////////////////////////////////////////////////////////////// + auto pollVddFSMIdle = [&] () + { + // Poll for PFETCNTLSTAT_REG[VDD_PG_STATE] for 0b1000 (FSM idle) + // – Timeout value = 1ms + FAPI_DBG("Polling for power gate sequencer state: FSM idle"); + l_loopsPerMs = 1E6 / FSM_IDLE_POLLING_HW_NS_DELAY; + + do + { + fapi2::delay(FSM_IDLE_POLLING_HW_NS_DELAY, + FSM_IDLE_POLLING_SIM_CYCLE_DELAY); + + FAPI_TRY(fapi2::getScom(i_target, PPM_PFSNS[l_type], l_data), + "getScom failed for address PPM_PFSNS"); // poll + } + while ((l_data.getBit<0>() == 0 ) && (--l_loopsPerMs != 0)); + + if( l_type ) + { + + FAPI_ASSERT((l_loopsPerMs != 0), + fapi2::VDD_QUAD_PFET_TIMEOUT() + .set_PPM_PFSNS_REG_VALUE( l_data ) + .set_PROC_CHIP( l_parentProc ) + .set_EQ_NUMBER_IN_ERROR( chipletPos ), + "VDD FSM Idle Timeout"); + } + else + { + FAPI_ASSERT((l_loopsPerMs != 0), + fapi2::VDD_CORE_PFET_TIMEOUT() + .set_PPM_PFSNS_REG_VALUE( l_data ) + .set_PROC_CHIP( l_parentProc ) + .set_CORE_NUMBER_IN_ERROR( chipletPos ), + "VDD FSM Idle Timeout"); + } + + fapi_try_exit: + return fapi2::current_err; + }; + + auto pollVcsFSMIdle = [&] () + { + // Poll for PFETCNTLSTAT_REG[VCS_PG_STATE] for 0b1000 (FSM idle) + // – Timeout value = 1ms + FAPI_DBG("Polling for power gate sequencer state: FSM idle"); + l_loopsPerMs = 1E6 / FSM_IDLE_POLLING_HW_NS_DELAY; + + do + { + fapi2::delay(FSM_IDLE_POLLING_HW_NS_DELAY, + FSM_IDLE_POLLING_SIM_CYCLE_DELAY); + + FAPI_TRY(fapi2::getScom(i_target, PPM_PFSNS[l_type], l_data), + "getScom failed for address PPM_PFSNS"); // poll + } + while ((l_data.getBit<2>() == 0 ) && (--l_loopsPerMs != 0)); + + if( l_type ) + { + + FAPI_ASSERT((l_loopsPerMs != 0), + fapi2::VCS_QUAD_PFET_TIMEOUT() + .set_PPM_PFSNS_REG_VALUE( l_data ) + .set_PROC_CHIP( l_parentProc ) + .set_EQ_NUMBER_IN_ERROR( chipletPos ), + "VCS FSM Idle Timeout" ); + } + else + { + FAPI_ASSERT((l_loopsPerMs != 0), + fapi2::VCS_CORE_PFET_TIMEOUT() + .set_PPM_PFSNS_REG_VALUE( l_data ) + .set_PROC_CHIP( l_parentProc ) + .set_CORE_NUMBER_IN_ERROR( chipletPos ), + "VCS FSM Idle Timeout" ); + } + + fapi_try_exit: + return fapi2::current_err; + + }; + + + auto powerOnVdd = [&] () + { + // Command the cache PFET controller to power-on + // Write PFETCNTLSTAT_REG: + // vdd_pfet_force_state = 11 (Force Von) + // vdd_pfet_val_override = 0 (Override disabled) + // vdd_pfet_sel_override = 0 (Override disabled) + // vdd_pfet_enable_regulation_finger = 0 + // (Regulation finger controlled by FSM) + FAPI_DBG("Clear VDD PFET stage select and value override bits"); + l_data.flush<0>(). + setBit<VDD_PFET_VAL_OVERRIDE_BIT>(). + setBit<VDD_PFET_SEL_OVERRIDE_BIT>(). + setBit<VDD_PFET_REGULATION_FINGER_EN_BIT>(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR[l_type], l_data), + "putScom failed for address PPM_PFCS"); + + FAPI_DBG("Force VDD on"); + l_data.flush<0>().insertFromRight + <VDD_PFET_FORCE_STATE_BIT, PFET_STATE_LENGTH>(PFET_FORCE_VON); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_OR[l_type], l_data), + "putScom failed for address PPM_PFCS_OR"); + + // Check for valid power on completion + // Polled Timeout: 100us + FAPI_TRY(pollVddFSMIdle()); + + // Write PFETCNTLSTAT_REG_WCLEAR + // vdd_pfet_force_state = 00 (No Operation); + // all fields set to 1 for WAND + // Use PPM_PFCS_CLR, + // vdd_pfet_force_state = 0b11 + FAPI_DBG("vdd_pfet_force_state = 00, or Idle"); + l_data.flush<0>().insertFromRight + <VDD_PFET_FORCE_STATE_BIT, PFET_STATE_LENGTH>(~PFET_NOP); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR[l_type], l_data), + "putScom failed for address PPM_PFCS_CLR"); + + fapi_try_exit: + return fapi2::current_err; + + }; + + auto powerOnVcs = [&] () + { + // Command the PFET controller to power-on + // Write PFETCNTLSTAT_REG_OR with values defined below + // vcs_pfet_force_state = 11 (Force Von) + // Write to PFETCNTLSTAT_REG_CLR + // vcs_pfet_val_override = 0 (Override disabled) + // vcs_pfet_sel_override = 0 (Override disabled) + // Note there is no vcs_pfet_enable_regulation_finger + FAPI_DBG("Clear VCS PFET stage select and value override bits"); + l_data.flush<0>(). + setBit<VCS_PFET_VAL_OVERRIDE_BIT>(). + setBit<VCS_PFET_SEL_OVERRIDE_BIT>(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR[l_type], l_data), + "putScom failed for address PPM_PFCS_CLR"); + + FAPI_DBG("Force VCS on"); + l_data.flush<0>().insertFromRight + <VCS_PFET_FORCE_STATE_BIT, PFET_STATE_LENGTH>(PFET_FORCE_VON); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_OR[l_type], l_data), + "putScom failed for address PPM_PFCS_OR"); + + // Check for valid power on completion + // Polled Timeout: 100us + FAPI_TRY(pollVcsFSMIdle()); + + // Write PFETCNTLSTAT_REG_WCLEAR + // vcs_pfet_force_state = 00 (No Operation); + // all fields set to 1 for WAND + // Use PPM_PFCS_CLR, vdd_pfet_force_state = ~(0b00) + FAPI_DBG("vcs_pfet_force_state = 00, or Idle"); + l_data.flush<0>().insertFromRight + <VCS_PFET_FORCE_STATE_BIT, PFET_STATE_LENGTH>(~PFET_NOP); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR[l_type], l_data), + "putScom failed for address PPM_PFCS_CLR"); + + fapi_try_exit: + return fapi2::current_err; + }; + + auto powerOffVdd = [&] () + { + // Command the PFET controller to power-off + // Write PFETCNTLSTAT_REG: + // vdd_pfet_force_state = 01 (Force Voff) + // vdd_pfet_val_override = 0 (Override disabled) + // vdd_pfet_sel_override = 0 (Override disabled) + // vdd_pfet_enable_regulation_finger = 0 + // (Regulation finger controlled by FSM) + FAPI_DBG("Clear VDD PFET stage select and value override bits"); + l_data.flush<0>(). + setBit<VDD_PFET_VAL_OVERRIDE_BIT>(). + setBit<VDD_PFET_SEL_OVERRIDE_BIT>(). + setBit<VDD_PFET_REGULATION_FINGER_EN_BIT>(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR[l_type], l_data), + "putScom failed for address PPM_PFCS"); + + FAPI_DBG("Force VDD off"); + l_data.flush<0>().insertFromRight + <VDD_PFET_FORCE_STATE_BIT, PFET_STATE_LENGTH>(PFET_FORCE_VOFF); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_OR[l_type], l_data), + "putScom failed for address PPM_PFCS"); + + // Check for valid power off completion + // Polled Timeout: 100us + FAPI_TRY(pollVddFSMIdle()); + + // Write PFETCNTLSTAT_REG_WCLEAR + // vdd_pfet_force_state = 00 (No Operation); + // all fields set to 1 for WAND + // Use PPM_PFCS_CLR, vdd_pfet_force_state = 0b11 + FAPI_DBG("vdd_pfet_force_state = 00, or Idle"); + l_data.flush<0>().insertFromRight + <VDD_PFET_FORCE_STATE_BIT, PFET_STATE_LENGTH>(~PFET_NOP); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR[l_type], l_data), + "putScom failed for address PPM_PFCS_CLR"); + + fapi_try_exit: + return fapi2::current_err; + }; + + auto powerOffVcs = [&] () + { + // Command the PFET controller to power-off + // Write PFETCNTLSTAT_REG_OR with values defined below + // vcs_pfet_force_state = 11 (Force Voff) + // vcs_pfet_val_override = 0 (Override disabled) + // vcs_pfet_sel_override = 0 (Override disabled) + // Note there is no vcs_pfet_enable_regulation_finger + FAPI_DBG("Clear VCS PFET stage select and value override bits"); + l_data.flush<0>(). + setBit<VCS_PFET_VAL_OVERRIDE_BIT>(). + setBit<VCS_PFET_SEL_OVERRIDE_BIT>(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR[l_type], l_data), + "putScom failed for address PPM_PFCS_CLR"); + + FAPI_DBG("Force VCS off"); + l_data.flush<0>(). + insertFromRight + <VCS_PFET_FORCE_STATE_BIT, PFET_STATE_LENGTH>(PFET_FORCE_VOFF); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_OR[l_type], l_data), + "putScom failed for address PPM_PFCS_OR"); + + // Check for valid power off completion + // Polled Timeout: 100us + FAPI_TRY(pollVcsFSMIdle()); + + // Write PFETCNTLSTAT_REG_WCLEAR + // vcs_pfet_force_state = 00 (No Operation); + // all fields set to 1 for WAND + // Use PPM_PFCS_CLR, vcs_pfet_force_state = ~(0b00) + FAPI_DBG("vcs_pfet_force_state = 00, or Idle"); + l_data.flush<0>().insertFromRight + <VCS_PFET_FORCE_STATE_BIT, PFET_STATE_LENGTH>(~PFET_NOP); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR[l_type], l_data), + "putScom failed for address PPM_PFCS_CLR"); + + fapi_try_exit: + return fapi2::current_err; + }; + + /////////////////////////////////////////////////////////////////////////// + // Initialization code + /////////////////////////////////////////////////////////////////////////// + + fapi2::buffer<uint64_t> l_data64; + FAPI_DBG("Assert PCB fence via NET_CTRL0[25]"); + FAPI_TRY(putScom(i_target, NET_CTRL0_WOR[l_type], MASK_SET(25))); + + FAPI_DBG("Assert chiplet electrical fence via NET_CTRL0[26]"); + FAPI_TRY(putScom(i_target, NET_CTRL0_WOR[l_type], MASK_SET(26))); + + FAPI_DBG("Assert vital thold via NET_CTRL0[16]"); + FAPI_TRY(putScom(i_target, NET_CTRL0_WOR[l_type], MASK_SET(16))); + + /////////////////////////////////////////////////////////////////////////// + // Procedure code + /////////////////////////////////////////////////////////////////////////// + switch(i_operation) + { + case p9power::POWER_ON: + case p9power::POWER_ON_VDD: + case p9power::POWER_ON_VCS: + { + // 4.3.8.1 Power-on via Hardware FSM + + // VDD first, VCS second + + // 1) Read PFETCNTLSTAT_REG: check for bits 0:3 being 0b0000 + l_data.flush<0>(). + setBit<VCS_PFET_VAL_OVERRIDE_BIT>(). + setBit<VCS_PFET_SEL_OVERRIDE_BIT>(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR[l_type], l_data), + "putScom failed for address PPM_PFCS_CLR"); + + FAPI_DBG("Make sure that we are not forcing PFET for VCS or VDD off"); + FAPI_TRY(fapi2::getScom(i_target, PPM_PFCS[l_type], l_data), + "getScom failed for address PPM_PFCS"); + l_data.extractToRight + <VDD_PFET_FORCE_STATE_BIT, 2 * PFET_STATE_LENGTH> + (l_temp); + FAPI_ASSERT((l_temp == 0), + fapi2::PFET_FORCE_STATE_ERROR() + .set_CHIPLET( i_target ) + .set_OP_TYPE( i_operation ) + .set_PFCS_REG_ADDRESS( PPM_PFCS[l_type] ) + .set_PFCS_REG_VALUE( l_data ), + "PFET_FORCE_STATE not 0"); + + // 2) Set bits to program HW to enable VDD PFET, and + // 3) Poll state bit until Pfet sequence is complete + if (i_operation != p9power::POWER_ON_VCS) + { + FAPI_TRY(powerOnVdd()); + } + + // 4) Set bits to program HW to enable VCS PFET, and + // 5) Poll state bit until Pfet sequence is complete + + // Note: if (i_target.getType() & fapi2::TARGET_TYPE_EQ) doesn't work. + // Created a POWER_*_VDD label to delineate Vcs and Vdd + if (i_operation != p9power::POWER_ON_VDD) + { + FAPI_TRY(powerOnVcs()); + } + + } + break; + + case p9power::POWER_OFF: + case p9power::POWER_OFF_VDD: + case p9power::POWER_OFF_VCS: + { + // 4.3.8.2 Power-off via Hardware FSM + // 1) Read PFETCNTLSTAT_REG: check for bits 0:3 being 0b0000 + FAPI_DBG("Make sure that we are not forcing PFET for VCS or VDD off"); + FAPI_TRY(fapi2::getScom(i_target, PPM_PFCS[l_type], l_data), + "getScom failed for address PPM_PFCS"); + + l_data.extractToRight + <VDD_PFET_FORCE_STATE_BIT, 2 * PFET_STATE_LENGTH> + (l_temp); + + FAPI_ASSERT((l_temp == 0), + fapi2::PFET_FORCE_STATE_ERROR() + .set_CHIPLET( i_target ) + .set_OP_TYPE( i_operation ) + .set_PFCS_REG_ADDRESS( PPM_PFCS[l_type] ) + .set_PFCS_REG_VALUE( l_data ), + "PFET_FORCE_STATE not 0"); + + // 2) Set bits to program HW to turn off VCS PFET, and + // 3) Poll state bit until Pfet sequence is complete + + // Note: if (i_target.getType() & fapi2::TARGET_TYPE_EQ) doesn't work. + // Created a POWER_*_VDD label to delineate Vcs and Vdd + if (i_operation != p9power::POWER_OFF_VDD) + { + FAPI_TRY(powerOffVcs()); + } + + // 4) Set bits to program HW to turn off VDD PFET, and + // 5) Poll state bit until Pfet sequence is complete + if (i_operation != p9power::POWER_OFF_VCS) + { + FAPI_TRY(powerOffVdd()); + } + } + break; + } + + FAPI_INF("<<p9_common_poweronoff"); +fapi_try_exit: + return fapi2::current_err; +} // Procedure #endif // __P9_COMMON_POWERONOFF_H__ |