From 484cde18daf38c981c01800448ba84050a17f710 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 21 Jun 2021 11:27:53 +0200 Subject: filetype: Add Rockchip boot image type Newer Rockchip SoCs boot images starting with the magic "RKNS". There are older image formats currently not supported, this one is at least supported on the RK3568. Signed-off-by: Sascha Hauer Link: https://lore.barebox.org/20210615141641.31577-4-s.hauer@pengutronix.de Link: https://lore.barebox.org/20210621092802.27275-4-s.hauer@pengutronix.de Signed-off-by: Sascha Hauer --- common/filetype.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'common') diff --git a/common/filetype.c b/common/filetype.c index 0cae00abaa..9edebb2cd8 100644 --- a/common/filetype.c +++ b/common/filetype.c @@ -73,6 +73,7 @@ static const struct filetype_str filetype_str[] = { [filetype_stm32_image_v1] = { "STM32 image (v1)", "stm32-image-v1" }, [filetype_zynq_image] = { "Zynq image", "zynq-image" }, [filetype_mxs_sd_image] = { "i.MX23/28 SD card image", "mxs-sd-image" }, + [filetype_rockchip_rkns_image] = { "Rockchip boot image", "rk-image" }, }; const char *file_type_to_string(enum filetype f) @@ -309,6 +310,8 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize) return filetype_riscv_linux_image; if (le32_to_cpu(buf[14]) == 0x56435352 && !memcmp(&buf[12], "barebox", 8)) return filetype_riscv_barebox_image; + if (strncmp(buf8, "RKNS", 4) == 0) + return filetype_rockchip_rkns_image; if ((buf8[0] == 0x5a || buf8[0] == 0x69 || buf8[0] == 0x78 || buf8[0] == 0x8b || buf8[0] == 0x9c) && buf8[0x1] == 0 && buf8[0x2] == 0 && buf8[0x3] == 0 && -- cgit v1.2.3 From b0dae6ee1e0e78bb5cfa52cf8ec55283730c276a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 21 Jun 2021 11:27:57 +0200 Subject: ARM: Rockchip: Add rk3568 support This adds basic support for the Rockchip rk3568 SoC. Signed-off-by: Sascha Hauer 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 --- arch/arm/Kconfig | 3 - arch/arm/mach-rockchip/Kconfig | 18 +++ arch/arm/mach-rockchip/Makefile | 2 + 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 ++ arch/arm/mach-rockchip/include/mach/debug_ll.h | 8 + arch/arm/mach-rockchip/include/mach/rk3568-regs.h | 18 +++ arch/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, 341 insertions(+), 5 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 (limited to 'common') 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 +#include +#include +#include +#include +#include + +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 + +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 #include #include +#include #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 +#include +#include +#include +#include + +#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, -- cgit v1.2.3