From e8e8287ce9d90a4858646b14d9cb67a82340b8ea Mon Sep 17 00:00:00 2001 From: Yue Du Date: Mon, 28 Sep 2015 13:41:48 -0500 Subject: [PATCH] PPE-HWP: [Level 2] Cache/Core chiplet_reset/init/scan0+startclocks Change-Id: I342d04700955ff99ddc1b027a53850972b5445a0 Original-Change-Id: Idb0cddd12c06b5662757f02c5d28fe6dd1c9b03c Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/20827 Tested-by: Jenkins Server Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/36090 Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Tested-by: Jenkins OP Build CI Reviewed-by: Christian R. Geddes --- .../procedures/hwp/lib/p9_common_poweronoff.C | 462 ++++++++++++++++++ .../procedures/hwp/lib/p9_common_poweronoff.H | 85 ++++ 2 files changed, 547 insertions(+) create mode 100644 src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.C create mode 100644 src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.H diff --git a/src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.C b/src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.C new file mode 100644 index 00000000000..98ba461435d --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.C @@ -0,0 +1,462 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/lib/p9_common_poweronoff.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_common_poweronoff.C +/// @brief common procedure for power on/off +/// +// *HWP HWP Owner : David Du +// *HWP Backup HWP Owner : Greg Still +// *HWP FW Owner : Sangeetha T S +// *HWP Team : PM +// *HWP Consumed by : SBE:SGPE:CME +// *HWP Level : 2 +// +// Procedure Summary: +// + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include +#include "p9_common_poweronoff.H" + +//------------------------------------------------------------------------------ +// Constant Definitions: +//------------------------------------------------------------------------------ +enum { CYCLES_PER_MS = 500000, + INST_PER_LOOP = 8, + 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: +//------------------------------------------------------------------------------ + +fapi2::ReturnCode +p9_common_poweronoff( + const fapi2::Target < fapi2::TARGET_TYPE_EQ | + fapi2::TARGET_TYPE_CORE > & i_target, + const p9power::powerOperation_t i_operation) +{ + uint32_t l_loopsPerMs; + + FAPI_INF(">>p9_common_poweronoff: %d", i_operation); + + fapi2::buffer l_data; + fapi2::buffer 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 = CYCLES_PER_MS / INST_PER_LOOP; + + // Note that the Lamda assumes that l_data already contains the + do + { + FAPI_TRY(fapi2::getScom(i_target, PPM_PFCS, l_data), + "getScom failed for address PPM_PFCS"); // poll + } + while ((l_data.getBit < VDD_PG_STATE_BIT + PG_STATE_IDLE_OFFSET > () + != 0 ) && (--l_loopsPerMs != 0)); + + FAPI_ASSERT((l_loopsPerMs != 0), + fapi2::PMPROC_PFETLIB_TIMEOUT() + .set_ADDRESS(PPM_PFCS), + "VDD FSM idle timeout"); + + /// (Optional) Check PFETCNTLSTAT_REG[VDD_PG_SEL]being 0x8 + // (Off encode point) +#if 0 // this field does not get set yet + l_data.extractToRight(l_temp); + FAPI_ASSERT((l_temp == 8), + fapi2::PROCPM_PFET_CODE_BAD_MODE(), + "VDD_PG_SEL != 8: l_temp %0x", l_temp); + +#endif + fapi_try_exit: + return fapi2::current_err; + }; + + auto pollVcsFSMIdle = [&] () + { + // 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 = CYCLES_PER_MS / INST_PER_LOOP; + + do + { + FAPI_TRY(fapi2::getScom(i_target, PPM_PFCS, l_data), + "getScom failed for address PPM_PFCS"); // poll + FAPI_DBG("timeout l_loopsPerMs. %x", l_loopsPerMs); + } + while ((l_data.getBit < VCS_PG_STATE_BIT + PG_STATE_IDLE_OFFSET > () + != 0 ) && (--l_loopsPerMs != 0)); + + FAPI_ASSERT((l_loopsPerMs != 0), + fapi2::PMPROC_PFETLIB_TIMEOUT() + .set_ADDRESS(PPM_PFCS), + "VCS FSM idle timeout"); + + // (Optional) Check PFETCNTLSTAT_REG[VDD_PG_SEL] + // being 0x8 (Off encode point) + + +#if 0 // this field does not get set yet + l_data.extractToRight(l_temp); + FAPI_ASSERT((l_temp == 8), + fapi2::PROCPM_PFET_CODE_BAD_MODE(), + "VCS_PG_SEL != 8: l_temp %0x", l_temp); + +#endif + 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(). + setBit(). + setBit(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR, l_data), + "putScom failed for address PPM_PFCS"); + + FAPI_DBG("Force VDD on"); + l_data.flush<0>().insertFromRight + (PFET_FORCE_VON); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_OR, 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 + (~PFET_NOP); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR, 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 VSS PFET stage select and value override bits"); + l_data.flush<0>(). + setBit(). + setBit(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR, l_data), + "putScom failed for address PPM_PFCS_CLR"); + + FAPI_DBG("Force VSS on"); + l_data.flush<0>().insertFromRight + (PFET_FORCE_VON); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_OR, 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("vss_pfet_force_state = 00, or Idle"); + l_data.flush<0>().insertFromRight + (~PFET_NOP); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR, 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(). + setBit(). + setBit(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR, l_data), + "putScom failed for address PPM_PFCS"); + + FAPI_DBG("Force VDD off"); + l_data.flush<0>().insertFromRight + (PFET_FORCE_VOFF); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_OR, 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 + (~PFET_NOP); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR, 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) + // DOC BUG: ?? 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 VSS PFET stage select and value override bits"); + l_data.flush<0>(). + setBit(). + setBit(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR, l_data), + "putScom failed for address PPM_PFCS_CLR"); + + FAPI_DBG("Force VSS off"); + l_data.flush<0>(). + insertFromRight + (PFET_FORCE_VOFF); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_OR, 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 + (~PFET_NOP); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR, l_data), + "putScom failed for address PPM_PFCS_CLR"); + + fapi_try_exit: + return fapi2::current_err; + }; + + /////////////////////////////////////////////////////////////////////////// + // Initialization code + /////////////////////////////////////////////////////////////////////////// +#if 0 // unneeded for AWAN operation. Also, fails if delay field is > 8 + l_data.flush<0>().insertFromRight(0x8). + insertFromRight(0x8); + + FAPI_TRY(fapi2::putScom(i_target, PPM_PFDLY, l_data), + "putScom failed for address PPM_PFDLY"); +#endif + + /////////////////////////////////////////////////////////////////////////// + // Procedure code + /////////////////////////////////////////////////////////////////////////// + switch(i_operation) + { + case p9power::POWER_ON: + case p9power::POWER_ON_VDD: + { + // 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(). + setBit(); + FAPI_TRY(fapi2::putScom(i_target, PPM_PFCS_CLR, 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_data), + "getScom failed for address PPM_PFCS"); + l_data.extractToRight + + (l_temp); + FAPI_ASSERT((l_temp == 0), + fapi2::PMPROC_PFETLIB_BAD_SCOM() + .set_ADDRESS(PPM_PFCS), + "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 + 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) + { + FAPI_TRY(powerOnVcs()); + } + + } + break; + + case p9power::POWER_OFF: + case p9power::POWER_OFF_VDD: + { + // 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_data), + "getScom failed for address PPM_PFCS"); + + l_data.extractToRight + + (l_temp); + FAPI_ASSERT((l_temp == 0), + fapi2::PMPROC_PFETLIB_BAD_SCOM() + .set_ADDRESS(PPM_PFCS), + "PFET_FORCE_STATE not 0"); + + // 2) Set bits to program HW to turn off VDD PFET, and + // 3) Poll state bit until Pfet sequence is complete + FAPI_TRY(powerOffVdd()); + + // 4) Set bits to program HW to turn off 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_OFF) + { + FAPI_TRY(powerOffVcs()); + } + + } + break; + } + + FAPI_INF("< +/// *HWP Backup HWP Owner : Greg Still +/// *HWP FW Owner : Sangeetha T S +/// *HWP Team : PM +/// *HWP Consumed by : SBE:SGPE:CME +/// *HWP Level : 2 +/// + +#ifndef __P9_COMMON_POWERONOFF_H__ +#define __P9_COMMON_POWERONOFF_H__ + +namespace p9power +{ +enum powerOperation_t +{ + POWER_ON = 0x0, + POWER_OFF = 0xFF, + POWER_ON_VDD = 0x1, + POWER_OFF_VDD = 0xFE +}; +} + +// Define only address offset to be compatible with both core and cache domain +#define PPM_PFCS 0x000f0118 +#define PPM_PFCS_CLR 0x000f0119 +#define PPM_PFCS_OR 0x000f011a +#define PPM_PFDLY 0x000f011b +#define PPM_PFSNS 0x000f011c +#define PPM_PFOFF 0x000f011d + +/// @typedef p9_common_poweronoff_FP_t +/// function pointer typedef definition for HWP call support +typedef fapi2::ReturnCode (*p9_common_poweronoff_FP_t) ( + const fapi2::Target < fapi2::TARGET_TYPE_EQ | + fapi2::TARGET_TYPE_CORE > &, + const p9power::powerOperation_t i_operation); + +extern "C" +{ +/// @brief common procedure for power on/off +/// +/// @param [in] i_target TARGET_TYPE_EQ|TARGET_TYPE_CORE target +/// @param [in] i_operation ENUM(ON,OFF) +/// +/// @attr +/// @attritem ATTR_PFET_TIMING - EX target, uint32 +/// +/// @retval FAPI_RC_SUCCESS + fapi2::ReturnCode + p9_common_poweronoff( + const fapi2::Target < fapi2::TARGET_TYPE_EQ | + fapi2::TARGET_TYPE_CORE > & i_target, + const p9power::powerOperation_t i_operation); + +} // extern C + +#endif // __P9_COMMON_POWERONOFF_H__