a5ds: add multicore support

Enable cores 1-3 using psci. On receiving the smc call from kernel,
core 0 will bring the secondary cores out pen and signal an event for
the cores. Currently on switching the cores is enabled i.e. it is not
possible to suspend, switch cores off, etc.

Change-Id: I6087e1d2ec650e1d587fd543efc1b08cbb50ae5f
Signed-off-by: Usama Arif <usama.arif@arm.com>
diff --git a/plat/arm/board/a5ds/a5ds_pm.c b/plat/arm/board/a5ds/a5ds_pm.c
index 5fd443b..98de77d 100644
--- a/plat/arm/board/a5ds/a5ds_pm.c
+++ b/plat/arm/board/a5ds/a5ds_pm.c
@@ -6,19 +6,56 @@
 
 #include <lib/psci/psci.h>
 #include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <drivers/arm/gicv2.h>
 
 /*******************************************************************************
+ * Platform handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int a5ds_pwr_domain_on(u_register_t mpidr)
+{
+	unsigned int pos = plat_core_pos_by_mpidr(mpidr);
+	uint64_t *hold_base = (uint64_t *)A5DS_HOLD_BASE;
+
+	hold_base[pos] = A5DS_HOLD_STATE_GO;
+	dsbish();
+	sev();
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void a5ds_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	/* TODO: This setup is needed only after a cold boot*/
+	gicv2_pcpu_distif_init();
+
+	/* Enable the gic cpu interface */
+	gicv2_cpuif_enable();
+}
+
+/*******************************************************************************
  * Export the platform handlers via a5ds_psci_pm_ops. The ARM Standard
  * platform layer will take care of registering the handlers with PSCI.
  ******************************************************************************/
 plat_psci_ops_t a5ds_psci_pm_ops = {
 	/* dummy struct */
 	.validate_ns_entrypoint = NULL,
+	.pwr_domain_on = a5ds_pwr_domain_on,
+	.pwr_domain_on_finish = a5ds_pwr_domain_on_finish
 };
 
 int __init plat_setup_psci_ops(uintptr_t sec_entrypoint,
 				const plat_psci_ops_t **psci_ops)
 {
+	uintptr_t *mailbox = (void *)A5DS_TRUSTED_MAILBOX_BASE;
+	*mailbox = sec_entrypoint;
+
 	*psci_ops = &a5ds_psci_pm_ops;
 
 	return 0;