diff options
Diffstat (limited to 'services/std_svc/psci/psci_stat.c')
-rw-r--r-- | services/std_svc/psci/psci_stat.c | 309 |
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; -} |