Tegra186: reduce complexity for the 'get_target_pwr_state' handler

This patch reduces the code complexity for the platform's 'get_target_pwr_state'
handler, by reducing the number of 'if' conditions and adding helper functions
to calculate power state for the cluster/system.

Tested with 'pmccabe'

Change-Id: I32fa4c814bd97f620f2003fa39f1bfceae563771
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
This commit is contained in:
Varun Wadekar 2017-05-24 08:47:15 -07:00
parent fcf23a1419
commit 4e1830a992
1 changed files with 66 additions and 44 deletions

View File

@ -20,6 +20,7 @@
#include <mce.h> #include <mce.h>
#include <smmu.h> #include <smmu.h>
#include <stdbool.h>
#include <t18x_ari.h> #include <t18x_ari.h>
#include <tegra_private.h> #include <tegra_private.h>
@ -161,31 +162,41 @@ int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
} }
/******************************************************************************* /*******************************************************************************
* Platform handler to calculate the proper target power level at the * Helper function to check if this is the last ON CPU in the cluster
* specified affinity level
******************************************************************************/ ******************************************************************************/
plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, static bool tegra_last_cpu_in_cluster(const plat_local_state_t *states,
const plat_local_state_t *states,
uint32_t ncpu) uint32_t ncpu)
{ {
plat_local_state_t target = *states; plat_local_state_t target;
uint32_t pos = 0; bool last_on_cpu = true;
plat_local_state_t result = PSCI_LOCAL_STATE_RUN; uint32_t num_cpus = ncpu, pos = 0;
uint32_t cpu = plat_my_core_pos(), num_cpu = ncpu;
int32_t ret, cluster_powerdn = 1; do {
uint64_t core_pos = read_mpidr() & (uint64_t)MPIDR_CPU_MASK; target = states[pos];
if (target != PLAT_MAX_OFF_STATE) {
last_on_cpu = false;
}
--num_cpus;
pos++;
} while (num_cpus != 0U);
return last_on_cpu;
}
/*******************************************************************************
* Helper function to get target power state for the cluster
******************************************************************************/
static plat_local_state_t tegra_get_afflvl1_pwr_state(const plat_local_state_t *states,
uint32_t ncpu)
{
uint32_t core_pos = (uint32_t)read_mpidr() & (uint32_t)MPIDR_CPU_MASK;
uint32_t cpu = plat_my_core_pos();
int32_t ret;
plat_local_state_t target = states[core_pos];
mce_cstate_info_t cstate_info = { 0 }; mce_cstate_info_t cstate_info = { 0 };
/* get the power state at this level */
if (lvl == (uint32_t)MPIDR_AFFLVL1) {
target = states[core_pos];
}
if (lvl == (uint32_t)MPIDR_AFFLVL2) {
target = states[cpu];
}
/* CPU suspend */ /* CPU suspend */
if ((lvl == (uint32_t)MPIDR_AFFLVL1) && (target == PSTATE_ID_CORE_POWERDN)) { if (target == PSTATE_ID_CORE_POWERDN) {
/* Program default wake mask */ /* Program default wake mask */
cstate_info.wake_mask = TEGRA186_CORE_WAKE_MASK; cstate_info.wake_mask = TEGRA186_CORE_WAKE_MASK;
@ -194,41 +205,32 @@ plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
/* Check if CCx state is allowed. */ /* Check if CCx state is allowed. */
ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED, ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED,
TEGRA_ARI_CORE_C7, tegra_percpu_data[cpu].wake_time, (uint64_t)TEGRA_ARI_CORE_C7,
tegra_percpu_data[cpu].wake_time,
0U); 0U);
if (ret != 0) { if (ret == 0) {
result = PSTATE_ID_CORE_POWERDN; target = PSCI_LOCAL_STATE_RUN;
} }
} }
/* CPU off */ /* CPU off */
if ((lvl == (uint32_t)MPIDR_AFFLVL1) && (target == PLAT_MAX_OFF_STATE)) { if (target == PLAT_MAX_OFF_STATE) {
/* find out the number of ON cpus in the cluster */
do {
target = states[pos];
if (target != PLAT_MAX_OFF_STATE) {
cluster_powerdn = 0;
}
--num_cpu;
pos++;
} while (num_cpu != 0U);
/* Enable cluster powerdn from last CPU in the cluster */ /* Enable cluster powerdn from last CPU in the cluster */
if (cluster_powerdn != 0) { if (tegra_last_cpu_in_cluster(states, ncpu)) {
/* Enable CC7 state and turn off wake mask */ /* Enable CC7 state and turn off wake mask */
cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7; cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7;
cstate_info.update_wake_mask = 1; cstate_info.update_wake_mask = 1;
mce_update_cstate_info(&cstate_info); mce_update_cstate_info(&cstate_info);
/* Check if CCx state is allowed. */ /* Check if CCx state is allowed. */
ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED, ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED,
TEGRA_ARI_CORE_C7, (uint64_t)TEGRA_ARI_CORE_C7,
MCE_CORE_SLEEP_TIME_INFINITE, MCE_CORE_SLEEP_TIME_INFINITE,
0U); 0U);
if (ret != 0) { if (ret == 0) {
result = PSTATE_ID_CORE_POWERDN; target = PSCI_LOCAL_STATE_RUN;
} }
} else { } else {
@ -236,17 +238,37 @@ plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
/* Turn off wake_mask */ /* Turn off wake_mask */
cstate_info.update_wake_mask = 1; cstate_info.update_wake_mask = 1;
mce_update_cstate_info(&cstate_info); mce_update_cstate_info(&cstate_info);
target = PSCI_LOCAL_STATE_RUN;
} }
} }
return target;
}
/*******************************************************************************
* Platform handler to calculate the proper target power level at the
* specified affinity level
******************************************************************************/
plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
const plat_local_state_t *states,
uint32_t ncpu)
{
plat_local_state_t target = PSCI_LOCAL_STATE_RUN;
int cpu = plat_my_core_pos();
/* System Suspend */ /* System Suspend */
if (((lvl == (uint32_t)MPIDR_AFFLVL2) || (lvl == (uint32_t)MPIDR_AFFLVL1)) && if ((lvl == (uint32_t)MPIDR_AFFLVL2) &&
(target == PSTATE_ID_SOC_POWERDN)) { (states[cpu] == PSTATE_ID_SOC_POWERDN)) {
result = PSTATE_ID_SOC_POWERDN; target = PSTATE_ID_SOC_POWERDN;
} }
/* default state */ /* CPU off, CPU suspend */
return result; if (lvl == (uint32_t)MPIDR_AFFLVL1) {
target = tegra_get_afflvl1_pwr_state(states, ncpu);
}
/* target cluster/system state */
return target;
} }
int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)