PSCI: Migrate ARM reference platforms to new platform API

This patch migrates ARM reference platforms, Juno and FVP, to the new platform
API mandated by the new PSCI power domain topology and composite power state
frameworks. The platform specific makefiles now exports the build flag
ENABLE_PLAT_COMPAT=0 to disable the platform compatibility layer.

Change-Id: I3040ed7cce446fc66facaee9c67cb54a8cd7ca29
diff --git a/plat/arm/common/aarch64/arm_helpers.S b/plat/arm/common/aarch64/arm_helpers.S
index 25b67f3..daf08fa 100644
--- a/plat/arm/common/aarch64/arm_helpers.S
+++ b/plat/arm/common/aarch64/arm_helpers.S
@@ -30,10 +30,36 @@
 #include <asm_macros.S>
 #include <platform_def.h>
 
-
+	.weak	plat_arm_calc_core_pos
+	.weak	plat_my_core_pos
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
 
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *  This function uses the plat_arm_calc_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	plat_arm_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_arm_calc_core_pos(uint64_t mpidr)
+	 *  Helper function to calculate the core position.
+	 *  With this function: CorePos = (ClusterId * 4) +
+	 *  				  CoreId
+	 * -----------------------------------------------------
+	 */
+func plat_arm_calc_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc plat_arm_calc_core_pos
 
 	/* ---------------------------------------------
 	 * int plat_crash_console_init(void)
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 7e8856b..3fda2ef 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -226,9 +226,6 @@
 
 	/* Initialize power controller before setting up topology */
 	plat_arm_pwrc_setup();
-
-	/* Topologies are best known to the platform. */
-	plat_arm_topology_setup();
 }
 
 void bl31_platform_setup(void)
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index bcc3833..eb2f750 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -83,7 +83,8 @@
 				plat/arm/common/arm_security.c			\
 				plat/arm/common/arm_topology.c			\
 				plat/common/plat_gic.c				\
-				plat/common/aarch64/platform_mp_stack.S
+				plat/common/aarch64/platform_mp_stack.S		\
+				plat/common/aarch64/plat_psci_common.c
 
 ifneq (${TRUSTED_BOARD_BOOT},0)
 
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 67c2b73..3f47309 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -33,49 +33,37 @@
 #include <errno.h>
 #include <psci.h>
 
-
 /*******************************************************************************
- * ARM standard platform utility function which is used to determine if any
- * platform actions should be performed for the specified affinity instance
- * given its state. Nothing needs to be done if the 'state' is not off or if
- * this is not the highest affinity level which will enter the 'state'.
+ * ARM standard platform handler called to check the validity of the power state
+ * parameter.
  ******************************************************************************/
