summaryrefslogtreecommitdiff
path: root/services/std_svc/psci/psci_stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'services/std_svc/psci/psci_stat.c')
-rw-r--r--services/std_svc/psci/psci_stat.c309
1 files changed, 0 insertions, 309 deletions
diff --git a/services/std_svc/psci/psci_stat.c b/services/std_svc/psci/psci_stat.c
deleted file mode 100644
index 155bbb07..00000000
--- a/services/std_svc/psci/psci_stat.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <assert.h>
-#include <debug.h>
-#include <platform.h>
-#include <platform_def.h>
-#include "psci_private.h"
-
-#ifndef PLAT_MAX_PWR_LVL_STATES
-#define PLAT_MAX_PWR_LVL_STATES 2
-#endif
-
-/* Ticks elapsed in one second by a signal of 1 MHz */
-#define MHZ_TICKS_PER_SEC 1000000
-
-/* Following structure is used for PSCI STAT */
-typedef struct psci_stat {
- u_register_t residency;
- u_register_t count;
-} psci_stat_t;
-
-/*
- * Following is used to keep track of the last cpu
- * that goes to power down in non cpu power domains.
- */
-static int last_cpu_in_non_cpu_pd[PSCI_NUM_NON_CPU_PWR_DOMAINS] = {-1};
-
-/*
- * Following are used to store PSCI STAT values for
- * CPU and non CPU power domains.
- */
-static psci_stat_t psci_cpu_stat[PLATFORM_CORE_COUNT]
- [PLAT_MAX_PWR_LVL_STATES];
-static psci_stat_t psci_non_cpu_stat[PSCI_NUM_NON_CPU_PWR_DOMAINS]
- [PLAT_MAX_PWR_LVL_STATES];
-
-/* Register PMF PSCI service */
-PMF_REGISTER_SERVICE(psci_svc, PMF_PSCI_STAT_SVC_ID,
- PSCI_STAT_TOTAL_IDS, PMF_STORE_ENABLE)
-
-/* The divisor to use to convert raw timestamp into microseconds */
-u_register_t residency_div;
-
-/*
- * This macro calculates the stats residency in microseconds,
- * taking in account the wrap around condition.
- */
-#define calc_stat_residency(_pwrupts, _pwrdnts, _res) \
- do { \
- if (_pwrupts < _pwrdnts) \
- _res = UINT64_MAX - _pwrdnts + _pwrupts;\
- else \
- _res = _pwrupts - _pwrdnts; \
- /* Convert timestamp into microseconds */ \
- _res = _res/residency_div; \
- } while (0)
-
-/*
- * This functions returns the index into the `psci_stat_t` array given the
- * local power state and power domain level. If the platform implements the
- * `get_pwr_lvl_state_idx` pm hook, then that will be used to return the index.
- */
-static int get_stat_idx(plat_local_state_t local_state, int pwr_lvl)
-{
- int idx;
-
- if (psci_plat_pm_ops->get_pwr_lvl_state_idx == NULL) {
- assert(PLAT_MAX_PWR_LVL_STATES == 2);
- if (is_local_state_retn(local_state))
- return 0;
-
- assert(is_local_state_off(local_state));
- return 1;
- }
-
- idx = psci_plat_pm_ops->get_pwr_lvl_state_idx(local_state, pwr_lvl);
- assert((idx >= 0) && (idx < PLAT_MAX_PWR_LVL_STATES));
- return idx;
-}
-
-/*******************************************************************************
- * This function is passed the target local power states for each power
- * domain (state_info) between the current CPU domain and its ancestors until
- * the target power level (end_pwrlvl).
- *
- * Then, for each level (apart from the CPU level) until the 'end_pwrlvl', it
- * updates the `last_cpu_in_non_cpu_pd[]` with last power down cpu id.
- *
- * This function will only be invoked with data cache enabled and while
- * powering down a core.
- ******************************************************************************/
-void psci_stats_update_pwr_down(unsigned int end_pwrlvl,
- const psci_power_state_t *state_info)
-{
- int lvl, parent_idx, cpu_idx = plat_my_core_pos();
-
- assert(end_pwrlvl <= PLAT_MAX_PWR_LVL);
- assert(state_info);
-
- parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
-
- for (lvl = PSCI_CPU_PWR_LVL + 1; lvl <= end_pwrlvl; lvl++) {
-
- /* Break early if the target power state is RUN */
- if (is_local_state_run(state_info->pwr_domain_state[lvl]))
- break;
-
- /*
- * The power domain is entering a low power state, so this is
- * the last CPU for this power domain
- */
- last_cpu_in_non_cpu_pd[parent_idx] = cpu_idx;
-
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
- }
-
-}
-
-/*******************************************************************************
- * This function updates the PSCI STATS(residency time and count) for CPU
- * and NON-CPU power domains.
- * It is called with caches enabled and locks acquired(for NON-CPU domain)
- ******************************************************************************/
-void psci_stats_update_pwr_up(unsigned int end_pwrlvl,
- const psci_power_state_t *state_info,
- unsigned int flags)
-{
- int parent_idx, cpu_idx = plat_my_core_pos();
- int lvl, stat_idx;
- plat_local_state_t local_state;
- unsigned long long pwrup_ts = 0, pwrdn_ts = 0;
- u_register_t residency;
-
- assert(end_pwrlvl <= PLAT_MAX_PWR_LVL);
- assert(state_info);
-
- /* Initialize the residency divisor if not already initialized */
- if (!residency_div) {
- /* Pre-calculate divisor so that it can be directly used to
- convert time-stamp into microseconds */
- residency_div = read_cntfrq_el0() / MHZ_TICKS_PER_SEC;
- assert(residency_div);
- }
-
- /* Get power down time-stamp for current CPU */
- PMF_GET_TIMESTAMP_BY_INDEX(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
- cpu_idx, flags, pwrdn_ts);
-
- /* In the case of 1st power on just return */
- if (!pwrdn_ts)
- return;
-
- /* Get power up time-stamp for current CPU */
- PMF_GET_TIMESTAMP_BY_INDEX(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR,
- cpu_idx, flags, pwrup_ts);
-
- /* Get the index into the stats array */
- local_state = state_info->pwr_domain_state[PSCI_CPU_PWR_LVL];
- stat_idx = get_stat_idx(local_state, PSCI_CPU_PWR_LVL);
-
- /* Calculate stats residency */
- calc_stat_residency(pwrup_ts, pwrdn_ts, residency);
-
- /* Update CPU stats. */
- psci_cpu_stat[cpu_idx][stat_idx].residency += residency;
- psci_cpu_stat[cpu_idx][stat_idx].count++;
-
- /*
- * Check what power domains above CPU were off
- * prior to this CPU powering on.
- */
- parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
- for (lvl = PSCI_CPU_PWR_LVL + 1; lvl <= end_pwrlvl; lvl++) {
- local_state = state_info->pwr_domain_state[lvl];
- if (is_local_state_run(local_state)) {
- /* Break early */
- break;
- }
-
- assert(last_cpu_in_non_cpu_pd[parent_idx] != -1);
-
- /* Get power down time-stamp for last CPU */
- PMF_GET_TIMESTAMP_BY_INDEX(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
- last_cpu_in_non_cpu_pd[parent_idx],
- flags, pwrdn_ts);
-
- /* Initialize back to reset value */
- last_cpu_in_non_cpu_pd[parent_idx] = -1;
-
- /* Get the index into the stats array */
- stat_idx = get_stat_idx(local_state, lvl);
-
- /* Calculate stats residency */
- calc_stat_residency(pwrup_ts, pwrdn_ts, residency);
-
- /* Update non cpu stats */
- psci_non_cpu_stat[parent_idx][stat_idx].residency += residency;
- psci_non_cpu_stat[parent_idx][stat_idx].count++;
-
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
- }
-
-}
-
-/*******************************************************************************
- * This function returns the appropriate count and residency time of the
- * local state for the highest power level expressed in the `power_state`
- * for the node represented by `target_cpu`.
- ******************************************************************************/
-int psci_get_stat(u_register_t target_cpu, unsigned int power_state,
- psci_stat_t *psci_stat)
-{
- int rc, pwrlvl, lvl, parent_idx, stat_idx, target_idx;
- psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
- plat_local_state_t local_state;
-
- /* Validate the target_cpu parameter and determine the cpu index */
- target_idx = plat_core_pos_by_mpidr(target_cpu);
- if (target_idx == -1)
- return PSCI_E_INVALID_PARAMS;
-
- /* Validate the power_state parameter */
- if (!psci_plat_pm_ops->translate_power_state_by_mpidr)
- rc = psci_validate_power_state(power_state, &state_info);
- else
- rc = psci_plat_pm_ops->translate_power_state_by_mpidr(
- target_cpu, power_state, &state_info);
-
- if (rc != PSCI_E_SUCCESS)
- return PSCI_E_INVALID_PARAMS;
-
- /* Find the highest power level */
- pwrlvl = psci_find_target_suspend_lvl(&state_info);
- if (pwrlvl == PSCI_INVALID_PWR_LVL)
- return PSCI_E_INVALID_PARAMS;
-
- /* Get the index into the stats array */
- local_state = state_info.pwr_domain_state[pwrlvl];
- stat_idx = get_stat_idx(local_state, pwrlvl);
-
- if (pwrlvl > PSCI_CPU_PWR_LVL) {
- /* Get the power domain index */
- parent_idx = psci_cpu_pd_nodes[target_idx].parent_node;
- for (lvl = PSCI_CPU_PWR_LVL + 1; lvl < pwrlvl; lvl++)
- parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
-
- /* Get the non cpu power domain stats */
- *psci_stat = psci_non_cpu_stat[parent_idx][stat_idx];
- } else {
- /* Get the cpu power domain stats */
- *psci_stat = psci_cpu_stat[target_idx][stat_idx];
- }
-
- return PSCI_E_SUCCESS;
-}
-
-/* This is the top level function for PSCI_STAT_RESIDENCY SMC. */
-u_register_t psci_stat_residency(u_register_t target_cpu,
- unsigned int power_state)
-{
- psci_stat_t psci_stat;
-
- int rc = psci_get_stat(target_cpu, power_state, &psci_stat);
- if (rc == PSCI_E_SUCCESS)
- return psci_stat.residency;
- else
- return 0;
-}
-
-/* This is the top level function for PSCI_STAT_COUNT SMC. */
-u_register_t psci_stat_count(u_register_t target_cpu,
- unsigned int power_state)
-{
- psci_stat_t psci_stat;
-
- int rc = psci_get_stat(target_cpu, power_state, &psci_stat);
- if (rc == PSCI_E_SUCCESS)
- return psci_stat.count;
- else
- return 0;
-}