summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2021-06-21 11:27:57 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2021-06-28 09:38:06 +0200
commitb0dae6ee1e0e78bb5cfa52cf8ec55283730c276a (patch)
tree54c7c96ced71126ef03d936343d24546969dad68
parentbaf57b8e8df1b7303f5bd0aaaa47a3eed4284439 (diff)
downloadbarebox-b0dae6ee1e0e78bb5cfa52cf8ec55283730c276a.tar.gz
barebox-b0dae6ee1e0e78bb5cfa52cf8ec55283730c276a.tar.xz
ARM: Rockchip: Add rk3568 support
This adds basic support for the Rockchip rk3568 SoC. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Link: https://lore.barebox.org/20210615141641.31577-8-s.hauer@pengutronix.de Link: https://lore.barebox.org/20210621092802.27275-8-s.hauer@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/mach-rockchip/Kconfig18
-rw-r--r--arch/arm/mach-rockchip/Makefile2
-rw-r--r--arch/arm/mach-rockchip/atf.c62
-rw-r--r--arch/arm/mach-rockchip/include/mach/atf.h18
-rw-r--r--arch/arm/mach-rockchip/include/mach/bbu.h14
-rw-r--r--arch/arm/mach-rockchip/include/mach/debug_ll.h8
-rw-r--r--arch/arm/mach-rockchip/include/mach/rk3568-regs.h18
-rw-r--r--arch/arm/mach-rockchip/include/mach/rockchip.h11
-rw-r--r--arch/arm/mach-rockchip/rk3568.c176
-rw-r--r--arch/arm/mach-rockchip/rockchip.c2
-rw-r--r--common/Kconfig10
-rw-r--r--firmware/Makefile3
-rw-r--r--include/bootsource.h1
14 files changed, 341 insertions, 5 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cd25f73f12..c7ab166888 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..d0492da28f 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -1,3 +1,5 @@
obj-y += rockchip.o
+pbl-$(CONFIG_ARCH_RK3568) += 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,