summaryrefslogtreecommitdiff
path: root/plat/arm/css/common/css_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/arm/css/common/css_pm.c')
-rw-r--r--plat/arm/css/common/css_pm.c109
1 files changed, 47 insertions, 62 deletions
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index 3f468570..6d6646e0 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -30,7 +30,6 @@
#include <arch_helpers.h>
#include <assert.h>
-#include <arm_gic.h>
#include <cassert.h>
#include <cci.h>
#include <css_pm.h>
@@ -41,6 +40,12 @@
#include <platform_def.h>
#include "css_scpi.h"
+/* Macros to read the CSS power domain state */
+#define CSS_CORE_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL0]
+#define CSS_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL1]
+#define CSS_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) ?\
+ (state)->pwr_domain_state[ARM_PWR_LVL2] : 0)
+
/* Allow CSS platforms to override `plat_arm_psci_pm_ops` */
#pragma weak plat_arm_psci_pm_ops
@@ -93,51 +98,39 @@ int css_pwr_domain_on(u_register_t mpidr)
return PSCI_E_SUCCESS;
}
-/*******************************************************************************
- * Handler called when a power level has just been powered on after
- * being turned off earlier. The target_state encodes the low power state that
- * each level has woken up from.
- ******************************************************************************/
-void css_pwr_domain_on_finish(const psci_power_state_t *target_state)
+static void css_pwr_domain_on_finisher_common(
+ const psci_power_state_t *target_state)
{
- assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_OFF);
-
- if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) {
- /*
- * Perform system initialization if woken up from system
- * suspend.
- */
- if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
- ARM_LOCAL_STATE_OFF)
- arm_system_pwr_domain_resume();
- }
+ assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
/*
* Perform the common cluster specific operations i.e enable coherency
* if this cluster was off.
*/
- if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
- ARM_LOCAL_STATE_OFF)
+ if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+/*******************************************************************************
+ * Handler called when a power level has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from. This handler would never be invoked with
+ * the system power domain uninitialized as either the primary would have taken
+ * care of it as part of cold boot or the first core awakened from system
+ * suspend would have already initialized it.
+ ******************************************************************************/
+void css_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* Assert that the system power domain need not be initialized */
+ assert(CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_RUN);
+ css_pwr_domain_on_finisher_common(target_state);
- if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) {
- /*
- * Skip GIC CPU interface and per-CPU Distributor interface
- * setups if woken up from system suspend as it is done as
- * part of css_system_pwr_domain_resume().
- */
- if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
- ARM_LOCAL_STATE_OFF)
- return;
- }
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_arm_gic_pcpu_init();
/* Enable the gic cpu interface */
- arm_gic_cpuif_setup();
-
- /* todo: Is this setup only needed after a cold boot? */
- arm_gic_pcpu_distif_setup();
+ plat_arm_gic_cpuif_enable();
}
/*******************************************************************************
@@ -152,21 +145,14 @@ static void css_power_down_common(const psci_power_state_t *target_state)
uint32_t system_state = scpi_power_on;
/* Prevent interrupts from spuriously waking up this cpu */
- arm_gic_cpuif_deactivate();
-
- if (PLAT_MAX_PWR_LVL > ARM_PWR_LVL1) {
- /*
- * Check if power down at system power domain level is
- * requested.
- */
- if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
- ARM_LOCAL_STATE_OFF)
+ plat_arm_gic_cpuif_disable();
+
+ /* Check if power down at system power domain level is requested */
+ if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
system_state = scpi_power_retention;
- }
/* Cluster is to be turned off, so disable coherency */
- if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
- ARM_LOCAL_STATE_OFF) {
+ if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
cluster_state = scpi_power_off;
}
@@ -187,9 +173,7 @@ static void css_power_down_common(const psci_power_state_t *target_state)
******************************************************************************/
void css_pwr_domain_off(const psci_power_state_t *target_state)
{
- assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_OFF);
-
+ assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
css_power_down_common(target_state);
}
@@ -200,16 +184,13 @@ void css_pwr_domain_off(const psci_power_state_t *target_state)
void css_pwr_domain_suspend(const psci_power_state_t *target_state)
{
/*
- * Juno has retention only at cpu level. Just return
+ * CSS currently supports retention only at cpu level. Just return
* as nothing is to be done for retention.
*/
- if (target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_RET)
+ if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET)
return;
- assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_OFF);
-
+ assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
css_power_down_common(target_state);
}
@@ -223,14 +204,18 @@ void css_pwr_domain_suspend(const psci_power_state_t *target_state)
void css_pwr_domain_suspend_finish(
const psci_power_state_t *target_state)
{
- /*
- * Return as nothing is to be done on waking up from retention.
- */
- if (target_state->pwr_domain_state[ARM_PWR_LVL0] ==
- ARM_LOCAL_STATE_RET)
+ /* Return as nothing is to be done on waking up from retention. */
+ if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET)
return;
- css_pwr_domain_on_finish(target_state);
+ /* Perform system domain restore if woken up from system suspend */
+ if (CSS_SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
+ arm_system_pwr_domain_resume();
+ else
+ /* Enable the gic cpu interface */
+ plat_arm_gic_cpuif_enable();
+
+ css_pwr_domain_on_finisher_common(target_state);
}
/*******************************************************************************