arch: arm: rockchip: Add initial support for RK3528

Rockchip RK3528 is a ARM-based SoC with quad-core Cortex-A53.

Add initial arch support for the RK3528 SoC.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
diff --git a/arch/arm/include/asm/arch-rk3528/boot0.h b/arch/arm/include/asm/arch-rk3528/boot0.h
new file mode 100644
index 0000000..8ae46f2
--- /dev/null
+++ b/arch/arm/include/asm/arch-rk3528/boot0.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright Contributors to the U-Boot project. */
+
+#ifndef __ASM_ARCH_BOOT0_H__
+#define __ASM_ARCH_BOOT0_H__
+
+#include <asm/arch-rockchip/boot0.h>
+
+#endif
diff --git a/arch/arm/include/asm/arch-rk3528/gpio.h b/arch/arm/include/asm/arch-rk3528/gpio.h
new file mode 100644
index 0000000..5516e64
--- /dev/null
+++ b/arch/arm/include/asm/arch-rk3528/gpio.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright Contributors to the U-Boot project. */
+
+#ifndef __ASM_ARCH_GPIO_H__
+#define __ASM_ARCH_GPIO_H__
+
+#include <asm/arch-rockchip/gpio.h>
+
+#endif
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index b61d424..4d5e587 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -319,6 +319,56 @@
 	  and video codec support. Peripherals include Gigabit Ethernet,
 	  USB2 host and OTG, SDIO, I2S, UARTs, SPI, I2C and PWMs.
 
+config ROCKCHIP_RK3528
+	bool "Support Rockchip RK3528"
+	select ARM64
+	select SUPPORT_SPL
+	select SPL
+	select CLK
+	select PINCTRL
+	select RAM
+	select REGMAP
+	select SYSCON
+	select BOARD_LATE_INIT
+	select DM_REGULATOR_FIXED
+	select DM_RESET
+	imply ARMV8_CRYPTO
+	imply ARMV8_SET_SMPEN
+	imply BOOTSTD_FULL
+	imply DM_RNG
+	imply FIT
+	imply LEGACY_IMAGE_FORMAT
+	imply MISC
+	imply MISC_INIT_R
+	imply MMC_HS200_SUPPORT if MMC_SDHCI_ROCKCHIP
+	imply OF_LIBFDT_OVERLAY
+	imply OF_LIVE
+	imply OF_UPSTREAM
+	imply PHY_GIGE if DWC_ETH_QOS_ROCKCHIP
+	imply RNG_ROCKCHIP
+	imply ROCKCHIP_COMMON_BOARD
+	imply ROCKCHIP_COMMON_STACK_ADDR
+	imply ROCKCHIP_EXTERNAL_TPL
+	imply ROCKCHIP_OTP
+	imply SPL_ATF
+	imply SPL_ATF_NO_PLATFORM_PARAM if SPL_ATF
+	imply SPL_CLK
+	imply SPL_DM_SEQ_ALIAS
+	imply SPL_FIT_SIGNATURE
+	imply SPL_LOAD_FIT
+	imply SPL_MMC_HS200_SUPPORT if SPL_MMC && MMC_HS200_SUPPORT
+	imply SPL_OF_CONTROL
+	imply SPL_PINCTRL
+	imply SPL_RAM
+	imply SPL_REGMAP
+	imply SPL_SERIAL
+	imply SPL_SYSCON
+	imply SYS_RELOC_GD_ENV_ADDR
+	imply SYSRESET
+	imply SYSRESET_PSCI if SPL_ATF
+	help
+	  The Rockchip RK3528 is a ARM-based SoC with a quad-core Cortex-A53.
+
 config ROCKCHIP_RK3568
 	bool "Support Rockchip RK3568"
 	select ARM64
@@ -639,6 +689,7 @@
 source "arch/arm/mach-rockchip/rk3328/Kconfig"
 source "arch/arm/mach-rockchip/rk3368/Kconfig"
 source "arch/arm/mach-rockchip/rk3399/Kconfig"
