psci: preserve target affinity level during suspend

This patch adds support to save and restore the target affinity level
specified during a cpu_suspend psci call. This ensures that we
traverse only through the affinity levels that we originally intended
to after resuming from suspend.

Change-Id: I0900ae49a50b496da137cfec8f158da0397ec56c
diff --git a/common/psci/psci_afflvl_suspend.c b/common/psci/psci_afflvl_suspend.c
index 6fb60f4..b2dc732 100644
--- a/common/psci/psci_afflvl_suspend.c
+++ b/common/psci/psci_afflvl_suspend.c
@@ -44,6 +44,37 @@
 				      unsigned int);
 
 /*******************************************************************************
+ * This function sets the affinity level till which the current cpu is being
+ * powered down to during a cpu_suspend call
+ ******************************************************************************/
+void psci_set_suspend_afflvl(aff_map_node *node, int afflvl)
+{
+	/*
+	 * Check that nobody else is calling this function on our behalf &
+	 * this information is being set only in the cpu node
+	 */
+	assert(node->mpidr == (read_mpidr() & MPIDR_AFFINITY_MASK));
+	assert(node->level == MPIDR_AFFLVL0);
+
+	/*
+	 * Store the affinity level we are powering down to in our context.
+	 * The cache flush in the suspend code will ensure that this info
+	 * is available immediately upon resuming.
+	 */
+	psci_suspend_context[node->data].suspend_level = afflvl;
+}
+
+/*******************************************************************************
+ * This function gets the affinity level till which the current cpu was powered
+ * down during a cpu_suspend call.
+ ******************************************************************************/
+int psci_get_suspend_afflvl(aff_map_node *node)
+{
+	/* Return the target affinity level */
+	return psci_suspend_context[node->data].suspend_level;
+}
+
+/*******************************************************************************
  * The next three functions implement a handler for each supported affinity
  * level which is called when that affinity level is about to be suspended.
  ******************************************************************************/
@@ -336,6 +367,9 @@
 			  end_afflvl,
 			  PSCI_STATE_SUSPEND);
 
+	/* Save the affinity level till which this cpu can be powered down */
+	psci_set_suspend_afflvl(mpidr_nodes[MPIDR_AFFLVL0], end_afflvl);
+
 	/* Perform generic, architecture and platform specific handling */
 	rc = psci_call_suspend_handlers(mpidr_nodes,
 					start_afflvl,