hikey: support BL31

Support BL31 and PSCI. Enable multiple cores in PSCI.

Change-Id: I66c39e1e9c4c45ac41a0142ed2070d79a3ac5ba3
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Signed-off-by: Dan Handley <dan.handley@arm.com>
diff --git a/plat/hisilicon/hikey/hisi_pwrc.c b/plat/hisilicon/hikey/hisi_pwrc.c
new file mode 100644
index 0000000..fcc9bd8
--- /dev/null
+++ b/plat/hisilicon/hikey/hisi_pwrc.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <hisi_ipc.h>
+#include <hisi_pwrc.h>
+#include <hisi_sram_map.h>
+#include <hi6220_regs_acpu.h>
+#include <hi6220_regs_ao.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <platform_def.h>
+
+#define CLUSTER_CORE_COUNT		(4)
+#define CLUSTER_CORE_MASK		((1 << CLUSTER_CORE_COUNT) - 1)
+
+void hisi_pwrc_set_core_bx_addr(unsigned int core, unsigned int cluster,
+				uintptr_t entry_point)
+{
+	uintptr_t *core_entry = (uintptr_t *)PWRCTRL_ACPU_ASM_D_ARM_PARA_AD;
+	unsigned int i;
+
+	if (!core_entry) {
+		INFO("%s: core entry point is null!\n", __func__);
+		return;
+	}
+
+	i = cluster * CLUSTER_CORE_COUNT + core;
+	mmio_write_64((uintptr_t)(core_entry + i), entry_point);
+}
+
+void hisi_pwrc_set_cluster_wfi(unsigned int cluster)
+{
+	unsigned int reg = 0;
+
+	if (cluster == 0) {
+		reg = mmio_read_32(ACPU_SC_SNOOP_PWD);
+		reg |= PD_DETECT_START0;
+		mmio_write_32(ACPU_SC_SNOOP_PWD, reg);
+	} else if (cluster == 1) {
+		reg = mmio_read_32(ACPU_SC_SNOOP_PWD);
+		reg |= PD_DETECT_START1;
+		mmio_write_32(ACPU_SC_SNOOP_PWD, reg);
+	}
+}
+
+int hisi_pwrc_setup(void)
+{
+	unsigned int reg, sec_entrypoint;
+	extern char pm_asm_code[], pm_asm_code_end[];
+	extern char v7_asm[], v7_asm_end[];
+
+	sec_entrypoint = PWRCTRL_ACPU_ASM_CODE_BASE;
+	mmio_write_32(ACPU_SC_CPUx_RVBARADDR(0), sec_entrypoint >> 2);
+	mmio_write_32(ACPU_SC_CPUx_RVBARADDR(1), sec_entrypoint >> 2);
+	mmio_write_32(ACPU_SC_CPUx_RVBARADDR(2), sec_entrypoint >> 2);
+	mmio_write_32(ACPU_SC_CPUx_RVBARADDR(3), sec_entrypoint >> 2);
+	mmio_write_32(ACPU_SC_CPUx_RVBARADDR(4), sec_entrypoint >> 2);
+	mmio_write_32(ACPU_SC_CPUx_RVBARADDR(5), sec_entrypoint >> 2);
+	mmio_write_32(ACPU_SC_CPUx_RVBARADDR(6), sec_entrypoint >> 2);
+	mmio_write_32(ACPU_SC_CPUx_RVBARADDR(7), sec_entrypoint >> 2);
+
+	memset((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, 0, 0x400);
+	memcpy((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, (void *)v7_asm,
+	       v7_asm_end - v7_asm);
+
+	memcpy((void *)PWRCTRL_ACPU_ASM_CODE_BASE, (void *)pm_asm_code,
+	       pm_asm_code_end - pm_asm_code);
+
+	reg = mmio_read_32(AO_SC_SYS_CTRL1);
+	reg |= AO_SC_SYS_CTRL1_REMAP_SRAM_AARM |
+	       AO_SC_SYS_CTRL1_REMAP_SRAM_AARM_MSK;
+	mmio_write_32(AO_SC_SYS_CTRL1, reg);
+
+	return 0;
+}