diff --git a/docs/user-guide.md b/docs/user-guide.md
index c6c8e19b135d4c979f97620bd2ee670f125ab5cd..2770b2cd583bffe597f7a9e35448313f9e751f7b 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -197,6 +197,12 @@ performed.
     by the interrupt management framework. Default is 2 (that is, version 2.0).
     This build option is deprecated.
 
+*   `ARM_PLAT_MT`: This flag determines whether the ARM platform layer has to
+    cater for the multi-threading `MT` bit when accessing MPIDR. When this
+    flag is set, the functions which deal with MPIDR assume that the `MT` bit
+    in MPIDR is set and access the bit-fields in MPIDR accordingly. Default
+    value of this flag is 0.
+
 *   `ASM_ASSERTION`: This flag determines whether the assertion checks within
     assembly source files are enabled or not. This option defaults to the
     value of `DEBUG` - that is, by default this is only enabled for a debug
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index bc492b281418ec71878b8406ed03c68974e1222e..234ceeba3168fe490e86f98e595f856a82a1dc00 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -46,6 +46,7 @@
 /*******************************************************************************
  * MPIDR macros
  ******************************************************************************/
+#define MPIDR_MT_MASK		(1 << 24)
 #define MPIDR_CPU_MASK		MPIDR_AFFLVL_MASK
 #define MPIDR_CLUSTER_MASK	(MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS)
 #define MPIDR_AFFINITY_BITS	8
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index f1ad9bb421b04b623ff3ceb7c5607f7e6bd24e3c..a2c736c9903bb7ff50e621ba9ddebc68aa9c616c 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -50,6 +50,7 @@
 /*******************************************************************************
  * MPIDR macros
  ******************************************************************************/
+#define MPIDR_MT_MASK		(1 << 24)
 #define MPIDR_CPU_MASK		MPIDR_AFFLVL_MASK
 #define MPIDR_CLUSTER_MASK	MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS
 #define MPIDR_AFFINITY_BITS	8
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 0b57ba81590870506e3d6ecbc45a1a6ac3952a16..b24af78d9442b7a921acba449261238d8208ef39 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -203,6 +203,10 @@ void plat_arm_interconnect_init(void);
 void plat_arm_interconnect_enter_coherency(void);
 void plat_arm_interconnect_exit_coherency(void);
 
+#if ARM_PLAT_MT
+unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr);
+#endif
+
 #if LOAD_IMAGE_V2
 /*
  * This function is called after loading SCP_BL2 image and it is used to perform
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index e918e306a694c704b2a9609da0580e2bf5c9366d..891e2fbd46f950bf85797fc11873da07e88d19a5 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -90,6 +90,11 @@ ARM_BL31_IN_DRAM		:=	0
 $(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 4430b139991cdbe1bbf20d540ca1705a5c32cf2c..3c952636a47f76bb22b541ce5eedb85e07d9131e 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 (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
-		return -1;
+#if ARM_PLAT_MT
+	unsigned int pe_id;
 
+	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 @@ int arm_check_mpidr(u_register_t mpidr)
 	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;
 }
diff --git a/plat/arm/css/common/css_topology.c b/plat/arm/css/common/css_topology.c
index d5f0275a8e04389f802ea8f6698ec15cd3ea3eee..9c86f8939f60e181157bce4bc3fbea3b003105bd 100644
--- a/plat/arm/css/common/css_topology.c
+++ b/plat/arm/css/common/css_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:
@@ -30,6 +30,10 @@
 
 #include <plat_arm.h>
 
+#if ARM_PLAT_MT
+#pragma weak plat_arm_get_cpu_pe_count
+#endif
+
 /******************************************************************************
  * This function implements a part of the critical interface between the psci
  * generic layer and the platform that allows the former to query the platform
@@ -43,3 +47,14 @@ int plat_core_pos_by_mpidr(u_register_t mpidr)
 
 	return -1;
 }
+
+#if ARM_PLAT_MT
+/******************************************************************************
+ * This function returns the PE count within the physical cpu corresponding to
+ * `mpidr`. Now one cpu only have one thread, so just return 1.
+ *****************************************************************************/
+unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr)
+{
+	return 1;
+}
+#endif /* ARM_PLAT_MT */
diff --git a/plat/arm/css/drivers/scpi/css_scpi.c b/plat/arm/css/drivers/scpi/css_scpi.c
index 65ae978f867781208d0f40edeac3aba0eea5838d..7c5c5789a53dfaafdfe785b8fd2af9d0fac37a78 100644
--- a/plat/arm/css/drivers/scpi/css_scpi.c
+++ b/plat/arm/css/drivers/scpi/css_scpi.c
@@ -150,8 +150,18 @@ void scpi_set_css_power_state(unsigned int mpidr,
 	uint32_t state = 0;
 	uint32_t *payload_addr;
 
+#if ARM_PLAT_MT
+	/*
+	 * The current SCPI driver only caters for single-threaded platforms.
+	 * Hence we ignore the thread ID (which is always 0) for such platforms.
+	 */
+	state |= (mpidr >> MPIDR_AFF1_SHIFT) & 0x0f;	/* CPU ID */
+	state |= ((mpidr >> MPIDR_AFF2_SHIFT) & 0x0f) << 4;	/* Cluster ID */
+#else
 	state |= mpidr & 0x0f;	/* CPU ID */
 	state |= (mpidr & 0xf00) >> 4;	/* Cluster ID */
+#endif /* ARM_PLAT_MT */
+
 	state |= cpu_state << 8;
 	state |= cluster_state << 12;
 	state |= css_state << 16;