riscv: Add AST2700 SoC initial platform support

AST2700 SoCs integrates a Ibex 32-bits RISC-V core as the boot MCU
for the first stage bootloader execution, namely SPL.

This patch implements the preliminary base to successfully run SPL
on this RV32-based MCU to the console banner message.

Signed-off-by: Chia-Wei Wang <chiawei_wang@aspeedtech.com>
Reviewed-by: Leo Yu-Chi Liang <ycliang@andestech.com>
diff --git a/board/aspeed/ibex_ast2700/Kconfig b/board/aspeed/ibex_ast2700/Kconfig
new file mode 100644
index 0000000..469cea5
--- /dev/null
+++ b/board/aspeed/ibex_ast2700/Kconfig
@@ -0,0 +1,21 @@
+if TARGET_ASPEED_AST2700_IBEX
+
+config SYS_BOARD
+	default "ibex_ast2700"
+
+config SYS_VENDOR
+	default "aspeed"
+
+config SYS_CPU
+	default "ast2700"
+
+config SYS_CONFIG_NAME
+	default "ibex_ast2700"
+
+config BOARD_SPECIFIC_OPTIONS
+	def_bool y
+	select RISCV_AST2700
+	select SUPPORT_SPL
+	imply SPL_DRIVERS_MISC
+
+endif
diff --git a/board/aspeed/ibex_ast2700/MAINTAINERS b/board/aspeed/ibex_ast2700/MAINTAINERS
new file mode 100644
index 0000000..777f582
--- /dev/null
+++ b/board/aspeed/ibex_ast2700/MAINTAINERS
@@ -0,0 +1,7 @@
+AST2700 using Ibex RISC-V Core as the boot MCU
+M:	Chia-Wei, Wang <chiawei_wang@aspeedtech.com>
+S:	Maintained
+F:	arch/riscv/include/asm/arch-ast2700/
+F:	board/aspeed/ibex_ast2700/
+F:	configs/ibex-ast2700_defconfig
+F:	include/configs/ibex_ast2700.h
diff --git a/board/aspeed/ibex_ast2700/Makefile b/board/aspeed/ibex_ast2700/Makefile
new file mode 100644
index 0000000..162f46f
--- /dev/null
+++ b/board/aspeed/ibex_ast2700/Makefile
@@ -0,0 +1,2 @@
+obj-y += ibex_ast2700.o
+obj-y += sli.o
diff --git a/board/aspeed/ibex_ast2700/ibex_ast2700.c b/board/aspeed/ibex_ast2700/ibex_ast2700.c
new file mode 100644
index 0000000..e697f9b
--- /dev/null
+++ b/board/aspeed/ibex_ast2700/ibex_ast2700.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+#include <asm/io.h>
+#include <asm/arch/sli.h>
+#include <dm.h>
+#include <ram.h>
+#include <spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	int ret;
+	struct udevice *dev;
+	struct ram_info ram;
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		printf("cannot get DRAM driver\n");
+		return ret;
+	}
+
+	ret = ram_get_info(dev, &ram);
+	if (ret) {
+		printf("cannot get DRAM information\n");
+		return ret;
+	}
+
+	gd->ram_size = ram.size;
+
+	return 0;
+}
+
+int spl_board_init_f(void)
+{
+	sli_init();
+
+	dram_init();
+
+	return 0;
+}
+
+struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+	return (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR;
+}
+
+void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
+{
+	return (void *)spl_get_load_buffer(sectors, bl_len);
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_RAM;
+}
+
+int board_init(void)
+{
+	struct udevice *dev;
+	int i = 0;
+	int ret;
+
+	/*
+	 * Loop over all MISC uclass drivers to call the comphy code
+	 * and init all CP110 devices enabled in the DT
+	 */
+	while (1) {
+		/* Call the comphy code via the MISC uclass driver */
+		ret = uclass_get_device(UCLASS_MISC, i++, &dev);
+
+		/* We're done, once no further CP110 device is found */
+		if (ret)
+			break;
+	}
+
+	return 0;
+}
+
+int board_late_init(void)
+{
+	return 0;
+}
diff --git a/board/aspeed/ibex_ast2700/sli.c b/board/aspeed/ibex_ast2700/sli.c
new file mode 100644
index 0000000..7868111
--- /dev/null
+++ b/board/aspeed/ibex_ast2700/sli.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+#include <asm/io.h>
+#include <asm/arch/sli.h>
+#include <asm/arch/scu.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+#define SLI_POLL_TIMEOUT_US	100
+
+static void sli_clear_interrupt_status(uint32_t base)
+{
+	writel(-1, (void *)base + SLI_INTR_STATUS);
+}
+
+static int sli_wait(uint32_t base, uint32_t mask)
+{
+	uint32_t value;
+
+	sli_clear_interrupt_status(base);
+
+	do {
+		value = readl((void *)base + SLI_INTR_STATUS);
+		if (value & SLI_INTR_RX_ERRORS)
+			return -1;
+	} while ((value & mask) != mask);
+
+	return 0;
+}
+
+static int sli_wait_suspend(uint32_t base)
+{
+	return sli_wait(base, SLI_INTR_TX_SUSPEND | SLI_INTR_RX_SUSPEND);
+}
+
+/*
+ * CPU die  --- downstream pads ---> I/O die
+ * CPU die  <--- upstream pads ----- I/O die
+ *
+ * US/DS PAD[3:0] : SLIM[3:0]
+ * US/DS PAD[5:4] : SLIH[1:0]
+ * US/DS PAD[7:6] : SLIV[1:0]
+ */
+int sli_init(void)
+{
+	uint32_t value;
+
+	/* The following training sequence is designed for AST2700A0 */
+	value = FIELD_GET(SCU1_REVISION_HWID, readl(SCU1_REVISION));
+	if (value)
+		return 0;
+
+	/* Return if SLI had been calibrated */
+	value = readl((void *)SLIH_IOD_BASE + SLI_CTRL_III);
+	value = FIELD_GET(SLI_CLK_SEL, value);
+	if (value) {
+		debug("SLI has been initialized\n");
+		return 0;
+	}
+
+	/* 25MHz PAD delay for AST2700A0 */
+	value = SLI_RX_PHY_LAH_SEL_NEG | SLI_TRANS_EN | SLI_CLEAR_BUS;
+	writel(value, (void *)SLIH_IOD_BASE + SLI_CTRL_I);
+	writel(value, (void *)SLIM_IOD_BASE + SLI_CTRL_I);
+	writel(value | SLIV_RAW_MODE, (void *)SLIV_IOD_BASE + SLI_CTRL_I);
+	sli_wait_suspend(SLIH_IOD_BASE);
+	sli_wait_suspend(SLIH_CPU_BASE);
+
+	return 0;
+}