uniphier: support Socionext UniPhier platform

Initial commit for Socionext UniPhier SoC support.  BL1, Bl2, and
BL31 are supported.  Refer to docs/plat/socionext-uniphier.md for
more detais.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
diff --git a/plat/socionext/uniphier/uniphier_scp.c b/plat/socionext/uniphier/uniphier_scp.c
new file mode 100644
index 0000000..9a921c4
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_scp.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+#include <utils_def.h>
+
+#include "uniphier.h"
+
+#define UNIPHIER_ROM_RSV3		0x5980120c
+
+#define UNIPHIER_STMBE2COM		0x5f800030
+#define UNIPHIER_BETOSTMIRQ0PT		0x5f800070
+
+#define UNIPHIER_SCP_READY_MAGIC	0x0000b6a5
+
+#define UNIPHIER_SCP_PACKET_START	0xA0
+#define UNIPHIER_SCP_PACKET_END		0xA5
+#define UNIPHIER_SCP_PACKET_ESC		0xA6
+#define UNIPHIER_SCP_IS_CTRL_CODE(c)	(0xA0 <= (c) && (c) <= 0xA6)
+
+int uniphier_scp_is_running(void)
+{
+	return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC;
+}
+
+void uniphier_scp_start(void)
+{
+	uint32_t tmp;
+
+	mmio_write_32(UNIPHIER_STMBE2COM + 4, UNIPHIER_SCP_BASE);
+	mmio_write_32(UNIPHIER_STMBE2COM, UNIPHIER_SCP_READY_MAGIC);
+
+	do {
+		tmp = mmio_read_32(UNIPHIER_ROM_RSV3);
+	} while (!(tmp & BIT(8)));
+
+	mmio_write_32(UNIPHIER_ROM_RSV3, tmp | BIT(9));
+}
+
+static void uniphier_scp_send_packet(const uint8_t *packet, int packet_len)
+{
+	uintptr_t reg = UNIPHIER_STMBE2COM;
+	uint32_t word;
+	int len, i;
+
+	while (packet_len) {
+		len = MIN(packet_len, 4);
+		word = 0;
+
+		for (i = 0; i < len; i++)
+			word |= *packet++ << (8 * i);
+
+		mmio_write_32(reg, word);
+		reg += 4;
+		packet_len -= len;
+	}
+
+	mmio_write_8(UNIPHIER_BETOSTMIRQ0PT, 0x55);
+}
+
+static void uniphier_scp_send_cmd(const uint8_t *cmd, int cmd_len)
+{
+	uint8_t packet[32];	/* long enough */
+	uint8_t *p = packet;
+	uint8_t c;
+	int i;
+
+	*p++ = UNIPHIER_SCP_PACKET_START;
+	*p++ = cmd_len;
+
+	for (i = 0; i < cmd_len; i++) {
+		c = *cmd++;
+		if (UNIPHIER_SCP_IS_CTRL_CODE(c)) {
+			*p++ = UNIPHIER_SCP_PACKET_ESC;
+			*p++ = c ^ BIT(7);
+		} else {
+			*p++ = c;
+		}
+	}
+
+	*p++ = UNIPHIER_SCP_PACKET_END;
+
+	uniphier_scp_send_packet(packet, p - packet);
+}
+
+#define UNIPHIER_SCP_CMD(name, ...)					\
+static const uint8_t __uniphier_scp_##name##_cmd[] = {			\
+	__VA_ARGS__							\
+};									\
+void uniphier_scp_##name(void)						\
+{									\
+	uniphier_scp_send_cmd(__uniphier_scp_##name##_cmd,		\
+			      ARRAY_SIZE(__uniphier_scp_##name##_cmd));	\
+}
+
+UNIPHIER_SCP_CMD(open_com, 0x00, 0x00, 0x05)
+UNIPHIER_SCP_CMD(system_off, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01)
+UNIPHIER_SCP_CMD(system_reset, 0x00, 0x02, 0x00)