-int32_t arm_do_affinst_actions(unsigned int afflvl, unsigned int state)
+int arm_validate_power_state(unsigned int power_state,
+			    psci_power_state_t *req_state)
 {
-	unsigned int max_phys_off_afflvl;
+	int pstate = psci_get_pstate_type(power_state);
+	int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+	int i;
 
-	assert(afflvl <= MPIDR_AFFLVL1);
+	assert(req_state);
 
-	if (state != PSCI_STATE_OFF)
-		return -EAGAIN;
+	if (pwr_lvl > PLAT_MAX_PWR_LVL)
+		return PSCI_E_INVALID_PARAMS;
 
-	/*
-	 * Find the highest affinity level which will be suspended and postpone
-	 * all the platform specific actions until that level is hit.
-	 */
-	max_phys_off_afflvl = psci_get_max_phys_off_afflvl();
-	assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
-	if (afflvl != max_phys_off_afflvl)
-		return -EAGAIN;
-
-	return 0;
-}
-
-/*******************************************************************************
- * ARM standard platform handler called to check the validity of the power state
- * parameter.
- ******************************************************************************/
-int arm_validate_power_state(unsigned int power_state)
-{
 	/* Sanity check the requested state */
-	if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) {
+	if (pstate == PSTATE_TYPE_STANDBY) {
 		/*
-		 * It's possible to enter standby only on affinity level 0
-		 * (i.e. a CPU on ARM standard platforms).
-		 * Ignore any other affinity level.
+		 * It's possible to enter standby only on power level 0
+		 * Ignore any other power level.
 		 */
-		if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0)
+		if (pwr_lvl != ARM_PWR_LVL0)
 			return PSCI_E_INVALID_PARAMS;
+
+		req_state->pwr_domain_state[ARM_PWR_LVL0] =
+					ARM_LOCAL_STATE_RET;
+	} else {
+		for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++)
+			req_state->pwr_domain_state[i] =
+					ARM_LOCAL_STATE_OFF;
 	}
 
 	/*
diff --git a/plat/arm/common/arm_topology.c b/plat/arm/common/arm_topology.c
index 94faa9f..cb0bb9c 100644
--- a/plat/arm/common/arm_topology.c
+++ b/plat/arm/common/arm_topology.c
@@ -30,35 +30,49 @@
 
 #include <arch.h>
 #include <psci.h>
+#include <plat_arm.h>
 #include <platform_def.h>
 
-/*
- * Weak definitions use fixed topology. Strong definitions could make topology
- * configurable
- */
-#pragma weak plat_get_aff_count
-#pragma weak plat_get_aff_state
-#pragma weak plat_arm_topology_setup
+#define get_arm_cluster_core_count(mpidr)\
+		(((mpidr) & 0x100) ? PLAT_ARM_CLUSTER1_CORE_COUNT :\
+				PLAT_ARM_CLUSTER0_CORE_COUNT)
 
+/* The power domain tree descriptor which need to be exported by ARM platforms */
+extern const unsigned char arm_power_domain_tree_desc[];
 
-unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr)
-{
-	/* Report 1 (absent) instance at levels higher that the cluster level */
-	if (aff_lvl > MPIDR_AFFLVL1)
-		return 1;
-
-	if (aff_lvl == MPIDR_AFFLVL1)
-		return ARM_CLUSTER_COUNT;
 
-	return mpidr & 0x100 ? PLAT_ARM_CLUSTER1_CORE_COUNT :
-				PLAT_ARM_CLUSTER0_CORE_COUNT;
-}
-
-unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr)
+/*******************************************************************************
+ * This function returns the ARM default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	return aff_lvl <= MPIDR_AFFLVL1 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT;
+	return arm_power_domain_tree_desc;
 }
 
-void plat_arm_topology_setup(void)
+/*******************************************************************************
+ * This function validates an MPIDR by checking whether it falls within the
+ * acceptable bounds. An error code (-1) is returned if an incorrect mpidr
+ * is passed.
+ ******************************************************************************/
+int arm_check_mpidr(u_register_t mpidr)
 {
+	unsigned int cluster_id, cpu_id;
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+
+	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+		return -1;
+
+	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+	if (cluster_id >= ARM_CLUSTER_COUNT)
+		return -1;
+
+	/* Validate cpu_id by checking whether it represents a CPU in
+	   one of the two clusters present on the platform. */
+	if (cpu_id >= get_arm_cluster_core_count(mpidr))
+		return -1;
+
+	return 0;
 }
diff --git a/plat/arm/common/tsp/arm_tsp.mk b/plat/arm/common/tsp/arm_tsp.mk
index fc6bd93..f285f58 100644
--- a/plat/arm/common/tsp/arm_tsp.mk
+++ b/plat/arm/common/tsp/arm_tsp.mk
@@ -31,6 +31,7 @@
 # TSP source files common to ARM standard platforms
 BL32_SOURCES		+=	drivers/arm/gic/arm_gic.c			\
 				drivers/arm/gic/gic_v2.c			\
+				plat/arm/common/arm_topology.c			\
 				plat/arm/common/tsp/arm_tsp_setup.c		\
 				plat/common/aarch64/platform_mp_stack.S		\
 				plat/common/plat_gic.c