[PATCH 07/12] ARM: Rockchip: Add rk3568 support

Sascha Hauer s.hauer at pengutronix.de
Mon Jun 21 02:27:57 PDT 2021


This adds basic support for the Rockchip rk3568 SoC.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Link: https://lore.barebox.org/20210615141641.31577-8-s.hauer@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/Kconfig                              |   3 -
 arch/arm/mach-rockchip/Kconfig                |  18 ++
 arch/arm/mach-rockchip/Makefile               |   4 +-
 arch/arm/mach-rockchip/atf.c                  |  62 ++++++
 arch/arm/mach-rockchip/include/mach/atf.h     |  18 ++
 arch/arm/mach-rockchip/include/mach/bbu.h     |  14 ++
 .../arm/mach-rockchip/include/mach/debug_ll.h |   8 +
 .../mach-rockchip/include/mach/rk3568-regs.h  |  18 ++
 .../arm/mach-rockchip/include/mach/rockchip.h |  11 ++
 arch/arm/mach-rockchip/rk3568.c               | 176 ++++++++++++++++++
 arch/arm/mach-rockchip/rockchip.c             |   2 +
 common/Kconfig                                |  10 +-
 firmware/Makefile                             |   3 +-
 include/bootsource.h                          |   1 +
 14 files changed, 342 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/mach-rockchip/atf.c
 create mode 100644 arch/arm/mach-rockchip/include/mach/atf.h
 create mode 100644 arch/arm/mach-rockchip/include/mach/bbu.h
 create mode 100644 arch/arm/mach-rockchip/include/mach/rk3568-regs.h
 create mode 100644 arch/arm/mach-rockchip/rk3568.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6f28e1ec10..0740039309 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -145,8 +145,6 @@ config ARCH_PXA
 
 config ARCH_ROCKCHIP
 	bool "Rockchip RX3xxx"
-	select CPU_V7
-	select ARM_SMP_TWD
 	select COMMON_CLK
 	select CLKDEV_LOOKUP
 	select COMMON_CLK_OF_PROVIDER
@@ -156,7 +154,6 @@ config ARCH_ROCKCHIP
 	select OFTREE
 	select HAVE_PBL_MULTI_IMAGES
 	select HAS_DEBUG_LL
-	select ARCH_HAS_L2X0
 
 config ARCH_SOCFPGA
 	bool "Altera SOCFPGA"
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 65bcbcac96..b4c8573c6e 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -13,11 +13,23 @@ config RK_TIMER
 
 config ARCH_RK3188
 	bool
+	select CPU_V7
+	select ARM_SMP_TWD
+	select ARCH_HAS_L2X0
 
 config ARCH_RK3288
 	bool
+	select CPU_V7
+	select ARM_SMP_TWD
+	select ARCH_HAS_L2X0
 	select CLOCKSOURCE_ROCKCHIP
 
+config ARCH_RK3568
+	bool
+	select CPU_V8
+	select ARM_ATF
+	select SYS_SUPPORTS_64BIT_KERNEL
+
 comment "select Rockchip boards:"
 
 config MACH_RADXA_ROCK
@@ -34,3 +46,9 @@ config MACH_PHYTEC_SOM_RK3288
 	  Say Y here if you are using a RK3288 based Phytecs SOM
 
 endmenu
+
+config ARCH_RK3568_OPTEE
+	bool "Build OP-TEE binary into barebox"
+	help
+	  With this option enabled the RK3568 OP-TEE binary is compiled
+	  into barebox and started along with the BL31 trusted firmware.
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 0188d0252f..b7bab1fb73 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -1,3 +1,5 @@
-obj-y += rockchip.o
+obj-y += rockchip.o atf.o
+pbl-y += atf.o
 obj-$(CONFIG_ARCH_RK3188) += rk3188.o
 obj-$(CONFIG_ARCH_RK3288) += rk3288.o
