summaryrefslogtreecommitdiffstats
path: root/src/lib/gpsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/gpsm.c')
-rwxr-xr-xsrc/lib/gpsm.c600
1 files changed, 0 insertions, 600 deletions
diff --git a/src/lib/gpsm.c b/src/lib/gpsm.c
deleted file mode 100755
index e2b71d6..0000000
--- a/src/lib/gpsm.c
+++ /dev/null
@@ -1,600 +0,0 @@
-// $Id: gpsm.c,v 1.2 2014/02/03 01:30:24 daviddu Exp $
-// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpsm.c,v $
-//-----------------------------------------------------------------------------
-// *! (C) Copyright International Business Machines Corp. 2013
-// *! All Rights Reserved -- Property of IBM
-// *! *** IBM Confidential ***
-//-----------------------------------------------------------------------------
-
-/// \file gpsm.c
-/// \brief Global Pstate Mechanism procedures
-///
-/// \todo : Should we initialize any/all iVRM delays in gpsm_lpsa_install()?
-
-#include "ssx.h"
-#include "pstates.h"
-#include "gpe_control.h"
-#include "gpsm.h"
-#include "vrm.h"
-
-/// The semaphore used to block threads waiting for GPSM protocol actions
-
-SsxSemaphore G_gpsm_protocol_semaphore;
-
-
-////////////////////////////////////////////////////////////////////////////
-// Private Utilities
-////////////////////////////////////////////////////////////////////////////
-
-// The mechanical transition to Firmware Pstate Mode - Not a procedure
-
-static void
-_gpsm_fw_mode(void)
-{
- pmc_mode_reg_t pmr;
-
- pmr.value = in32(PMC_MODE_REG);
- pmr.fields.enable_hw_pstate_mode = 0;
- pmr.fields.enable_fw_auction_pstate_mode = 0;
- pmr.fields.enable_fw_pstate_mode = 1;
- out32(PMC_MODE_REG, pmr.value);
-}
-
-
-// The mechanical transition to Firmware Auction Pstate Mode - Not a procedure
-
-static void
-_gpsm_fw_auction_mode(void)
-{
- pmc_mode_reg_t pmr;
-
- pmr.value = in32(PMC_MODE_REG);
- pmr.fields.enable_hw_pstate_mode = 0;
- pmr.fields.enable_fw_auction_pstate_mode = 1;
- pmr.fields.enable_fw_pstate_mode = 0;
- out32(PMC_MODE_REG, pmr.value);
-}
-
-
-// The mechanical transition to Hardware Pstate Mode - Not a procedure.
-// Disable voltage change via safe_mode_without_spivid
-// before enter hw mode to prevent possible glitch that
-// hw momentarily flush turbo to pstate actual,
-// After enter hw mode, we will enable back the spivid
-
-static void
-_gpsm_hw_mode(void)
-{
- pmc_mode_reg_t pmr;
-
- if (!gpsm_dcm_slave_p()) {
- pmr.value = in32(PMC_MODE_REG);
- pmr.fields.safe_mode_without_spivid = 1;
- out32(PMC_MODE_REG, pmr.value);
- }
-
- pmr.value = in32(PMC_MODE_REG);
- pmr.fields.enable_hw_pstate_mode = 1;
- pmr.fields.enable_fw_auction_pstate_mode = 0;
- pmr.fields.enable_fw_pstate_mode = 0;
- out32(PMC_MODE_REG, pmr.value);
-
- if (!gpsm_dcm_slave_p()) {
- pmr.value = in32(PMC_MODE_REG);
- pmr.fields.safe_mode_without_spivid = 0;
- out32(PMC_MODE_REG, pmr.value);
- }
-
-}
-
-
-////////////////////////////////////////////////////////////////////////////
-// Private Sub-Procedures
-////////////////////////////////////////////////////////////////////////////
-
-// By definition, quiescing the GPSM always leaves the system in firmware
-// Pstate mode. This is necessary for a consistent specification due to the
-// fact that in general, Hardware Pstate mode can not be quiesced without
-// leaving that mode.
-
-// To quiesce the GPSM in firmware or firmware auction mode requires waiting
-// for both the voltage and frequency changes to be complete. Note that they
-// will never be ongoing simultaneously. This predicate is used for all
-// firmware-mode quiesce, even though normally only one part or the other
-// (voltage/protocol) is active.
-//
-// Recall that PMC interrupts are level-low, so if ongoing status is clear,
-// the operation is ongoing.
-
-static int
-gpsm_fw_quiesce(void)
-{
- int rc = 0;
-
- if (!ssx_irq_status_get(PGP_IRQ_PMC_PROTOCOL_ONGOING)) {
- ssx_irq_enable(PGP_IRQ_PMC_PROTOCOL_ONGOING);
- rc = ssx_semaphore_pend(&G_gpsm_protocol_semaphore, SSX_WAIT_FOREVER);
- }
-
- if ((!rc) && !ssx_irq_status_get(PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING)) {
- ssx_irq_enable(PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING);
- rc = ssx_semaphore_pend(&G_gpsm_protocol_semaphore, SSX_WAIT_FOREVER);
- }
-
- if (!rc) {
- _gpsm_fw_mode();
- }
-
- return rc;
-}
-
-
-// To quiesce the GPSM in hardware mode requires waiting for any ongoing
-// Pstate change to be complete. Note that there is no guarantee that this
-// condition will ever be true in general unless something external to PMC
-// ensures that Global bids stop coming in to the GPSM. An alternative used
-// here is to 'lock' the GPSM temporarily by setting the rail bounds min and
-// max to the current Global Pstate Actual. The GPSM will eventually quiesce
-// at the global actual, and we can safely move to Firmware Pstate mode and
-// release the lock.
-//
-// Recall that PMC 'ongoing' interrupts are level-low, so if ongoing status is
-// clear, the operation is ongoing.
-
-static int
-gpsm_hw_quiesce(void)
-{
- int rc = 0;
- pmc_rail_bounds_register_t prbr, original_prbr;
- pmc_pstate_monitor_and_ctrl_reg_t ppmacr;
-
- ppmacr.value = in32(PMC_PSTATE_MONITOR_AND_CTRL_REG);
-
- original_prbr.value = prbr.value = in32(PMC_RAIL_BOUNDS_REGISTER);
- prbr.fields.pmin_rail = ppmacr.fields.gpsa;
- prbr.fields.pmax_rail = ppmacr.fields.gpsa;
- out32(PMC_RAIL_BOUNDS_REGISTER, prbr.value);
-
- rc = _gpsm_hw_quiesce();
-
- if (!rc) {
- _gpsm_fw_mode();
- out32(PMC_RAIL_BOUNDS_REGISTER, original_prbr.value);
- }
-
- return rc;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// Public Predicates
-////////////////////////////////////////////////////////////////////////////
-
-/// Is the Global Pstate Mechanism quiesced?
-///
-/// This predicate can only truly be answered 'true' if we are not in
-/// hardware Pstate mode.
-///
-/// \retval 0 Either we're in Hardware Pstate Mode, or a Voltage/Frequency
-/// operation is ongoing.
-///
-/// \retval 1 We're not in Hardware Pstate Mode and no Voltage/Frequency
-/// operation is ongoing.
-
-int
-gpsm_quiesced_p(void)
-{
- return !(gpsm_hw_mode_p() ||
- !ssx_irq_status_get(PGP_IRQ_PMC_PROTOCOL_ONGOING) ||
- !ssx_irq_status_get(PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING));
-}
-
-/// Predicate: Is the PMC in hardware Pstate mode?
-///
-/// \returns 0/1
-
-int
-gpsm_hw_mode_p(void)
-{
- pmc_mode_reg_t pmr;
-
- pmr.value = in32(PMC_MODE_REG);
- return (pmr.fields.enable_hw_pstate_mode != 0);
-}
-
-
-/// Predicate: Is the PMC in firmware auction Pstate mode?
-///
-/// \returns 0/1
-
-int
-gpsm_fw_auction_mode_p(void)
-{
- pmc_mode_reg_t pmr;
-
- pmr.value = in32(PMC_MODE_REG);
- return (pmr.fields.enable_fw_auction_pstate_mode != 0);
-}
-
-
-/// Predicate: Is the PMC in firmware Pstate mode?
-///
-/// \returns 0/1
-
-int
-gpsm_fw_mode_p(void)
-{
- pmc_mode_reg_t pmr;
-
- pmr.value = in32(PMC_MODE_REG);
- return (pmr.fields.enable_fw_pstate_mode != 0);
-}
-
-
-/// Predicate: Is the chip configured as a DCM?
-///
-/// \returns 0/1
-
-int
-gpsm_dcm_mode_p(void)
-{
- pmc_mode_reg_t pmc_mode_reg;
- pmc_mode_reg.value = in32(PMC_MODE_REG);
- return pmc_mode_reg.fields.enable_interchip_interface;
-}
-
-
-/// Predicate: Is the chip configured as a DCM Slave?
-///
-/// \returns 0/1
-
-int
-gpsm_dcm_master_p(void)
-{
- pmc_mode_reg_t pmc_mode_reg;
- pmc_mode_reg.value = in32(PMC_MODE_REG);
- return
- pmc_mode_reg.fields.enable_interchip_interface &&
- pmc_mode_reg.fields.interchip_mode;
-}
-
-
-/// Predicate: Is the chip configured as a DCM Slave?
-///
-/// \returns 0/1
-
-int
-gpsm_dcm_slave_p(void)
-{
- pmc_mode_reg_t pmc_mode_reg;
- pmc_mode_reg.value = in32(PMC_MODE_REG);
- return
- pmc_mode_reg.fields.enable_interchip_interface &&
- (pmc_mode_reg.fields.interchip_mode == 0);
-}
-
-
-
-
-////////////////////////////////////////////////////////////////////////////
-// Procedures
-////////////////////////////////////////////////////////////////////////////
-
-/// Recover the GlobalPstateTable object from the PMC
-///
-/// \note It is assumed that the pointer to the Global Pstate table installed
-/// in the PMC is actually a pointer to a complete GlobalPstateTable object
-/// (which contains a Global Pstate table as its first element).
-///
-/// \returns A pointer to the currently active GlobalPstateTable object.
-
-GlobalPstateTable*
-gpsm_gpst(void)
-{
- pmc_parameter_reg1_t ppr1;
-
- ppr1.value = in32(PMC_PARAMETER_REG1);
- return (GlobalPstateTable*)
- (ppr1.fields.ba_sram_pstate_table << GLOBAL_PSTATE_TABLE_ALIGNMENT);
-}
-
-
-/// Quiesce the GPSM to firmware mode from any other mode
-///
-/// At the exit of this procedure, the PMC will be in Firmware Pstate Mode and
-/// there will be no ongoing voltage or frequency transitions.
-int
-gpsm_quiesce(void)
-{
- int rc;
-
- if (gpsm_hw_mode_p()) {
- rc = gpsm_hw_quiesce();
- } else {
- rc = gpsm_fw_quiesce();
- }
-
- return rc;
-}
-
-/// Quiesce the GPSM in Hardware Pstate Mode
-///
-/// In general there is no guarantee that the GPSM will ever quiesce, or
-/// remain quiesced in Hardware Pstate Mode unless something like the
-/// procedure in gpsm_hw_quiesce() is used. This procedure is provided for
-/// the benefit of applications that are in complete control of Pstates
-/// (including idle state Pstates) to simply wait for the Pstate protocol to
-/// quiesce, without quiescing and entering Firmware Pstate mode like
-/// gpsm_hw_quiesce().
-
-int
-_gpsm_hw_quiesce(void)
-{
- int rc;
-
- do {
- rc = 0;
-
- if (!gpsm_hw_mode_p()) {
- rc = -GPSM_ILLEGAL_MODE_HW_QUIESCE;
- break;
- }
-
- if (!ssx_irq_status_get(PGP_IRQ_PMC_PROTOCOL_ONGOING)) {
- ssx_irq_enable(PGP_IRQ_PMC_PROTOCOL_ONGOING);
- rc = ssx_semaphore_pend(&G_gpsm_protocol_semaphore,
- SSX_WAIT_FOREVER);
- if (rc) break;
- }
- } while (0);
-
- return rc;
-}
-
-
-/// Change to GPSM firmware mode from any mode
-
-int
-gpsm_fw_mode(void)
-{
- return gpsm_quiesce();
-}
-
-
-/// Change to GPSM firmware auction mode from any mode
-
-int
-gpsm_fw_auction_mode(void)
-{
- int rc;
-
- rc = gpsm_quiesce();
- if (!rc) {
- _gpsm_fw_auction_mode();
- }
- return rc;
-}
-
-
-/// Change to Hardware Pstate Mode
-///
-/// The (unchecked) assumption behind this procedure is that the caller has
-/// run through Pstate intialization and enablement, and the system is in a
-/// state where the entry to Hardware Pstate Mode is safe once the GPSM is
-/// quiesced.
-
-int
-gpsm_hw_mode(void)
-{
- int rc;
-
- TRACE_GPSM(TRACE_GPSM_HW_MODE);
-
- rc = gpsm_quiesce();
- if (!rc) {
- _gpsm_hw_mode();
- }
- return rc;
-}
-
-
-/// The default GPSM auction procedure
-///
-/// The default auction returns the value of
-/// PMC_HARDWARE_AUCTION_PSTATE_REG.haps.
-
-Pstate
-gpsm_default_auction(void)
-{
- pmc_hardware_auction_pstate_reg_t phapr;
-
- phapr.value = in32(PMC_HARDWARE_AUCTION_PSTATE_REG);
- return phapr.fields.haps;
-}
-
-
-/// Update a user-supplied vector of Pstates with the current Global bid of
-/// each core.
-///
-/// \param[out] o_bids A vector of Pstates; The vector must be large enough to
-/// hold the bid of every possible core.
-///
-/// This routine is provided for use by non-default Global Pstate auction
-/// procedures.
-
-void
-gpsm_get_global_bids(Pstate *o_bids)
-{
- // This takes advantage of the implicit layout of the
- // PMC_CORE_PSTATE_REG<n>.
-
- uint32_t *bids32 = (uint32_t *)o_bids;
-
- bids32[0] = in32(PMC_CORE_PSTATE_REG0);
- bids32[1] = in32(PMC_CORE_PSTATE_REG1);
- bids32[2] = in32(PMC_CORE_PSTATE_REG2);
- bids32[3] = in32(PMC_CORE_PSTATE_REG3);
-}
-
-
-/// Update a current Global bid of each core from a user supplied vector.
-///
-/// \param[in] i_bids An array of Global Pstate bids.
-///
-/// This routine is provided for use by test procedures; there is likely no
-/// product-level energy management application for this procedure.
-
-void
-gpsm_set_global_bids(const Pstate *i_bids)
-{
- // This takes advantage of the implicit layout of the
- // PMC_CORE_PSTATE_REG<n>.
-
- uint32_t *bids32 = (uint32_t *)i_bids;
-
- out32(PMC_CORE_PSTATE_REG0, bids32[0]);
- out32(PMC_CORE_PSTATE_REG1, bids32[1]);
- out32(PMC_CORE_PSTATE_REG2, bids32[2]);
- out32(PMC_CORE_PSTATE_REG3, bids32[3]);
-}
-
-
-/// Application-controlled Global Actual Broadcast
-///
-/// \param[in] i_pstate The Global Actual Pstate to broadcast
-///
-/// \param[in] i_entry A gpst_entry_t containing the information to be used by
-/// the iVRM. If iVRM are not enabled then \a entry can be initialized to 0.
-///
-/// This API is provided for advanced applications to have complete control
-/// over a firmware-mode Global Actual broadcast. There is no error
-/// checking. Most applications in Firware Pstate mode will use the
-/// higher-level gpsm_broadcast_global_actual() API.
-
-void
-_gpsm_broadcast_global_actual(const Pstate i_pstate,
- const gpst_entry_t i_entry)
-{
- pmc_pstate_monitor_and_ctrl_reg_t ppmacr;
- pmc_eff_global_actual_voltage_reg_t pegavr;
-
- ppmacr.value = 0;
- ppmacr.fields.gpsa = i_pstate;
- out32(PMC_PSTATE_MONITOR_AND_CTRL_REG, ppmacr.value);
-
- pegavr.value = 0;
- pegavr.fields.maxreg_vdd = i_entry.fields.maxreg_vdd;
- pegavr.fields.maxreg_vcs = i_entry.fields.maxreg_vcs;
- pegavr.fields.eff_evid_vdd = i_entry.fields.evid_vdd_eff;
- pegavr.fields.eff_evid_vcs = i_entry.fields.evid_vcs_eff;
- out32(PMC_EFF_GLOBAL_ACTUAL_VOLTAGE_REG, pegavr.value);
-
- TRACE_GPSM(TRACE_GPSM_BROADCAST_GLOBAL_ACTUAL);
-}
-
-
-/// Broadcast the Global Actual Pstate in firmware Pstate mode.
-///
-/// \param[in] i_gpst An initialized GlobalPstateTable structure used to
-/// define the legal Pstate range, and to provide the voltage settings
-/// (maxreg_vxx and eff_evid_vxx) for the internal VRM.
-///
-/// \param[in] i_pstate The pstate specfiying the Global Actual Pstate to be
-/// broadast to the core chiplets.
-///
-/// \param[in] i_bias This is a signed bias used to obtain the voltage Pstate,
-/// <em> in addition to the \a undervolting_bias already built into the Pstate
-/// table </em>. The iVRM information sent with the Global Actual Pstate comes
-/// from the \a pstate - \a undervolting_bias + \a bias entry of the Pstate
-/// table.
-///
-/// This API can be used in firware Pstate mode to broadcast a Global Actual
-/// Pstate and iVRM settings to the core chiplets. The API also supports
-/// optional under/over-volting. The requested Pstate will be broadcast along
-/// with the voltage information from the associated Pstate table entry.
-///
-/// Under/over-volting is specified by setting the \a bias to a non-0
-/// (signed) value. For example, to undervfolt by one Pstate (if possible),
-/// call the API with \a bias = -1.
-///
-/// This API always waits for the Global Pstate Machine to quiesce before
-/// proceeding with the Global Actual broadcast. Therefore it can only be
-/// called from thread mode, or from a non-thread mode guaranteed by the
-/// caller to have quiesced.
-///
-/// \note The application can use the _gpsm_broadcast_global_actual() API for
-/// complete control over the information transmitted to the cores.
-///
-/// The following return codes are not considered errors:
-///
-/// \retval 0 Success
-///
-/// \retval -GPST_PSTATE_CLIPPED_HIGH_GPSM_BGA The requested Pstate does not
-/// exist in the table. The maximum Pstate entry in the table has been
-/// broadcast as the voltage Pstate.
-///
-/// \retval -GPST_PSTATE_CLIPPED_LOW_GPSM_BGA The requested Pstate does not
-/// exist in the table. The minimum Pstate entry in the table has been
-/// broadcast as the voltage Pstate.
-///
-/// The following return codes are considered errors:
-///
-/// \retval -GPSM_INVALID_OBJECT The Global Pstate Table is either null (0) or
-/// otherwise invalid.
-///
-/// \retval -GPSM_INVALID_ARGUMENT One or more arguments are invalid or
-/// inconsistent in some way.
-///
-/// \retval -GPSM_ILLEGAL_MODE_BGA The PMC is not in firmware pstate mode.
-///
-/// This API may also return errors from the SSX semaphore operations that
-/// implement the wait for quiescence.
-
-int
-gpsm_broadcast_global_actual(const GlobalPstateTable* i_gpst,
- const Pstate i_pstate,
- const int i_bias)
-{
- int rc, bias_rc, entry_rc;
- gpst_entry_t entry;
- Pstate voltage_pstate;
-
- do {
-
- if (!gpsm_fw_mode_p()) {
- rc = GPSM_ILLEGAL_MODE_BGA;
- break;
- }
-
- // Bias the pstate, fetch the Pstate entry, quiesce and broadcast.
- // bias_pstate() only returns saturation warnings. These are turned
- // into bounds warnings if necessary (indicating that the Pstate
- // saturated but the PMAX or PMIN was also a legal entry in the
- // table).
-
- bias_rc = bias_pstate(i_pstate, i_bias, &voltage_pstate);
- entry_rc = gpst_entry(i_gpst, voltage_pstate, 0, &entry);
- if (entry_rc &&
- (entry_rc != -GPST_PSTATE_CLIPPED_LOW_GPST_ENTRY) &&
- (entry_rc != -GPST_PSTATE_CLIPPED_HIGH_GPST_ENTRY)) {
- rc = entry_rc;
- break;
- }
-
- rc = gpsm_quiesce();
- if (rc) break;
-
- _gpsm_broadcast_global_actual(i_pstate, entry);
-
- if (entry_rc != 0) {
- rc = entry_rc;
- } else if (bias_rc == -PSTATE_OVERFLOW_BIAS_PS) {
- rc = -GPST_PSTATE_CLIPPED_HIGH_GPSM_BGA;
- } else if (bias_rc == -PSTATE_UNDERFLOW_BIAS_PS) {
- rc = -GPST_PSTATE_CLIPPED_LOW_GPSM_BGA;
- }
- } while (0);
-
- return rc;
-}
-
-
OpenPOWER on IntegriCloud