Merge pull request #773 from dp-arm/dp/fiptool-enhancements

Various fiptool enhancements and bug fixes
diff --git a/common/bl_common.c b/common/bl_common.c
index 193e972..15d5bde 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -315,14 +315,9 @@
 	return io_result;
 }
 
-/*******************************************************************************
- * Generic function to load and authenticate an image. The image is actually
- * loaded by calling the 'load_image()' function. Therefore, it returns the
- * same error codes if the loading operation failed, or -EAUTH if the
- * authentication failed. In addition, this function uses recursion to
- * authenticate the parent images up to the root of trust.
- ******************************************************************************/
-int load_auth_image(unsigned int image_id, image_info_t *image_data)
+static int load_auth_image_internal(unsigned int image_id,
+				    image_info_t *image_data,
+				    int is_parent_image)
 {
 	int rc;
 
@@ -332,7 +327,7 @@
 	/* Use recursion to authenticate parent images */
 	rc = auth_mod_get_parent_id(image_id, &parent_id);
 	if (rc == 0) {
-		rc = load_auth_image(parent_id, image_data);
+		rc = load_auth_image_internal(parent_id, image_data, 1);
 		if (rc != 0) {
 			return rc;
 		}
@@ -351,6 +346,7 @@
 				 (void *)image_data->image_base,
 				 image_data->image_size);
 	if (rc != 0) {
+		/* Authentication error, zero memory and flush it right away. */
 		memset((void *)image_data->image_base, 0x00,
 		       image_data->image_size);
 		flush_dcache_range(image_data->image_base,
@@ -362,13 +358,29 @@
 	 * File has been successfully loaded and authenticated.
 	 * Flush the image to main memory so that it can be executed later by
 	 * any CPU, regardless of cache and MMU state.
+	 * Do it only for child images, not for the parents (certificates).
 	 */
-	flush_dcache_range(image_data->image_base, image_data->image_size);
+	if (!is_parent_image) {
+		flush_dcache_range(image_data->image_base,
+				   image_data->image_size);
+	}
 #endif /* TRUSTED_BOARD_BOOT */
 
 	return 0;
 }
 
+/*******************************************************************************
+ * Generic function to load and authenticate an image. The image is actually
+ * loaded by calling the 'load_image()' function. Therefore, it returns the
+ * same error codes if the loading operation failed, or -EAUTH if the
+ * authentication failed. In addition, this function uses recursion to
+ * authenticate the parent images up to the root of trust.
+ ******************************************************************************/
+int load_auth_image(unsigned int image_id, image_info_t *image_data)
+{
+	return load_auth_image_internal(image_id, image_data, 0);
+}
+
 #else /* LOAD_IMAGE_V2 */
 
 /*******************************************************************************
@@ -494,18 +506,12 @@
 	return io_result;
 }
 
-/*******************************************************************************
- * Generic function to load and authenticate an image. The image is actually
- * loaded by calling the 'load_image()' function. Therefore, it returns the
- * same error codes if the loading operation failed, or -EAUTH if the
- * authentication failed. In addition, this function uses recursion to
- * authenticate the parent images up to the root of trust.
- ******************************************************************************/
-int load_auth_image(meminfo_t *mem_layout,
-		    unsigned int image_id,
-		    uintptr_t image_base,
-		    image_info_t *image_data,
-		    entry_point_info_t *entry_point_info)
+static int load_auth_image_internal(meminfo_t *mem_layout,
+				    unsigned int image_id,
+				    uintptr_t image_base,
+				    image_info_t *image_data,
+				    entry_point_info_t *entry_point_info,
+				    int is_parent_image)
 {
 	int rc;
 
@@ -515,8 +521,8 @@
 	/* Use recursion to authenticate parent images */
 	rc = auth_mod_get_parent_id(image_id, &parent_id);
 	if (rc == 0) {
-		rc = load_auth_image(mem_layout, parent_id, image_base,
-				     image_data, NULL);
+		rc = load_auth_image_internal(mem_layout, parent_id, image_base,
+				     image_data, NULL, 1);
 		if (rc != 0) {
 			return rc;
 		}
@@ -536,6 +542,7 @@
 				 (void *)image_data->image_base,
 				 image_data->image_size);
 	if (rc != 0) {
+		/* Authentication error, zero memory and flush it right away. */
 		memset((void *)image_data->image_base, 0x00,
 		       image_data->image_size);
 		flush_dcache_range(image_data->image_base,
@@ -546,13 +553,34 @@
 	 * File has been successfully loaded and authenticated.
 	 * Flush the image to main memory so that it can be executed later by
 	 * any CPU, regardless of cache and MMU state.
+	 * Do it only for child images, not for the parents (certificates).
 	 */
-	flush_dcache_range(image_data->image_base, image_data->image_size);
+	if (!is_parent_image) {
+		flush_dcache_range(image_data->image_base,
+				   image_data->image_size);
+	}
 #endif /* TRUSTED_BOARD_BOOT */
 
 	return 0;
 }
 
+/*******************************************************************************
+ * Generic function to load and authenticate an image. The image is actually
+ * loaded by calling the 'load_image()' function. Therefore, it returns the
+ * same error codes if the loading operation failed, or -EAUTH if the
+ * authentication failed. In addition, this function uses recursion to
+ * authenticate the parent images up to the root of trust.
+ ******************************************************************************/
+int load_auth_image(meminfo_t *mem_layout,
+		    unsigned int image_id,
+		    uintptr_t image_base,
+		    image_info_t *image_data,
+		    entry_point_info_t *entry_point_info)
+{
+	return load_auth_image_internal(mem_layout, image_id, image_base,
+					image_data, entry_point_info, 0);
+}
+
 #endif /* LOAD_IMAGE_V2 */
 
 /*******************************************************************************
diff --git a/drivers/arm/pl011/aarch32/pl011_console.S b/drivers/arm/pl011/aarch32/pl011_console.S
index 21ed7ab..5b73528 100644
--- a/drivers/arm/pl011/aarch32/pl011_console.S
+++ b/drivers/arm/pl011/aarch32/pl011_console.S
@@ -118,15 +118,15 @@
 1:
 	/* Check if the transmit FIFO is full */
 	ldr	r2, [r1, #UARTFR]
-	tst	r2, #PL011_UARTFR_TXFF_BIT
-	beq	1b
+	tst	r2, #PL011_UARTFR_TXFF
+	bne	1b
 	mov	r2, #0xD
 	str	r2, [r1, #UARTDR]
 2:
 	/* Check if the transmit FIFO is full */
 	ldr	r2, [r1, #UARTFR]
-	tst	r2, #PL011_UARTFR_TXFF_BIT
-	beq	2b
+	tst	r2, #PL011_UARTFR_TXFF
+	bne	2b
 	str	r0, [r1, #UARTDR]
 	bx	lr
 putc_error:
@@ -149,8 +149,8 @@
 1:
 	/* Check if the receive FIFO is empty */
 	ldr	r1, [r0, #UARTFR]
-	tst	r1, #PL011_UARTFR_RXFE_BIT
-	beq	1b
+	tst	r1, #PL011_UARTFR_RXFE
+	bne	1b
 	ldr	r1, [r0, #UARTDR]
 	mov	r0, r1
 	bx	lr
diff --git a/include/common/aarch32/el3_common_macros.S b/include/common/aarch32/el3_common_macros.S
index 0018ea4..50ce952 100644
--- a/include/common/aarch32/el3_common_macros.S
+++ b/include/common/aarch32/el3_common_macros.S
@@ -67,14 +67,6 @@
 	orr	r0, r0, #SCR_SIF_BIT
 	stcopr	r0, SCR
 
-	/* -----------------------------------------------------------------
-	 * Reset those registers that may have architecturally unknown reset
-	 * values
-	 * -----------------------------------------------------------------
-	 */
-	mov	r0, #0
-	stcopr	r0, SDCR
-
 	/* -----------------------------------------------------
 	 * Enable the Asynchronous data abort now that the
 	 * exception vectors have been setup.
diff --git a/include/drivers/emmc.h b/include/drivers/emmc.h
index 5f78dce..4bd7328 100644
--- a/include/drivers/emmc.h
+++ b/include/drivers/emmc.h
@@ -131,21 +131,21 @@
 } emmc_ops_t;
 
 typedef struct emmc_csd {
-	unsigned char		not_used:		1;
-	unsigned char		crc:			7;
-	unsigned char		ecc:			2;
-	unsigned char		file_format:		2;
-	unsigned char		tmp_write_protect:	1;
-	unsigned char		perm_write_protect:	1;
-	unsigned char		copy:			1;
-	unsigned char		file_format_grp:	1;
+	unsigned int 	    not_used:		1;
+	unsigned int   	    crc:			7;
+	unsigned int   	    ecc:			2;
+	unsigned int   	    file_format:		2;
+	unsigned int   	    tmp_write_protect:	1;
+	unsigned int   	    perm_write_protect:	1;
+	unsigned int   	    copy:			1;
+	unsigned int   	    file_format_grp:	1;
 
-	unsigned short		reserved_1:		5;
-	unsigned short		write_bl_partial:	1;
-	unsigned short		write_bl_len:		4;
-	unsigned short		r2w_factor:		3;
-	unsigned short		default_ecc:		2;
-	unsigned short		wp_grp_enable:		1;
+	unsigned int 		reserved_1:		5;
+	unsigned int 		write_bl_partial:	1;
+	unsigned int 		write_bl_len:		4;
+	unsigned int 		r2w_factor:		3;
+	unsigned int 		default_ecc:		2;
+	unsigned int 		wp_grp_enable:		1;
 
 	unsigned int		wp_grp_size:		5;
 	unsigned int		erase_grp_mult:		5;
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index 3c5ab26..170fa84 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -382,8 +382,8 @@
 
 /* Debug register defines. The format is: coproc, opt1, CRn, CRm, opt2 */
 #define HDCR		p15, 4, c1, c1, 1
-#define SDCR		p15, 0, c1, c3, 1
 #define PMCR		p15, 0, c9, c12, 0
+#define CNTHP_CTL	p15, 4, c14, c2, 1
 
 /* GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRn, CRm, opt2 */
 #define ICC_IAR1	p15, 0, c12, c12, 0
diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h
index 0633bca..7955d62 100644
--- a/include/lib/aarch32/arch_helpers.h
+++ b/include/lib/aarch32/arch_helpers.h
@@ -250,6 +250,7 @@
 DEFINE_COPROCR_RW_FUNCS(icc_eoir1_el1, ICC_EOIR1)
 
 DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR)
+DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL)
 DEFINE_COPROCR_READ_FUNC(pmcr, PMCR)
 
 /*
diff --git a/include/lib/aarch32/smcc_macros.S b/include/lib/aarch32/smcc_macros.S
index c80c3e4..4d329f5 100644
--- a/include/lib/aarch32/smcc_macros.S
+++ b/include/lib/aarch32/smcc_macros.S
@@ -109,7 +109,13 @@
 	msr	spsr_und, r9
 	msr	sp_und, r10
 	msr	lr_und, r11
-	msr	spsr, r12
+	/*
+	 * Use the `_fsxc` suffix explicitly to instruct the assembler
+	 * to update all the 32 bits of SPSR. Else, by default, the
+	 * assembler assumes `_fc` suffix which only modifies
+	 * f->[31:24] and c->[7:0] bits of SPSR.
+	 */
+	msr	spsr_fsxc, r12
 
 	/* Restore the rest of the general purpose registers */
 	ldm	r0, {r0-r12}
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 37db031..a013809 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -280,6 +280,8 @@
 DEFINE_SYSREG_READ_FUNC(ctr_el0)
 
 DEFINE_SYSREG_RW_FUNCS(mdcr_el2)
+DEFINE_SYSREG_RW_FUNCS(hstr_el2)
+DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2)
 DEFINE_SYSREG_READ_FUNC(pmcr_el0)
 
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 29fcffe..bc32e40 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -220,4 +220,7 @@
 unsigned int plat_arm_calc_core_pos(u_register_t mpidr);
 const mmap_region_t *plat_arm_get_mmap(void);
 
+/* Allow platform to override psci_pm_ops during runtime */
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops);
+
 #endif /* __PLAT_ARM_H__ */
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index 4a6ca81..489275e 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, 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:
@@ -35,6 +35,12 @@
 #include <psci.h>
 #include <types.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)
+
 int css_pwr_domain_on(u_register_t mpidr);
 void css_pwr_domain_on_finish(const psci_power_state_t *target_state);
 void css_pwr_domain_off(const psci_power_state_t *target_state);
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index 29532e8..51b7759 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -243,6 +243,12 @@
 			 * (5 bits) and HPMN is at offset zero within HDCR.
 			 */
 			write_hdcr((read_pmcr() & PMCR_N_BITS) >> PMCR_N_SHIFT);
+
+			/*
+			 * Reset CNTHP_CTL to disable the EL2 physical timer and
+			 * therefore prevent timer interrupts.
+			 */
+			write_cnthp_ctl(0);
 			isb();
 
 			write_scr(read_scr() & ~SCR_NS_BIT);
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index fadc1db..35380f3 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -269,6 +269,18 @@
 			 */
 			write_mdcr_el2((read_pmcr_el0() & PMCR_EL0_N_BITS)
 					>> PMCR_EL0_N_SHIFT);
+			/*
+			 * Avoid unexpected traps of non-secure access to
+			 * certain system registers at EL1 or lower where
+			 * HSTR_EL2 is not completely reset to zero by the
+			 * hardware - zero the entire register.
+			 */
+			write_hstr_el2(0);
+			/*
+			 * Reset CNTHP_CTL_EL2 to disable the EL2 physical timer
+			 * and therefore prevent timer interrupts.
+			 */
+			write_cnthp_ctl_el2(0);
 		}
 	}
 
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 66c0c3d..139f713 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -327,7 +327,7 @@
  * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
  * platform layer will take care of registering the handlers with PSCI.
  ******************************************************************************/
-const plat_psci_ops_t plat_arm_psci_pm_ops = {
+plat_psci_ops_t plat_arm_psci_pm_ops = {
 	.cpu_standby = fvp_cpu_standby,
 	.pwr_domain_on = fvp_pwr_domain_on,
 	.pwr_domain_off = fvp_pwr_domain_off,
diff --git a/plat/arm/board/juno/juno_pm.c b/plat/arm/board/juno/juno_pm.c
index c355d94..c0fa628 100644
--- a/plat/arm/board/juno/juno_pm.c
+++ b/plat/arm/board/juno/juno_pm.c
@@ -76,7 +76,7 @@
  * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
  * platform will take care of registering the handlers with PSCI.
  ******************************************************************************/
-const plat_psci_ops_t plat_arm_psci_pm_ops = {
+plat_psci_ops_t plat_arm_psci_pm_ops = {
 	.pwr_domain_on			= css_pwr_domain_on,
 	.pwr_domain_on_finish		= css_pwr_domain_on_finish,
 	.pwr_domain_off			= css_pwr_domain_off,
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 1e756a9..d2e682d 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, 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:
@@ -38,8 +38,11 @@
 #include <platform_def.h>
 #include <psci.h>
 
+/* Allow ARM Standard platforms to override this function */
+#pragma weak plat_arm_psci_override_pm_ops
+
 /* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */
-extern const plat_psci_ops_t plat_arm_psci_pm_ops;
+extern plat_psci_ops_t plat_arm_psci_pm_ops;
 
 #if ARM_RECOM_STATE_ID_ENC
 extern unsigned int arm_pm_idle_states[];
@@ -151,6 +154,14 @@
 }
 
 /******************************************************************************
+ * Default definition on ARM standard platforms to override the plat_psci_ops.
+ *****************************************************************************/
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return ops;
+}
+
+/******************************************************************************
  * Helper function to resume the platform from system suspend. Reinitialize
  * the system components which are not in the Always ON power domain.
  * TODO: Unify the platform setup when waking up from cold boot and system
@@ -201,7 +212,7 @@
 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
 				const plat_psci_ops_t **psci_ops)
 {
-	*psci_ops = &plat_arm_psci_pm_ops;
+	*psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops);
 
 	/* Setup mailbox with entry point. */
 	arm_program_trusted_mailbox(sec_entrypoint);
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
index 65e125e..86ba6df 100644
--- a/plat/arm/css/common/css_common.mk
+++ b/plat/arm/css/common/css_common.mk
@@ -41,18 +41,18 @@
 BL1_SOURCES		+=	plat/arm/css/common/css_bl1_setup.c
 
 BL2_SOURCES		+=	plat/arm/css/common/css_bl2_setup.c		\
-				plat/arm/css/common/css_mhu.c			\
-				plat/arm/css/common/css_scpi.c
+				plat/arm/css/drivers/scpi/css_mhu.c		\
+				plat/arm/css/drivers/scpi/css_scpi.c
 
 BL2U_SOURCES		+=	plat/arm/css/common/css_bl2u_setup.c		\
-				plat/arm/css/common/css_mhu.c			\
-				plat/arm/css/common/css_scpi.c
+				plat/arm/css/drivers/scpi/css_mhu.c		\
+				plat/arm/css/drivers/scpi/css_scpi.c
 
-BL31_SOURCES		+=	plat/arm/css/common/css_mhu.c			\
-				plat/arm/css/common/css_pm.c			\
-				plat/arm/css/common/css_scpi.c			\
-				plat/arm/css/common/css_topology.c
-
+BL31_SOURCES		+=	plat/arm/css/common/css_pm.c			\
+				plat/arm/css/common/css_topology.c		\
+				plat/arm/css/drivers/scp/css_pm_scpi.c		\
+				plat/arm/css/drivers/scpi/css_mhu.c		\
+				plat/arm/css/drivers/scpi/css_scpi.c
 
 ifneq (${RESET_TO_BL31},0)
   $(error "Using BL31 as the reset vector is not supported on CSS platforms. \
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index 7607f61..d4dd0af 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -37,13 +37,7 @@
 #include <plat_arm.h>
 #include <platform.h>
 #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)
+#include "../drivers/scp/css_scp.h"
 
 /* Allow CSS platforms to override `plat_arm_psci_pm_ops` */
 #pragma weak plat_arm_psci_pm_ops
@@ -87,12 +81,7 @@
  ******************************************************************************/
 int css_pwr_domain_on(u_register_t mpidr)
 {
-	/*
-	 * SCP takes care of powering up parent power domains so we
-	 * only need to care about level 0
-	 */
-	scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
-				 scpi_power_on);
+	css_scp_on(mpidr);
 
 	return PSCI_E_SUCCESS;
 }
@@ -140,30 +129,12 @@
  ******************************************************************************/
 static void css_power_down_common(const psci_power_state_t *target_state)
 {
-	uint32_t cluster_state = scpi_power_on;
-	uint32_t system_state = scpi_power_on;
-
 	/* Prevent interrupts from spuriously waking up this cpu */
 	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 (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();
-		cluster_state = scpi_power_off;
-	}
-
-	/*
-	 * Ask the SCP to power down the appropriate components depending upon
-	 * their state.
-	 */
-	scpi_set_css_power_state(read_mpidr_el1(),
-				 scpi_power_off,
-				 cluster_state,
-				 system_state);
 }
 
 /*******************************************************************************
@@ -174,6 +145,7 @@
 {
 	assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
 	css_power_down_common(target_state);
+	css_scp_off(target_state);
 }
 
 /*******************************************************************************
@@ -191,6 +163,7 @@
 
 	assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
 	css_power_down_common(target_state);
+	css_scp_suspend(target_state);
 }
 
 /*******************************************************************************
@@ -222,34 +195,12 @@
  ******************************************************************************/
 void __dead2 css_system_off(void)
 {
-	uint32_t response;
-
-	/* Send the power down request to the SCP */
-	response = scpi_sys_power_state(scpi_system_shutdown);
-
-	if (response != SCP_OK) {
-		ERROR("CSS System Off: SCP error %u.\n", response);
-		panic();
-	}
-	wfi();
-	ERROR("CSS System Off: operation not handled.\n");
-	panic();
+	css_scp_sys_shutdown();
 }
 
 void __dead2 css_system_reset(void)
 {
-	uint32_t response;
-
-	/* Send the system reset request to the SCP */
-	response = scpi_sys_power_state(scpi_system_reboot);
-
-	if (response != SCP_OK) {
-		ERROR("CSS System Reset: SCP error %u.\n", response);
-		panic();
-	}
-	wfi();
-	ERROR("CSS System Reset: operation not handled.\n");
-	panic();
+	css_scp_sys_reboot();
 }
 
 /*******************************************************************************
@@ -303,43 +254,14 @@
  ******************************************************************************/
 int css_node_hw_state(u_register_t mpidr, unsigned int power_level)
 {
-	int rc, element;
-	unsigned int cpu_state, cluster_state;
-
-	/*
-	 * The format of 'power_level' is implementation-defined, but 0 must
-	 * mean a CPU. We also allow 1 to denote the cluster
-	 */
-	if (power_level != ARM_PWR_LVL0 && power_level != ARM_PWR_LVL1)
-		return PSCI_E_INVALID_PARAMS;
-
-	/* Query SCP */
-	rc = scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state);
-	if (rc != 0)
-		return PSCI_E_INVALID_PARAMS;
-
-	/* Map power states of CPU and cluster to expected PSCI return codes */
-	if (power_level == ARM_PWR_LVL0) {
-		/*
-		 * The CPU state returned by SCP is an 8-bit bit mask
-		 * corresponding to each CPU in the cluster
-		 */
-		element = mpidr & MPIDR_AFFLVL_MASK;
-		return CSS_CPU_PWR_STATE(cpu_state, element) ==
-			CSS_CPU_PWR_STATE_ON ? HW_ON : HW_OFF;
-	} else {
-		assert(cluster_state == CSS_CLUSTER_PWR_STATE_ON ||
-				cluster_state == CSS_CLUSTER_PWR_STATE_OFF);
-		return cluster_state == CSS_CLUSTER_PWR_STATE_ON ? HW_ON :
-			HW_OFF;
-	}
+	return css_scp_get_power_state(mpidr, power_level);
 }
 
 /*******************************************************************************
  * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
  * platform will take care of registering the handlers with PSCI.
  ******************************************************************************/
-const plat_psci_ops_t plat_arm_psci_pm_ops = {
+plat_psci_ops_t plat_arm_psci_pm_ops = {
 	.pwr_domain_on		= css_pwr_domain_on,
 	.pwr_domain_on_finish	= css_pwr_domain_on_finish,
 	.pwr_domain_off		= css_pwr_domain_off,
diff --git a/plat/arm/css/common/css_scp_bootloader.c b/plat/arm/css/common/css_scp_bootloader.c
index d3f671e..049afe4 100644
--- a/plat/arm/css/common/css_scp_bootloader.c
+++ b/plat/arm/css/common/css_scp_bootloader.c
@@ -34,9 +34,9 @@
 #include <debug.h>
 #include <platform.h>
 #include <stdint.h>
-#include "css_mhu.h"
+#include "../drivers/scpi/css_mhu.h"
+#include "../drivers/scpi/css_scpi.h"
 #include "css_scp_bootloader.h"
-#include "css_scpi.h"
 
 /* ID of the MHU slot used for the BOM protocol */
 #define BOM_MHU_SLOT_ID		0
diff --git a/plat/arm/css/drivers/scp/css_pm_scpi.c b/plat/arm/css/drivers/scp/css_pm_scpi.c
new file mode 100644
index 0000000..e22504d
--- /dev/null
+++ b/plat/arm/css/drivers/scp/css_pm_scpi.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2016, 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:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <css_pm.h>
+#include <debug.h>
+#include "../scpi/css_scpi.h"
+#include "css_scp.h"
+
+/*
+ * This file implements the SCP power management functions using SCPI protocol.
+ */
+
+/*
+ * Helper function to inform power down state to SCP.
+ */
+void css_scp_suspend(const psci_power_state_t *target_state)
+{
+	uint32_t cluster_state = scpi_power_on;
+	uint32_t system_state = scpi_power_on;
+
+	/* 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 (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
+		cluster_state = scpi_power_off;
+
+	/*
+	 * Ask the SCP to power down the appropriate components depending upon
+	 * their state.
+	 */
+	scpi_set_css_power_state(read_mpidr_el1(),
+				 scpi_power_off,
+				 cluster_state,
+				 system_state);
+}
+
+/*
+ * Helper function to turn off a CPU power domain and its parent power domains
+ * if applicable. Since SCPI doesn't differentiate between OFF and suspend, we
+ * call the suspend helper here.
+ */
+void css_scp_off(const psci_power_state_t *target_state)
+{
+	css_scp_suspend(target_state);
+}
+
+/*
+ * Helper function to turn ON a CPU power domain and its parent power domains
+ * if applicable.
+ */
+void css_scp_on(u_register_t mpidr)
+{
+	/*
+	 * SCP takes care of powering up parent power domains so we
+	 * only need to care about level 0
+	 */
+	scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
+				 scpi_power_on);
+}
+
+/*
+ * Helper function to get the power state of a power domain node as reported
+ * by the SCP.
+ */
+int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level)
+{
+	int rc, element;
+	unsigned int cpu_state, cluster_state;
+
+	/*
+	 * The format of 'power_level' is implementation-defined, but 0 must
+	 * mean a CPU. We also allow 1 to denote the cluster
+	 */
+	if (power_level != ARM_PWR_LVL0 && power_level != ARM_PWR_LVL1)
+		return PSCI_E_INVALID_PARAMS;
+
+	/* Query SCP */
+	rc = scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state);
+	if (rc != 0)
+		return PSCI_E_INVALID_PARAMS;
+
+	/* Map power states of CPU and cluster to expected PSCI return codes */
+	if (power_level == ARM_PWR_LVL0) {
+		/*
+		 * The CPU state returned by SCP is an 8-bit bit mask
+		 * corresponding to each CPU in the cluster
+		 */
+		element = mpidr & MPIDR_AFFLVL_MASK;
+		return CSS_CPU_PWR_STATE(cpu_state, element) ==
+			CSS_CPU_PWR_STATE_ON ? HW_ON : HW_OFF;
+	} else {
+		assert(cluster_state == CSS_CLUSTER_PWR_STATE_ON ||
+				cluster_state == CSS_CLUSTER_PWR_STATE_OFF);
+		return cluster_state == CSS_CLUSTER_PWR_STATE_ON ? HW_ON :
+			HW_OFF;
+	}
+}
+
+/*
+ * Helper function to shutdown the system via SCPI.
+ */
+void __dead2 css_scp_sys_shutdown(void)
+{
+	uint32_t response;
+
+	/* Send the power down request to the SCP */
+	response = scpi_sys_power_state(scpi_system_shutdown);
+
+	if (response != SCP_OK) {
+		ERROR("CSS System Off: SCP error %u.\n", response);
+		panic();
+	}
+	wfi();
+	ERROR("CSS System Off: operation not handled.\n");
+	panic();
+}
+
+/*
+ * Helper function to reset the system via SCPI.
+ */
+void __dead2 css_scp_sys_reboot(void)
+{
+	uint32_t response;
+
+	/* Send the system reset request to the SCP */
+	response = scpi_sys_power_state(scpi_system_reboot);
+
+	if (response != SCP_OK) {
+		ERROR("CSS System Reset: SCP error %u.\n", response);
+		panic();
+	}
+	wfi();
+	ERROR("CSS System Reset: operation not handled.\n");
+	panic();
+}
diff --git a/plat/arm/css/common/css_mhu.h b/plat/arm/css/drivers/scp/css_scp.h
similarity index 75%
copy from plat/arm/css/common/css_mhu.h
copy to plat/arm/css/drivers/scp/css_scp.h
index 2175cdf..a12798b 100644
--- a/plat/arm/css/common/css_mhu.h
+++ b/plat/arm/css/drivers/scp/css_scp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016, 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:
@@ -28,16 +28,16 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef __CSS_MHU_H__
-#define __CSS_MHU_H__
+#ifndef __CSS_SCP_H__
+#define __CSS_SCP_H__
 
-#include <stdint.h>
+#include <psci.h>
 
-void mhu_secure_message_start(unsigned int slot_id);
-void mhu_secure_message_send(unsigned int slot_id);
-uint32_t mhu_secure_message_wait(void);
-void mhu_secure_message_end(unsigned int slot_id);
+void css_scp_suspend(const psci_power_state_t *target_state);
+void css_scp_off(const psci_power_state_t *target_state);
+void css_scp_on(u_register_t mpidr);
+int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level);
+void __dead2 css_scp_sys_shutdown(void);
+void __dead2 css_scp_sys_reboot(void);
 
-void mhu_secure_init(void);
-
-#endif	/* __CSS_MHU_H__ */
+#endif	/* __CSS_SCP_H__ */
diff --git a/plat/arm/css/common/css_mhu.c b/plat/arm/css/drivers/scpi/css_mhu.c
similarity index 99%
rename from plat/arm/css/common/css_mhu.c
rename to plat/arm/css/drivers/scpi/css_mhu.c
index 265d6c2..302286f 100644
--- a/plat/arm/css/common/css_mhu.c
+++ b/plat/arm/css/drivers/scpi/css_mhu.c
@@ -33,8 +33,8 @@
 #include <bakery_lock.h>
 #include <css_def.h>
 #include <mmio.h>
-#include <platform_def.h>
 #include <plat_arm.h>
+#include <platform_def.h>
 #include "css_mhu.h"
 
 /* SCP MHU secure channel registers */
diff --git a/plat/arm/css/common/css_mhu.h b/plat/arm/css/drivers/scpi/css_mhu.h
similarity index 96%
rename from plat/arm/css/common/css_mhu.h
rename to plat/arm/css/drivers/scpi/css_mhu.h
index 2175cdf..6973a14 100644
--- a/plat/arm/css/common/css_mhu.h
+++ b/plat/arm/css/drivers/scpi/css_mhu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
diff --git a/plat/arm/css/common/css_scpi.c b/plat/arm/css/drivers/scpi/css_scpi.c
similarity index 94%
rename from plat/arm/css/common/css_scpi.c
rename to plat/arm/css/drivers/scpi/css_scpi.c
index 90a8939..f419abd 100644
--- a/plat/arm/css/common/css_scpi.c
+++ b/plat/arm/css/drivers/scpi/css_scpi.c
@@ -63,9 +63,11 @@
 
 static void scpi_secure_message_send(size_t payload_size)
 {
-	/* Ensure that any write to the SCPI payload area is seen by SCP before
+	/*
+	 * Ensure that any write to the SCPI payload area is seen by SCP before
 	 * we write to the MHU register. If these 2 writes were reordered by
-	 * the CPU then SCP would read stale payload data */
+	 * the CPU then SCP would read stale payload data
+	 */
 	dmbst();
 
 	mhu_secure_message_send(SCPI_MHU_SLOT_ID);
@@ -86,9 +88,11 @@
 		panic();
 	}
 
-	/* Ensure that any read to the SCPI payload area is done after reading
+	/*
+	 * Ensure that any read to the SCPI payload area is done after reading
 	 * the MHU register. If these 2 reads were reordered then the CPU would
-	 * read invalid payload data */
+	 * read invalid payload data
+	 */
 	dmbld();
 
 	memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
@@ -137,8 +141,9 @@
 	return status == SCP_OK ? 0 : -1;
 }
 
-void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
-		scpi_power_state_t cluster_state, scpi_power_state_t css_state)
+void scpi_set_css_power_state(unsigned int mpidr,
+		scpi_power_state_t cpu_state, scpi_power_state_t cluster_state,
+		scpi_power_state_t css_state)
 {
 	scpi_cmd_t *cmd;
 	uint32_t state = 0;
diff --git a/plat/arm/css/common/css_scpi.h b/plat/arm/css/drivers/scpi/css_scpi.h
similarity index 98%
rename from plat/arm/css/common/css_scpi.h
rename to plat/arm/css/drivers/scpi/css_scpi.h
index 1fb55e4..d1e7cba 100644
--- a/plat/arm/css/common/css_scpi.h
+++ b/plat/arm/css/drivers/scpi/css_scpi.h
@@ -122,7 +122,7 @@
 } scpi_system_state_t;
 
 extern int scpi_wait_ready(void);
-extern void scpi_set_css_power_state(unsigned mpidr,
+extern void scpi_set_css_power_state(unsigned int mpidr,
 					scpi_power_state_t cpu_state,
 					scpi_power_state_t cluster_state,
 					scpi_power_state_t css_state);
diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S
index 069d96d..802e1fe 100644
--- a/plat/common/aarch32/platform_helpers.S
+++ b/plat/common/aarch32/platform_helpers.S
@@ -31,27 +31,12 @@
 #include <arch.h>
 #include <asm_macros.S>
 
-	.weak	plat_my_core_pos
 	.weak	plat_reset_handler
 	.weak	plat_disable_acp
 	.weak	platform_mem_init
 	.weak	plat_panic_handler
 
 	/* -----------------------------------------------------
-	 *  int plat_my_core_pos(void);
-	 *  With this function: CorePos	= (ClusterId * 4) +
-	 *				  CoreId
-	 * -----------------------------------------------------
-	 */
-func plat_my_core_pos
-	ldcopr	r0, MPIDR
-	and	r1, r0, #MPIDR_CPU_MASK
-	and	r0, r0, #MPIDR_CLUSTER_MASK
-	add	r0, r1, r0, LSR #6
-	bx	lr
-endfunc	plat_my_core_pos
-
-	/* -----------------------------------------------------
 	 * Placeholder function which should be redefined by
 	 * each platform.
 	 * -----------------------------------------------------
diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c
index 4c688ca..78a68ba 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -236,7 +236,12 @@
 	int reg_width = GET_RW(read_ctx_reg(get_el3state_ctx(&ctx->cpu_ctx),
 			       CTX_SPSR_EL3));
 
+	/*
+	 * Get information about the Trusty image. Its absence is a critical
+	 * failure.
+	 */
 	ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+	assert(ep_info);
 
 	cm_el1_sysregs_context_save(NON_SECURE);