+obj-pbl-$(CONFIG_ARCH_RK3568) += rk3568.o
diff --git a/arch/arm/mach-rockchip/atf.c b/arch/arm/mach-rockchip/atf.c
new file mode 100644
index 0000000000..3c4c9d1c8a
--- /dev/null
+++ b/arch/arm/mach-rockchip/atf.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <common.h>
+#include <firmware.h>
+#include <asm/system.h>
+#include <mach/atf.h>
+#include <elf.h>
+#include <asm/atf_common.h>
+
+static unsigned long load_elf64_image_phdr(const void *elf)
+{
+	const Elf64_Ehdr *ehdr; /* Elf header structure pointer */
+	const Elf64_Phdr *phdr; /* Program header structure pointer */
+	int i;
+
+	ehdr = elf;
+	phdr = elf + ehdr->e_phoff;
+
+	/* Load each program header */
+	for (i = 0; i < ehdr->e_phnum; ++i) {
+		void *dst = (void *)(ulong)phdr->p_paddr;
+		const void *src = elf + phdr->p_offset;
+
+		pr_debug("Loading phdr %i to 0x%p (%lu bytes)\n",
+			 i, dst, (ulong)phdr->p_filesz);
+		if (phdr->p_filesz)
+			memcpy(dst, src, phdr->p_filesz);
+		if (phdr->p_filesz != phdr->p_memsz)
+			memset(dst + phdr->p_filesz, 0x00,
+				phdr->p_memsz - phdr->p_filesz);
+		++phdr;
+	}
+
+	return ehdr->e_entry;
+}
+
+void rk3568_atf_load_bl31(void *fdt)
+{
+	const void *bl31_elf, *optee;
+	unsigned long bl31;
+	size_t bl31_elf_size, optee_size;
+	uintptr_t optee_load_address = 0;
+
+	get_builtin_firmware(rk3568_bl31_bin, &bl31_elf, &bl31_elf_size);
+
+	bl31 = load_elf64_image_phdr(bl31_elf);
+
+	if (IS_ENABLED(CONFIG_ARCH_RK3568_OPTEE)) {
+		optee_load_address = RK3568_OPTEE_LOAD_ADDRESS;
+
+		get_builtin_firmware(rk3568_op_tee_bin, &optee, &optee_size);
+
+		memcpy((void *)optee_load_address, optee, optee_size);
+	}
+
+	/* Setup an initial stack for EL2 */
+	asm volatile("msr sp_el2, %0" : :
+			"r" (RK3568_BAREBOX_LOAD_ADDRESS - 16) :
+			"cc");
+
+	bl31_entry(bl31, optee_load_address,
+		   RK3568_BAREBOX_LOAD_ADDRESS, (uintptr_t)fdt);
+}
diff --git a/arch/arm/mach-rockchip/include/mach/atf.h b/arch/arm/mach-rockchip/include/mach/atf.h
new file mode 100644
index 0000000000..337a8261c8
--- /dev/null
+++ b/arch/arm/mach-rockchip/include/mach/atf.h
@@ -0,0 +1,18 @@
+#ifndef __MACH_ATF_H
+#define __MACH_ATF_H
+
+/* First usable DRAM address. Lower mem is used for ATF and OP-TEE */
+#define RK3568_DRAM_BOTTOM		0xa00000
+
+/* OP-TEE expects to be loaded here */
+#define RK3568_OPTEE_LOAD_ADDRESS	0x200000
+
+/*
+ * board lowlevel code should relocate barebox here. This is where
+ * OP-TEE jumps to after initialization.
+ */
+#define RK3568_BAREBOX_LOAD_ADDRESS	(RK3568_DRAM_BOTTOM + 1024*1024)
+
+void rk3568_atf_load_bl31(void *fdt);
+
+#endif /* __MACH_ATF_H */
diff --git a/arch/arm/mach-rockchip/include/mach/bbu.h b/arch/arm/mach-rockchip/include/mach/bbu.h
new file mode 100644
index 0000000000..e61e0615e2
--- /dev/null
+++ b/arch/arm/mach-rockchip/include/mach/bbu.h
@@ -0,0 +1,14 @@
+#ifndef __MACH_ROCKCHIP_BBU_H
+#define __MACH_ROCKCHIP_BBU_H
+
+#include <bbu.h>
+
+static inline int rk3568_bbu_mmc_register(const char *name, unsigned long flags,
+                const char *devicefile)
+{
+	return bbu_register_std_file_update(name, flags,
+                devicefile, filetype_rockchip_rkns_image);
+
+}
+
+# endif /* __MACH_ROCKCHIP_BBU_H */
diff --git a/arch/arm/mach-rockchip/include/mach/debug_ll.h b/arch/arm/mach-rockchip/include/mach/debug_ll.h
index 7806aab8bb..af6257a674 100644
--- a/arch/arm/mach-rockchip/include/mach/debug_ll.h
+++ b/arch/arm/mach-rockchip/include/mach/debug_ll.h
@@ -5,6 +5,7 @@
 #include <io.h>
 #include <mach/rk3188-regs.h>
 #include <mach/rk3288-regs.h>
+#include <mach/rk3568-regs.h>
 
 #ifdef CONFIG_DEBUG_LL
 
@@ -22,6 +23,13 @@
 #define serial_out(a, v)	writel(v, a)
 #define serial_in(a)		readl(a)
 
