aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/arch/aarch32/arch.h10
-rw-r--r--include/arch/aarch32/arch_helpers.h5
-rw-r--r--include/arch/aarch64/arch.h10
-rw-r--r--include/arch/aarch64/arch_helpers.h6
-rw-r--r--plat/arm/board/fvp/fvp_pm.c19
-rw-r--r--plat/arm/css/common/css_pm.c22
6 files changed, 71 insertions, 1 deletions
diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h
index 8492b3ea4b..a11d55e08e 100644
--- a/include/arch/aarch32/arch.h
+++ b/include/arch/aarch32/arch.h
@@ -701,4 +701,14 @@
#define AMEVTYPER1E p15, 0, c13, c15, 6
#define AMEVTYPER1F p15, 0, c13, c15, 7
+/*******************************************************************************
+ * Definitions for DynamicIQ Shared Unit registers
+ ******************************************************************************/
+#define CLUSTERPWRDN p15, 0, c15, c3, 6
+
+/* CLUSTERPWRDN register definitions */
+#define DSU_CLUSTER_PWR_OFF 0
+#define DSU_CLUSTER_PWR_ON 1
+#define DSU_CLUSTER_PWR_MASK U(1)
+
#endif /* ARCH_H */
diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h
index a90b2a54cf..eed56e2192 100644
--- a/include/arch/aarch32/arch_helpers.h
+++ b/include/arch/aarch32/arch_helpers.h
@@ -336,6 +336,11 @@ DEFINE_DCOP_PARAM_FUNC(cvac, DCCIMVAC)
DEFINE_DCOP_PARAM_FUNC(cvac, DCCMVAC)
#endif
+/*
+ * DynamIQ Shared Unit power management
+ */
+DEFINE_COPROCR_RW_FUNCS(clusterpwrdn, CLUSTERPWRDN)
+
/* Previously defined accessor functions with incomplete register names */
#define dsb() dsbsy()
#define dmb() dmbsy()
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 19dd8c5e38..e45a594c56 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -947,4 +947,14 @@
#define RGSR_EL1 S3_0_C1_C0_5
#define GCR_EL1 S3_0_C1_C0_6
+/*******************************************************************************
+ * Definitions for DynamicIQ Shared Unit registers
+ ******************************************************************************/
+#define CLUSTERPWRDN_EL1 S3_0_c15_c3_6
+
+/* CLUSTERPWRDN_EL1 register definitions */
+#define DSU_CLUSTER_PWR_OFF 0
+#define DSU_CLUSTER_PWR_ON 1
+#define DSU_CLUSTER_PWR_MASK U(1)
+
#endif /* ARCH_H */
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 669a1403c4..9cd1ae5153 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -520,6 +520,9 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(tfsr_el1, TFSR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(rgsr_el1, RGSR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1)
+/* DynamIQ Shared Unit power management */
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1)
+
#define IS_IN_EL(x) \
(GET_EL(read_CurrentEl()) == MODE_EL##x)
@@ -582,4 +585,7 @@ static inline uint64_t el_implemented(unsigned int el)
#define read_cpacr() read_cpacr_el1()
#define write_cpacr(_v) write_cpacr_el1(_v)
+#define read_clusterpwrdn() read_clusterpwrdn_el1()
+#define write_clusterpwrdn(_v) write_clusterpwrdn_el1(_v)
+
#endif /* ARCH_HELPERS_H */
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index c47d837796..333d89288a 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -64,6 +64,25 @@ static void fvp_cluster_pwrdwn_common(void)
/* Disable coherency if this cluster is to be turned off */
fvp_interconnect_disable();
+#if HW_ASSISTED_COHERENCY
+ uint32_t reg;
+
+ /*
+ * If we have determined this core to be the last man standing and we
+ * intend to power down the cluster proactively, we provide a hint to
+ * the power controller that cluster power is not required when all
+ * cores are powered down.
+ * Note that this is only an advisory to power controller and is supported
+ * by SoCs with DynamIQ Shared Units only.
+ */
+ reg = read_clusterpwrdn();
+
+ /* Clear and set bit 0 : Cluster power not required */
+ reg &= ~DSU_CLUSTER_PWR_MASK;
+ reg |= DSU_CLUSTER_PWR_OFF;
+ write_clusterpwrdn(reg);
+#endif
+
/* Program the power controller to turn the cluster off */
fvp_pwrc_write_pcoffr(mpidr);
}
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index af69c6fb46..8e74526346 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -124,8 +124,28 @@ static void css_power_down_common(const psci_power_state_t *target_state)
plat_arm_gic_cpuif_disable();
/* Cluster is to be turned off, so disable coherency */
- if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
+ if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
plat_arm_interconnect_exit_coherency();
+
+#if HW_ASSISTED_COHERENCY
+ uint32_t reg;
+
+ /*
+ * If we have determined this core to be the last man standing and we
+ * intend to power down the cluster proactively, we provide a hint to
+ * the power controller that cluster power is not required when all
+ * cores are powered down.
+ * Note that this is only an advisory to power controller and is supported
+ * by SoCs with DynamIQ Shared Units only.
+ */
+ reg = read_clusterpwrdn();
+
+ /* Clear and set bit 0 : Cluster power not required */
+ reg &= ~DSU_CLUSTER_PWR_MASK;
+ reg |= DSU_CLUSTER_PWR_OFF;
+ write_clusterpwrdn(reg);
+#endif
+ }
}
/*******************************************************************************