Add power management support in the SPD

This patch implements a set of handlers in the SPD which are called by
the PSCI runtime service upon receiving a power management
operation. These handlers in turn pass control to the Secure Payload
image if required before returning control to PSCI. This ensures that
the Secure Payload has complete visibility of all power transitions in
the system and can prepare accordingly.

Change-Id: I2d1dba5629b7cf2d53999d39fe807dfcf3f62fe2
diff --git a/include/context.h b/include/context.h
index 082e511..cb4cd8e 100644
--- a/include/context.h
+++ b/include/context.h
@@ -259,6 +259,42 @@
 CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context, el3state_ctx), \
 	assert_core_context_el3state_offset_mismatch);
 
+/*
+ * Helper macro to set the general purpose registers that correspond to
+ * parameters in an aapcs_64 call i.e. x0-x7
+ */
+#define set_aapcs_args0(ctx, x0)				do {	\
+		write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0, x0);	\
+	} while (0);
+#define set_aapcs_args1(ctx, x0, x1)				do {	\
+		write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1, x1);	\
+		set_aapcs_args0(ctx, x0);				\
+	} while (0);
+#define set_aapcs_args2(ctx, x0, x1, x2)			do {	\
+		write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2, x2);	\
+		set_aapcs_args1(ctx, x0, x1);				\
+	} while (0);
+#define set_aapcs_args3(ctx, x0, x1, x2, x3)			do {	\
+		write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3, x3);	\
+		set_aapcs_args2(ctx, x0, x1, x2);			\
+	} while (0);
+#define set_aapcs_args4(ctx, x0, x1, x2, x3, x4)		do {	\
+		write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X4, x4);	\
+		set_aapcs_args3(ctx, x0, x1, x2, x3);			\
+	} while (0);
+#define set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5)		do {	\
+		write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X5, x5);	\
+		set_aapcs_args4(ctx, x0, x1, x2, x3, x4);		\
+	} while (0);
+#define set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6)	do {	\
+		write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X6, x6);	\
+		set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5);		\
+	} while (0);
+#define set_aapcs_args7(ctx, x0, x1, x2, x3, x4, x5, x6, x7)	do {	\
+		write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X7, x7);	\
+		set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6);	\
+	} while (0);
+
 /*******************************************************************************
  * Function prototypes
  ******************************************************************************/
diff --git a/include/context_mgmt.h b/include/context_mgmt.h
index b8c8077..35f7c8c 100644
--- a/include/context_mgmt.h
+++ b/include/context_mgmt.h
@@ -48,6 +48,7 @@
 extern void cm_el1_sysregs_context_restore(uint32_t security_state);
 extern void cm_set_el3_eret_context(uint32_t security_state, uint64_t entrypoint,
 		uint32_t spsr, uint32_t scr);
+extern void cm_set_el3_elr(uint32_t security_state, uint64_t entrypoint);
 extern void cm_set_next_eret_context(uint32_t security_state);
 extern void cm_init_exception_stack(uint64_t mpidr, uint32_t security_state);
 #endif /*__ASSEMBLY__*/
diff --git a/include/psci.h b/include/psci.h
index e14c60b..3a040f9 100644
--- a/include/psci.h
+++ b/include/psci.h
@@ -55,7 +55,7 @@
  ******************************************************************************/
 #define PSCI_TOS_UP_MIG_CAP	0
 #define PSCI_TOS_NOT_UP_MIG_CAP	1
-#define PSCI_TOS_NOT_PRESENT	2
+#define PSCI_TOS_NOT_PRESENT_MP	2
 
 /*******************************************************************************
  * PSCI CPU_SUSPEND 'power_state' parameter specific defines
@@ -140,6 +140,22 @@
 } plat_pm_ops;
 
 /*******************************************************************************
+ * Optional structure populated by the Secure Payload Dispatcher to be given a
+ * chance to perform any bookkeeping before PSCI executes a power mgmt.
+ * operation. It also allows PSCI to determine certain properties of the SP e.g.
+ * migrate capability etc.
+ ******************************************************************************/
+typedef struct {
+	void (*svc_on)(uint64_t target_cpu);
+	int32_t (*svc_off)(uint64_t __unused);
+	void (*svc_suspend)(uint64_t power_state);
+	void (*svc_on_finish)(uint64_t __unused);
+	void (*svc_suspend_finish)(uint64_t suspend_level);
+	void (*svc_migrate)(uint64_t __unused1, uint64_t __unused2);
+	int32_t (*svc_migrate_info)(uint64_t *__unused);
+} spd_pm_ops;
+
+/*******************************************************************************
  * Function & Data prototypes
  ******************************************************************************/
 extern unsigned int psci_version(void);