+#elif defined CONFIG_DEBUG_ROCKCHIP_RK3568_UART
+
+#define UART_CLOCK		24000000
+#define RK_DEBUG_SOC		RK3568
+#define serial_out(a, v)	writel(v, a)
+#define serial_in(a)		readl(a)
+
 #endif
 
 #define __RK_UART_BASE(soc, num) soc##_UART##num##_BASE
diff --git a/arch/arm/mach-rockchip/include/mach/rk3568-regs.h b/arch/arm/mach-rockchip/include/mach/rk3568-regs.h
new file mode 100644
index 0000000000..bb2ca7bd90
--- /dev/null
+++ b/arch/arm/mach-rockchip/include/mach/rk3568-regs.h
@@ -0,0 +1,18 @@
+#ifndef __MACH_RK3568_REGS_H
+#define __MACH_RK3568_REGS_H
+
+/* UART */
+#define RK3568_UART0_BASE	0xfdd50000
+#define RK3568_UART1_BASE	0xfe650000
+#define RK3568_UART2_BASE	0xfe660000
+#define RK3568_UART3_BASE	0xfe670000
+#define RK3568_UART4_BASE	0xfe680000
+#define RK3568_UART5_BASE	0xfe690000
+#define RK3568_UART6_BASE	0xfe6a0000
+#define RK3568_UART7_BASE	0xfe6b0000
+#define RK3568_UART8_BASE	0xfe6c0000
+#define RK3568_UART9_BASE	0xfe6d0000
+
+#define RK3568_IRAM_BASE	0xfdcc0000
+
+#endif /* __MACH_RK3568_REGS_H */
diff --git a/arch/arm/mach-rockchip/include/mach/rockchip.h b/arch/arm/mach-rockchip/include/mach/rockchip.h
index 8d37c67d4f..722b73d6f8 100644
--- a/arch/arm/mach-rockchip/include/mach/rockchip.h
+++ b/arch/arm/mach-rockchip/include/mach/rockchip.h
@@ -19,4 +19,15 @@ static inline int rk3288_init(void)
 }
 #endif
 
+#ifdef CONFIG_ARCH_RK3568
+int rk3568_init(void);
+#else
+static inline int rk3568_init(void)
+{
+	return -ENOTSUPP;
+}
+#endif
+
+int rk3568_lowlevel_init(void);
+
 #endif /* __MACH_ROCKCHIP_H */