+source "arch/arm/mach-rockchip/rk3528/Kconfig"
 source "arch/arm/mach-rockchip/rk3568/Kconfig"
 source "arch/arm/mach-rockchip/rk3588/Kconfig"
 source "arch/arm/mach-rockchip/rv1108/Kconfig"
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 5e7edc9..5a7dd5b 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -42,6 +42,7 @@
 obj-$(CONFIG_ROCKCHIP_RK3328) += rk3328/
 obj-$(CONFIG_ROCKCHIP_RK3368) += rk3368/
 obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399/
+obj-$(CONFIG_ROCKCHIP_RK3528) += rk3528/
 obj-$(CONFIG_ROCKCHIP_RK3568) += rk3568/
 obj-$(CONFIG_ROCKCHIP_RK3588) += rk3588/
 obj-$(CONFIG_ROCKCHIP_RV1108) += rv1108/
diff --git a/arch/arm/mach-rockchip/rk3528/Kconfig b/arch/arm/mach-rockchip/rk3528/Kconfig
new file mode 100644
index 0000000..993b2dd
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3528/Kconfig
@@ -0,0 +1,15 @@
+if ROCKCHIP_RK3528
+
+config ROCKCHIP_BOOT_MODE_REG
+	default 0xff370200
+
+config ROCKCHIP_STIMER_BASE
+	default 0xff620000
+
+config SYS_SOC
+	default "rk3528"
+
+config SYS_CONFIG_NAME
+	default "rk3528_common"
+
+endif
diff --git a/arch/arm/mach-rockchip/rk3528/Makefile b/arch/arm/mach-rockchip/rk3528/Makefile
new file mode 100644
index 0000000..f0c18cd
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3528/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-y += rk3528.o
+obj-y += clk_rk3528.o
+obj-y += syscon_rk3528.o
diff --git a/arch/arm/mach-rockchip/rk3528/clk_rk3528.c b/arch/arm/mach-rockchip/rk3528/clk_rk3528.c
new file mode 100644
index 0000000..6e77f11
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3528/clk_rk3528.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright Contributors to the U-Boot project.
+
+#include <dm.h>
+#include <asm/arch-rockchip/cru_rk3528.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+				DM_DRIVER_GET(rockchip_rk3528_cru), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+	return RK3528_CRU_BASE;
+}
diff --git a/arch/arm/mach-rockchip/rk3528/rk3528.c b/arch/arm/mach-rockchip/rk3528/rk3528.c
new file mode 100644
index 0000000..4892ff6
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3528/rk3528.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright Contributors to the U-Boot project.
+
+#define LOG_CATEGORY LOGC_ARCH
+
+#include <dm.h>
+#include <misc.h>
+#include <asm/armv8/mmu.h>
+#include <asm/arch-rockchip/bootrom.h>
+#include <asm/arch-rockchip/hardware.h>
+
+#define FIREWALL_DDR_BASE		0xff2e0000
+#define FW_DDR_MST6_REG			0x58
+#define FW_DDR_MST7_REG			0x5c
+#define FW_DDR_MST14_REG		0x78
+#define FW_DDR_MST16_REG		0x80
+
+const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
+	[BROM_BOOTSOURCE_EMMC] = "/soc/mmc@ffbf0000",
+	[BROM_BOOTSOURCE_SD] = "/soc/mmc@ffc30000",
+};
+
+static struct mm_region rk3528_mem_map[] = {
+	{
+		.virt = 0x0UL,
+		.phys = 0x0UL,
+		.size = 0xfc000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.virt = 0xfc000000UL,
+		.phys = 0xfc000000UL,
+		.size = 0x04000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = rk3528_mem_map;
+
+void board_debug_uart_init(void)
+{
+}
+
+int arch_cpu_init(void)
+{
+	u32 val;
+
+	if (!IS_ENABLED(CONFIG_SPL_BUILD))
+		return 0;
+
+	/* Set the emmc to access ddr memory */
+	val = readl(FIREWALL_DDR_BASE + FW_DDR_MST6_REG);
+	writel(val & 0x0000ffff, FIREWALL_DDR_BASE + FW_DDR_MST6_REG);
+
+	/* Set the fspi to access ddr memory */
+	val = readl(FIREWALL_DDR_BASE + FW_DDR_MST7_REG);
+	writel(val & 0xffff0000, FIREWALL_DDR_BASE + FW_DDR_MST7_REG);
+
+	/* Set the sdmmc to access ddr memory */
+	val = readl(FIREWALL_DDR_BASE + FW_DDR_MST14_REG);
+	writel(val & 0x0000ffff, FIREWALL_DDR_BASE + FW_DDR_MST14_REG);
+
+	/* Set the usb to access ddr memory */
+	val = readl(FIREWALL_DDR_BASE + FW_DDR_MST16_REG);
+	writel(val & 0xffff0000, FIREWALL_DDR_BASE + FW_DDR_MST16_REG);
+
+	return 0;
+}
+
+#define HP_TIMER_BASE			CONFIG_ROCKCHIP_STIMER_BASE
+#define HP_CTRL_REG			0x04
+#define TIMER_EN			BIT(0)
+#define HP_LOAD_COUNT0_REG		0x14
+#define HP_LOAD_COUNT1_REG		0x18
+
+void rockchip_stimer_init(void)
+{
+	u32 reg;
+
+	if (!IS_ENABLED(CONFIG_XPL_BUILD))
+		return;
+
+	reg = readl(HP_TIMER_BASE + HP_CTRL_REG);
+	if (reg & TIMER_EN)
+		return;
+
+	asm volatile("msr cntfrq_el0, %0" : : "r" (CONFIG_COUNTER_FREQUENCY));
+	writel(0xffffffff, HP_TIMER_BASE + HP_LOAD_COUNT0_REG);
+	writel(0xffffffff, HP_TIMER_BASE + HP_LOAD_COUNT1_REG);
+	writel(TIMER_EN, HP_TIMER_BASE + HP_CTRL_REG);
+}
+
+#define RK3528_OTP_CPU_CODE_OFFSET		0x02
+#define RK3528_OTP_CPU_CHIP_TYPE_OFFSET		0x28
+
+int checkboard(void)
+{
+	u8 cpu_code[2], chip_type;
+	struct udevice *dev;
+	char suffix[2];
+	int ret;
+
+	if (!IS_ENABLED(CONFIG_ROCKCHIP_OTP) || !CONFIG_IS_ENABLED(MISC))
+		return 0;
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_DRIVER_GET(rockchip_otp), &dev);
+	if (ret) {
+		log_debug("Could not find otp device, ret=%d\n", ret);
+		return 0;
+	}
+
+	/* cpu-code: SoC model, e.g. 0x35 0x28 */
+	ret = misc_read(dev, RK3528_OTP_CPU_CODE_OFFSET, cpu_code, 2);
+	if (ret < 0) {
+		log_debug("Could not read cpu-code, ret=%d\n", ret);
+		return 0;
+	}
+
+	ret = misc_read(dev, RK3528_OTP_CPU_CHIP_TYPE_OFFSET, &chip_type, 1);
+	if (ret < 0) {
+		log_debug("Could not read chip type, ret=%d\n", ret);
+		return 0;
+	}
+
+	suffix[0] = chip_type != 0x1 ? 'A' : '\0';
+	suffix[1] = '\0';
+
+	printf("SoC:   RK%02x%02x%s\n", cpu_code[0], cpu_code[1], suffix);
+
+	return 0;
+}
diff --git a/arch/arm/mach-rockchip/rk3528/syscon_rk3528.c b/arch/arm/mach-rockchip/rk3528/syscon_rk3528.c
new file mode 100644
index 0000000..4a32a5f
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3528/syscon_rk3528.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright Contributors to the U-Boot project.
+
+#include <dm.h>
+#include <asm/arch-rockchip/clock.h>
+
+static const struct udevice_id rk3528_syscon_ids[] = {
+	{ .compatible = "rockchip,rk3528-grf", .data = ROCKCHIP_SYSCON_GRF },
+	{ }
+};
+
+U_BOOT_DRIVER(rockchip_rk3528_syscon) = {
+	.name = "rockchip_rk3528_syscon",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3528_syscon_ids,
+#if CONFIG_IS_ENABLED(OF_REAL)
+	.bind = dm_scan_fdt_dev,
+#endif
+};