ARM platforms: Add support for MT bit in MPIDR

This patch modifies some of the functions in ARM platform layer to cater
for the case when multi-threading `MT` is set in MPIDR. A new build flag
`ARM_PLAT_MT` is added, and when enabled, the functions accessing MPIDR
now assume that the `MT` bit is set for the platform and access the bit
fields accordingly.

Also, a new API plat_arm_get_cpu_pe_count is added when `ARM_PLAT_MT` is
enabled, returning the PE count within the physical cpu corresponding to
`mpidr`.

Change-Id: I04ccf212ac3054a60882761f4087bae299af13cb
Signed-off-by: Summer Qin <summer.qin@arm.com>
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 4628a43..204ae4c 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -90,6 +90,11 @@
 $(eval $(call assert_boolean,ARM_BL31_IN_DRAM))
 $(eval $(call add_define,ARM_BL31_IN_DRAM))
 
+# Process ARM_PLAT_MT flag
+ARM_PLAT_MT			:=	0
+$(eval $(call assert_boolean,ARM_PLAT_MT))
+$(eval $(call add_define,ARM_PLAT_MT))
+
 # Enable PSCI_STAT_COUNT/RESIDENCY APIs on ARM platforms
 ENABLE_PSCI_STAT		:=	1
 ENABLE_PMF			:=	1
diff --git a/plat/arm/common/arm_topology.c b/plat/arm/common/arm_topology.c
index 4430b13..3c95263 100644
--- a/plat/arm/common/arm_topology.c
+++ b/plat/arm/common/arm_topology.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -40,14 +40,26 @@
 int arm_check_mpidr(u_register_t mpidr)
 {
 	unsigned int cluster_id, cpu_id;
+	uint64_t valid_mask;
 
-	mpidr &= MPIDR_AFFINITY_MASK;
+#if ARM_PLAT_MT
+	unsigned int pe_id;
 
-	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
-		return -1;
-
+	valid_mask = ~(MPIDR_AFFLVL_MASK |
+			(MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT) |
+			(MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT));
+	cluster_id = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	pe_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+#else
+	valid_mask = ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK);
 	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
 	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+#endif /* ARM_PLAT_MT */
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+	if (mpidr & valid_mask)
+		return -1;
 
 	if (cluster_id >= PLAT_ARM_CLUSTER_COUNT)
 		return -1;
@@ -57,5 +69,10 @@
 	if (cpu_id >= plat_arm_get_cluster_core_count(mpidr))
 		return -1;
 
+#if ARM_PLAT_MT
+	if (pe_id >= plat_arm_get_cpu_pe_count(mpidr))
+		return -1;
+#endif /* ARM_PLAT_MT */
+
 	return 0;
 }