diff --git a/arch/arm/mach-rockchip/rk3568.c b/arch/arm/mach-rockchip/rk3568.c
new file mode 100644
index 0000000000..fcf3cb7053
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3568.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier:     GPL-2.0+
+#include <common.h>
+#include <io.h>
+#include <bootsource.h>
+#include <mach/rk3568-regs.h>
+#include <mach/rockchip.h>
+
+#define GRF_BASE		0xfdc60000
+#define GRF_GPIO1B_DS_2		0x218
+#define GRF_GPIO1B_DS_3		0x21c
+#define GRF_GPIO1C_DS_0		0x220
+#define GRF_GPIO1C_DS_1		0x224
+#define GRF_GPIO1C_DS_2		0x228
+#define GRF_GPIO1C_DS_3		0x22c
+#define GRF_GPIO1D_DS_0		0x230
+#define GRF_GPIO1D_DS_1		0x234
+#define GRF_SOC_CON4		0x510
+#define EDP_PHY_GRF_BASE	0xfdcb0000
+#define EDP_PHY_GRF_CON0	(EDP_PHY_GRF_BASE + 0x00)
+#define EDP_PHY_GRF_CON10	(EDP_PHY_GRF_BASE + 0x28)
+#define PMU_BASE_ADDR		0xfdd90000
+#define PMU_NOC_AUTO_CON0	0x70
+#define PMU_NOC_AUTO_CON1	0x74
+#define CRU_BASE		0xfdd20000
+#define CRU_SOFTRST_CON26	0x468
+#define CRU_SOFTRST_CON28	0x470
+#define SGRF_BASE		0xFDD18000
+#define SGRF_SOC_CON3		0xC
+#define SGRF_SOC_CON4		0x10
+#define PMUGRF_SOC_CON15	0xfdc20100
+#define CPU_GRF_BASE		0xfdc30000
+#define GRF_CORE_PVTPLL_CON0	0x10
+#define USBPHY_U3_GRF		0xfdca0000
+#define USBPHY_U3_GRF_CON1	(USBPHY_U3_GRF + 0x04)
+#define USBPHY_U2_GRF		0xfdca8000
+#define USBPHY_U2_GRF_CON0	(USBPHY_U2_GRF + 0x00)
+#define USBPHY_U2_GRF_CON1	(USBPHY_U2_GRF + 0x04)
+
+#define PMU_PWR_GATE_SFTCON	0xA0
+#define PMU_PWR_DWN_ST		0x98
+#define PMU_BUS_IDLE_SFTCON0	0x50
+#define PMU_BUS_IDLE_ST		0x68
+#define PMU_BUS_IDLE_ACK	0x60
+
+#define EBC_PRIORITY_REG	0xfe158008
+
+static void qos_priority_init(void)
+{
+	u32 delay;
+
+	/* enable all pd except npu and gpu */
+	writel(0xffff0000 & ~(BIT(0 + 16) | BIT(1 + 16)),
+	       PMU_BASE_ADDR + PMU_PWR_GATE_SFTCON);
+	delay = 1000;
+	do {
+		udelay(1);
+		delay--;
+		if (delay == 0) {
+			printf("Fail to set domain.");
+			hang();
+		}
+	} while (readl(PMU_BASE_ADDR + PMU_PWR_DWN_ST) & ~(BIT(0) | BIT(1)));
+
+	/* release all idle request except npu and gpu */
+	writel(0xffff0000 & ~(BIT(1 + 16) | BIT(2 + 16)),
+	       PMU_BASE_ADDR + PMU_BUS_IDLE_SFTCON0);
+
+	delay = 1000;
+	/* wait ack status */
+	do {
+		udelay(1);
+		delay--;
+		if (delay == 0) {
+			printf("Fail to get ack on domain.\n");
+			hang();
+		}
+	} while (readl(PMU_BASE_ADDR + PMU_BUS_IDLE_ACK) & ~(BIT(1) | BIT(2)));
+
+	delay = 1000;
+	/* wait idle status */
+	do {
+		udelay(1);
+		delay--;
+		if (delay == 0) {
+			printf("Fail to set idle on domain.\n");
+			hang();
+		}
+	} while (readl(PMU_BASE_ADDR + PMU_BUS_IDLE_ST) & ~(BIT(1) | BIT(2)));
+
+	writel(0x303, EBC_PRIORITY_REG);
+}
+
+int rk3568_lowlevel_init(void)
+{
+	/*
+	 * When perform idle operation, corresponding clock can
+	 * be opened or gated automatically.
+	 */
+	writel(0xffffffff, PMU_BASE_ADDR + PMU_NOC_AUTO_CON0);
+	writel(0x000f000f, PMU_BASE_ADDR + PMU_NOC_AUTO_CON1);
+
+	/* Set the emmc sdmmc0 to secure */
+	writel(((0x3 << 11 | 0x1 << 4) << 16), SGRF_BASE + SGRF_SOC_CON4);
+	/* set the emmc ds to level 2 */
+	writel(0x3f3f0707, GRF_BASE + GRF_GPIO1B_DS_2);
+	writel(0x3f3f0707, GRF_BASE + GRF_GPIO1B_DS_3);
+	writel(0x3f3f0707, GRF_BASE + GRF_GPIO1C_DS_0);
+	writel(0x3f3f0707, GRF_BASE + GRF_GPIO1C_DS_1);
+	writel(0x3f3f0707, GRF_BASE + GRF_GPIO1C_DS_2);
+	writel(0x3f3f0707, GRF_BASE + GRF_GPIO1C_DS_3);
+
+	/* Set the fspi to secure */
+	writel(((0x1 << 14) << 16) | (0x0 << 14), SGRF_BASE + SGRF_SOC_CON3);
+
+	/* Disable eDP phy by default */
+	writel(0x00070007, EDP_PHY_GRF_CON10);
+	writel(0x0ff10ff1, EDP_PHY_GRF_CON0);
+
+	/* Set core pvtpll ring length */
+	writel(0x00ff002b, CPU_GRF_BASE + GRF_CORE_PVTPLL_CON0);
+
+	/*
+	 * Assert reset the pipephy0, pipephy1 and pipephy2,
+	 * and de-assert reset them in Kernel combphy driver.
+	 */
+	writel(0x02a002a0, CRU_BASE + CRU_SOFTRST_CON28);
+
+	/*
+	 * Set USB 2.0 PHY0 port1 and PHY1 port0 and port1
+	 * enter suspend mode to to save power. And USB 2.0
+	 * PHY0 port0 for OTG interface still in normal mode.
+	 */
+	writel(0x01ff01d1, USBPHY_U3_GRF_CON1);
+	writel(0x01ff01d1, USBPHY_U2_GRF_CON0);
+	writel(0x01ff01d1, USBPHY_U2_GRF_CON1);
+
+	qos_priority_init();
+
+	return 0;
+}
+
+struct rk_bootsource {
+	enum bootsource src;
+	int instance;
+};
+
+static struct rk_bootsource bootdev_map[] = {
+	{ .src = BOOTSOURCE_UNKNOWN, .instance = 0 },
+	{ .src = BOOTSOURCE_NAND, .instance = 0 },
+	{ .src = BOOTSOURCE_MMC, .instance = 0 },
+	{ .src = BOOTSOURCE_SPI_NOR, .instance = 0 },
+	{ .src = BOOTSOURCE_SPI_NAND, .instance = 0 },
+	{ .src = BOOTSOURCE_MMC, .instance = 1 },
+};
+
+static enum bootsource rk3568_bootsource(void)
+{
+	u32 v;
+
+	v = readl(RK3568_IRAM_BASE + 0x10);
+
+	if (v >= ARRAY_SIZE(bootdev_map))
+		return BOOTSOURCE_UNKNOWN;
+
+	bootsource_set(bootdev_map[v].src);
+	bootsource_set_instance(bootdev_map[v].instance);
+
+	return bootdev_map[v].src;
+}
+
+int rk3568_init(void)
+{
+	rk3568_bootsource();
+
+	return 0;
+}
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index b0fbb49457..f0b2484c68 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -9,6 +9,8 @@ static int rockchip_init(void)
 		rk3188_init();
 	else if (of_machine_is_compatible("rockchip,rk3288"))
 		rk3288_init();
