summaryrefslogtreecommitdiff
path: root/plat/nvidia
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2017-04-18 11:22:01 -0700
committerVarun Wadekar <vwadekar@nvidia.com>2017-05-01 15:36:44 -0700
commit7c1d43420697e39e5094b24cf7b4fb218e6edce7 (patch)
tree431700c5537e4b4d35beb214035c977e872ea621 /plat/nvidia
parent14a1c0edf06bfe832ab7ca2d07bcc0547ddf40d5 (diff)
Tegra210: implement 'get_target_pwr_state' handler
This patch implements the handler to calculate the cluster and system power states for the Tegra210 SoC. The power states returned by this handler are used by the PSCI library to decide cache maintenance operations - cluster v cpu. Change-Id: I93e4139d4cd8a086b51f328e9a76e91428ebcdab Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Diffstat (limited to 'plat/nvidia')
-rw-r--r--plat/nvidia/tegra/soc/t210/plat_psci_handlers.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index 05028a1f..91a13e8c 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -100,6 +100,39 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state,
return PSCI_E_SUCCESS;
}
+/*******************************************************************************
+ * 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,
+ unsigned int ncpu)
+{
+ plat_local_state_t target = *states;
+ int cpu = plat_my_core_pos();
+ int core_pos = read_mpidr() & MPIDR_CPU_MASK;
+
+ /* get the power state at this level */
+ if (lvl == MPIDR_AFFLVL1)
+ target = *(states + core_pos);
+ if (lvl == MPIDR_AFFLVL2)
+ target = *(states + cpu);
+
+ /* Cluster idle/power-down */
+ if ((lvl == MPIDR_AFFLVL1) && ((target == PSTATE_ID_CLUSTER_IDLE) ||
+ (target == PSTATE_ID_CLUSTER_POWERDN))) {
+ return target;
+ }
+
+ /* System Suspend */
+ if (((lvl == MPIDR_AFFLVL2) || (lvl == MPIDR_AFFLVL1)) &&
+ (target == PSTATE_ID_SOC_POWERDN))
+ return PSTATE_ID_SOC_POWERDN;
+
+ /* default state */
+ return PSCI_LOCAL_STATE_RUN;
+}
+
int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
{
u_register_t mpidr = read_mpidr();
@@ -121,14 +154,14 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
} else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) {
- assert(stateid_afflvl0 == PLAT_MAX_OFF_STATE);
+ assert(stateid_afflvl0 == PSTATE_ID_CLUSTER_IDLE);
/* Prepare for cluster idle */
tegra_fc_cluster_idle(mpidr);
} else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_POWERDN) {
- assert(stateid_afflvl0 == PLAT_MAX_OFF_STATE);
+ assert(stateid_afflvl0 == PSTATE_ID_CLUSTER_POWERDN);
/* Prepare for cluster powerdn */
tegra_fc_cluster_powerdn(mpidr);