+	else if (of_machine_is_compatible("rockchip,rk3568"))
+		rk3568_init();
 	else
 		pr_err("Unknown rockchip SoC\n");
 
diff --git a/common/Kconfig b/common/Kconfig
index 8b8f80bbb3..273186c5fa 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1331,6 +1331,13 @@ config DEBUG_ROCKCHIP_RK3288_UART
 	  Say Y here if you want kernel low-level debugging support
 	  on RK3288.
 
+config DEBUG_ROCKCHIP_RK3568_UART
+	bool "RK3568 Debug UART"
+	depends on ARCH_RK3568
+	help
+	  Say Y here if you want kernel low-level debugging support
+	  on RK3568.
+
 config DEBUG_SOCFPGA_UART0
 	bool "Use SOCFPGA UART0 for low-level debug"
 	depends on ARCH_SOCFPGA
@@ -1417,7 +1424,8 @@ config DEBUG_OMAP_UART_PORT
 
 config DEBUG_ROCKCHIP_UART_PORT
 	int "RK3xxx UART debug port" if DEBUG_ROCKCHIP_RK3188_UART || \
-				DEBUG_ROCKCHIP_RK3288_UART
+				DEBUG_ROCKCHIP_RK3288_UART || \
+				DEBUG_ROCKCHIP_RK3568_UART
 	default 2
 	depends on ARCH_ROCKCHIP
 	help
diff --git a/firmware/Makefile b/firmware/Makefile
index 3a38c40079..00bdedfc6b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -9,7 +9,8 @@ firmware-$(CONFIG_FIRMWARE_IMX_LPDDR4_PMU_TRAIN) += \
 firmware-$(CONFIG_FIRMWARE_IMX8MM_ATF) += imx8mm-bl31.bin
 firmware-$(CONFIG_FIRMWARE_IMX8MP_ATF) += imx8mp-bl31.bin
 firmware-$(CONFIG_FIRMWARE_IMX8MQ_ATF) += imx8mq-bl31.bin
-
+firmware-$(CONFIG_ARCH_RK3568) += rk3568-bl31.bin
+firmware-$(CONFIG_ARCH_RK3568_OPTEE) += rk3568-op-tee.bin
 firmware-$(CONFIG_DRIVER_NET_FSL_FMAN) += fsl_fman_ucode_ls1046_r1.0_106_4_18.bin
 
 firmware-$(CONFIG_ARCH_LAYERSCAPE_PPA) += ppa-ls1046a.bin
diff --git a/include/bootsource.h b/include/bootsource.h
index 32295ddd96..646b0e91c1 100644
--- a/include/bootsource.h
+++ b/include/bootsource.h
@@ -12,6 +12,7 @@ enum bootsource {
 	BOOTSOURCE_SPI,
 	BOOTSOURCE_SPI_EEPROM,
 	BOOTSOURCE_SPI_NOR,
+	BOOTSOURCE_SPI_NAND,
 	BOOTSOURCE_SERIAL,
 	BOOTSOURCE_ONENAND,
 	BOOTSOURCE_HD,
-- 
2.29.2




More information about the barebox mailing list