From 1207a257d66e6141824d00baf5495309e570dd2e Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 12 Oct 2021 09:33:46 +0200 Subject: ARM: Rockchip rk3568 EVB: Enable deep probe The rk3568 EVB board is successfully tested with deep probe support, enable it. Signed-off-by: Sascha Hauer Link: https://lore.barebox.org/20211012073352.4071559-3-s.hauer@pengutronix.de Signed-off-by: Sascha Hauer --- arch/arm/boards/rockchip-rk3568-evb/board.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/boards/rockchip-rk3568-evb/board.c b/arch/arm/boards/rockchip-rk3568-evb/board.c index 9cd84d7fb9..2d472d1331 100644 --- a/arch/arm/boards/rockchip-rk3568-evb/board.c +++ b/arch/arm/boards/rockchip-rk3568-evb/board.c @@ -10,6 +10,7 @@ #include #include #include +#include static bool machine_is_rk3568_evb = false; @@ -45,6 +46,8 @@ static struct driver_d rk3568_evb_board_driver = { }; coredevice_platform_driver(rk3568_evb_board_driver); +BAREBOX_DEEP_PROBE_ENABLE(rk3568_evb_of_match); + static int rk3568_evb_detect_hwid(void) { int ret; -- cgit v1.2.3 From 6668748f7b0c77e5c5549217c08c9429a5631ddb Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 12 Oct 2021 09:33:47 +0200 Subject: ARM: Rockchip: rk3568 EVB: use 64bit partition sizes The ofpart partition fixup will use #address-cells = <2> and #size-cells = <2>. Use the same in the dts file to make the diff between the live tree and its fixed version smaller. Signed-off-by: Sascha Hauer Link: https://lore.barebox.org/20211012073352.4071559-4-s.hauer@pengutronix.de Signed-off-by: Sascha Hauer --- arch/arm/dts/rk3568-evb1-v10.dts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/dts/rk3568-evb1-v10.dts b/arch/arm/dts/rk3568-evb1-v10.dts index bd583015e8..ebfd45ada8 100644 --- a/arch/arm/dts/rk3568-evb1-v10.dts +++ b/arch/arm/dts/rk3568-evb1-v10.dts @@ -472,17 +472,17 @@ partitions { compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; + #address-cells = <2>; + #size-cells = <2>; partition@8000 { label = "barebox"; - reg = <0x8000 0x400000>; + reg = <0x0 0x8000 0x0 0x400000>; }; environment_emmc: partition@408000 { label = "barebox-environment"; - reg = <0x408000 0x8000>; + reg = <0x0 0x408000 0x0 0x8000>; }; }; }; @@ -503,17 +503,17 @@ partitions { compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; + #address-cells = <2>; + #size-cells = <2>; partition@8000 { label = "barebox"; - reg = <0x8000 0x400000>; + reg = <0x0 0x8000 0x0 0x400000>; }; environment_sd: partition@408000 { label = "barebox-environment"; - reg = <0x408000 0x8000>; + reg = <0x0 0x408000 0x0 0x8000>; }; }; }; -- cgit v1.2.3 From e563d9723963d4468bd6a60f603d827941c7ff77 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 12 Oct 2021 09:33:50 +0200 Subject: ARM: rk3568: Detect USB boot The table of register content to bootsource mapping has been taken from the vendor U-Boot. This table lacks an entry for USB boot. Add this entry. It's unknown if this entry is entirely correct, it reflects the value read from the register when doing USB boot. Signed-off-by: Sascha Hauer Link: https://lore.barebox.org/20211012073352.4071559-7-s.hauer@pengutronix.de Signed-off-by: Sascha Hauer --- arch/arm/mach-rockchip/rk3568.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-rockchip/rk3568.c b/arch/arm/mach-rockchip/rk3568.c index fcf3cb7053..4e6d3eef88 100644 --- a/arch/arm/mach-rockchip/rk3568.c +++ b/arch/arm/mach-rockchip/rk3568.c @@ -145,12 +145,12 @@ struct rk_bootsource { }; 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 }, + [0x1] = { .src = BOOTSOURCE_NAND, .instance = 0 }, + [0x2] = { .src = BOOTSOURCE_MMC, .instance = 0 }, + [0x3] = { .src = BOOTSOURCE_SPI_NOR, .instance = 0 }, + [0x4] = { .src = BOOTSOURCE_SPI_NAND, .instance = 0 }, + [0x5] = { .src = BOOTSOURCE_MMC, .instance = 1 }, + [0xa] = { .src = BOOTSOURCE_USB, .instance = 0 }, }; static enum bootsource rk3568_bootsource(void) -- cgit v1.2.3 From 6c8c249deaa01f8c1c2b3381242f5e52273d25c6 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 12 Oct 2021 09:33:52 +0200 Subject: ARM: Rockchip: RK3568: implement failsafe barebox update The RK3568 ROM searches for valid boot images at different positions on SD/eMMC cards. This can be used to implement a failsafe barebox update which is immune against power failures. Signed-off-by: Sascha Hauer Link: https://lore.barebox.org/20211012073352.4071559-9-s.hauer@pengutronix.de Signed-off-by: Sascha Hauer --- arch/arm/boards/rockchip-rk3568-evb/board.c | 4 +- arch/arm/dts/rk3568-evb1-v10.dts | 10 -- arch/arm/mach-rockchip/Makefile | 1 + arch/arm/mach-rockchip/bbu.c | 141 ++++++++++++++++++++++++++++ arch/arm/mach-rockchip/include/mach/bbu.h | 9 +- 5 files changed, 150 insertions(+), 15 deletions(-) create mode 100644 arch/arm/mach-rockchip/bbu.c (limited to 'arch/arm') diff --git a/arch/arm/boards/rockchip-rk3568-evb/board.c b/arch/arm/boards/rockchip-rk3568-evb/board.c index 2d472d1331..09385bea29 100644 --- a/arch/arm/boards/rockchip-rk3568-evb/board.c +++ b/arch/arm/boards/rockchip-rk3568-evb/board.c @@ -28,8 +28,8 @@ static int rk3568_evb_probe(struct device_d *dev) else of_device_enable_path("/chosen/environment-emmc"); - rk3568_bbu_mmc_register("emmc", BBU_HANDLER_FLAG_DEFAULT, "/dev/emmc.barebox"); - rk3568_bbu_mmc_register("sd", 0, "/dev/sd.barebox"); + rk3568_bbu_mmc_register("emmc", BBU_HANDLER_FLAG_DEFAULT, "/dev/emmc"); + rk3568_bbu_mmc_register("sd", 0, "/dev/sd"); return 0; } diff --git a/arch/arm/dts/rk3568-evb1-v10.dts b/arch/arm/dts/rk3568-evb1-v10.dts index ebfd45ada8..6f1eebc619 100644 --- a/arch/arm/dts/rk3568-evb1-v10.dts +++ b/arch/arm/dts/rk3568-evb1-v10.dts @@ -475,11 +475,6 @@ #address-cells = <2>; #size-cells = <2>; - partition@8000 { - label = "barebox"; - reg = <0x0 0x8000 0x0 0x400000>; - }; - environment_emmc: partition@408000 { label = "barebox-environment"; reg = <0x0 0x408000 0x0 0x8000>; @@ -506,11 +501,6 @@ #address-cells = <2>; #size-cells = <2>; - partition@8000 { - label = "barebox"; - reg = <0x0 0x8000 0x0 0x400000>; - }; - environment_sd: partition@408000 { label = "barebox-environment"; reg = <0x0 0x408000 0x0 0x8000>; diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index ebaa3a5450..66bcdba2eb 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_ARCH_RK3188) += rk3188.o obj-$(CONFIG_ARCH_RK3288) += rk3288.o obj-pbl-$(CONFIG_ARCH_RK3568) += rk3568.o obj-$(CONFIG_ARCH_RK3568) += bootm.o +obj-$(CONFIG_BAREBOX_UPDATE) += bbu.o diff --git a/arch/arm/mach-rockchip/bbu.c b/arch/arm/mach-rockchip/bbu.c new file mode 100644 index 0000000000..71bbac27e8 --- /dev/null +++ b/arch/arm/mach-rockchip/bbu.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The MaskROM looks for images on these locations: */ +#define IMG_OFFSET_0 (0 * SZ_1K + SZ_32K) +#define IMG_OFFSET_1 (512 * SZ_1K + SZ_32K) +#define IMG_OFFSET_2 (1024 * SZ_1K + SZ_32K) +#define IMG_OFFSET_3 (1536 * SZ_1K + SZ_32K) +#define IMG_OFFSET_4 (2048 * SZ_1K + SZ_32K) + +#define RK3568_IRAM_ACTIVE_BOOT_SLOT GENMASK(12, 10) + +static int rk3568_get_active_slot(void) +{ + return FIELD_GET(RK3568_IRAM_ACTIVE_BOOT_SLOT, + readl(RK3568_IRAM_BASE + 0x14)); +} + +/* + * The strategy here is: + * The MaskROM iterates over the above five locations until it finds a valid + * boot image. The images are protected with sha sums, so any change to an + * image on disk is invalidating it. We first check if we have enough space to + * write two copies of barebox. To make it simple we only use IMG_OFFSET_0 and + * IMG_OFFSET_4 which leaves the maximum size for a single image. When there's + * not enough free space on the beginning of the disk we only write a single + * image. When we have enough space for two images we first write the inactive one + * (leaving the active one intact). Afterwards we write the active one which + * leaves the previously written inactive image as a fallback in case writing the + * first one gets interrupted. + */ +static int rk3568_bbu_mmc_handler(struct bbu_handler *handler, + struct bbu_data *data) +{ + enum filetype filetype; + int ret, fd, wr0, wr1; + loff_t space; + const char *cdevname; + + filetype = file_detect_type(data->image, data->len); + if (filetype != filetype_rockchip_rkns_image) { + if (!bbu_force(data, "incorrect image type. Expected: %s, got %s", + file_type_to_string(filetype_rockchip_rkns_image), + file_type_to_string(filetype))) + return -EINVAL; + } + + cdevname = devpath_to_name(data->devicefile); + + device_detect_by_name(cdevname); + + ret = bbu_confirm(data); + if (ret) + return ret; + + space = cdev_unallocated_space(cdev_by_name(cdevname)); + + if (space < IMG_OFFSET_0 + data->len) { + pr_err("Unallocated space on %s is too small for one image\n", + data->devicefile); + return -ENOSPC; + } + + fd = open(data->devicefile, O_WRONLY); + if (fd < 0) + return fd; + + if (space >= IMG_OFFSET_4 + data->len) { + int slot = rk3568_get_active_slot(); + + pr_info("Unallocated space is enough for two copies, doing failsafe update\n"); + + if (slot == 0) { + wr0 = IMG_OFFSET_4; + wr1 = IMG_OFFSET_0; + } else { + wr0 = IMG_OFFSET_0; + wr1 = IMG_OFFSET_4; + } + } else { + wr0 = IMG_OFFSET_0; + wr1 = 0; + } + + ret = pwrite_full(fd, data->image, data->len, wr0); + if (ret < 0) { + pr_err("writing to %s failed with %s\n", data->devicefile, + strerror(-ret)); + goto err_close; + } + + if (wr1) { + ret = pwrite_full(fd, data->image, data->len, wr1); + if (ret < 0) { + pr_err("writing to %s failed with %s\n", data->devicefile, + strerror(-ret)); + goto err_close; + } + } + + ret = 0; + +err_close: + close(fd); + + return ret; +} + +int rk3568_bbu_mmc_register(const char *name, unsigned long flags, + const char *devicefile) +{ + struct bbu_handler *handler; + int ret; + + handler = xzalloc(sizeof(*handler)); + + handler->flags = flags; + handler->devicefile = devicefile; + handler->name = name; + handler->handler = rk3568_bbu_mmc_handler; + + ret = bbu_register_handler(handler); + if (ret) + free(handler); + + return ret; +} diff --git a/arch/arm/mach-rockchip/include/mach/bbu.h b/arch/arm/mach-rockchip/include/mach/bbu.h index e61e0615e2..7fb08a0a9e 100644 --- a/arch/arm/mach-rockchip/include/mach/bbu.h +++ b/arch/arm/mach-rockchip/include/mach/bbu.h @@ -3,12 +3,15 @@ #include +#ifdef CONFIG_BAREBOX_UPDATE +int rk3568_bbu_mmc_register(const char *name, unsigned long flags, + const char *devicefile); +#else 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); - + return -ENOSYS; } +#endif # endif /* __MACH_ROCKCHIP_BBU_H */ -- cgit v1.2.3 From 170c9d4123c2263fbe9439dc073c7b343474beeb Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Mon, 8 Nov 2021 08:52:03 +0100 Subject: ARM: Rockchip: init: propagate error in init function The SoC init functions return an error code when run on a SoC without support compiled in. Propagate error codes, so this is reported to the user. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20211108075209.2366770-3-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/arm/mach-rockchip/rockchip.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index f0b2484c68..c185b0cc2b 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -6,14 +6,13 @@ static int rockchip_init(void) { if (of_machine_is_compatible("rockchip,rk3188")) - 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"); + return rk3188_init(); + if (of_machine_is_compatible("rockchip,rk3288")) + return rk3288_init(); + if (of_machine_is_compatible("rockchip,rk3568")) + return rk3568_init(); - return 0; + pr_err("Unknown rockchip SoC\n"); + return -ENODEV; } postcore_initcall(rockchip_init); -- cgit v1.2.3 From 0b0ef6d8e8344c283f5de77e033f1801346f9a0d Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Mon, 8 Nov 2021 08:52:04 +0100 Subject: ARM: Rockchip: rk3568: make rk3568_lowlevel_init void The lowlevel_init can't fail and there's no sane way to deal with an error that early anyway, so make return type void. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20211108075209.2366770-4-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/arm/mach-rockchip/include/mach/rockchip.h | 2 +- arch/arm/mach-rockchip/rk3568.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-rockchip/include/mach/rockchip.h b/arch/arm/mach-rockchip/include/mach/rockchip.h index 722b73d6f8..269d113bc3 100644 --- a/arch/arm/mach-rockchip/include/mach/rockchip.h +++ b/arch/arm/mach-rockchip/include/mach/rockchip.h @@ -28,6 +28,6 @@ static inline int rk3568_init(void) } #endif -int rk3568_lowlevel_init(void); +void rk3568_lowlevel_init(void); #endif /* __MACH_ROCKCHIP_H */ diff --git a/arch/arm/mach-rockchip/rk3568.c b/arch/arm/mach-rockchip/rk3568.c index 4e6d3eef88..234c6d22d1 100644 --- a/arch/arm/mach-rockchip/rk3568.c +++ b/arch/arm/mach-rockchip/rk3568.c @@ -90,7 +90,7 @@ static void qos_priority_init(void) writel(0x303, EBC_PRIORITY_REG); } -int rk3568_lowlevel_init(void) +void rk3568_lowlevel_init(void) { /* * When perform idle operation, corresponding clock can @@ -135,8 +135,6 @@ int rk3568_lowlevel_init(void) writel(0x01ff01d1, USBPHY_U2_GRF_CON1); qos_priority_init(); - - return 0; } struct rk_bootsource { -- cgit v1.2.3 From 6b2c6c9a4afb3d2c082d07f5019e82cb2ed0c0f3 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Mon, 8 Nov 2021 08:52:05 +0100 Subject: ARM64: : mark prologue location Unlike with ARM32, barebox prologue on ARM64 starts with the function prologue, because of the absence of the naked attribute. The code is written with that in mind (6 branches instead of 8 to account for the two instructions inserted by the compiler), but it's still suprising. Add a hint about that in the code. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20211108075209.2366770-5-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/arm/include/asm/barebox-arm-head.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/include/asm/barebox-arm-head.h b/arch/arm/include/asm/barebox-arm-head.h index 8409a77d2e..187d12c9fc 100644 --- a/arch/arm/include/asm/barebox-arm-head.h +++ b/arch/arm/include/asm/barebox-arm-head.h @@ -44,6 +44,8 @@ static inline void __barebox_arm_head(void) "1: b 1b\n" #endif #else + /* two instruction long function prologue */ + /* only use if stack is initialized! */ "b 2f\n" "nop\n" "nop\n" -- cgit v1.2.3 From da4ade48e94302d5779f48451ac4a706a8ceaa81 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Mon, 8 Nov 2021 08:52:08 +0100 Subject: ARM: Rockchip: make rk3568's atf_load_bl31 reusable Future support for rk3399 can use the same function, so move the bulk into a macro. We can't use a function here, because the function itself uses macros like IS_ENABLED() and get_builtin_firmware(), which we would have to call outside of the common code, reducing amount of code we share. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20211108075209.2366770-8-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/arm/mach-rockchip/atf.c | 53 ++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-rockchip/atf.c b/arch/arm/mach-rockchip/atf.c index 3c4c9d1c8a..de22784489 100644 --- a/arch/arm/mach-rockchip/atf.c +++ b/arch/arm/mach-rockchip/atf.c @@ -33,30 +33,35 @@ static unsigned long load_elf64_image_phdr(const void *elf) 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; +#define rockchip_atf_load_bl31(SOC, atf_bin, tee_bin, fdt) do { \ + const void *bl31_elf, *optee; \ + unsigned long bl31; \ + size_t bl31_elf_size, optee_size; \ + uintptr_t optee_load_address = 0; \ + \ + get_builtin_firmware(atf_bin, &bl31_elf, &bl31_elf_size); \ + \ + bl31 = load_elf64_image_phdr(bl31_elf); \ + \ + if (IS_ENABLED(CONFIG_ARCH_##SOC##_OPTEE)) { \ + optee_load_address = SOC##_OPTEE_LOAD_ADDRESS; \ + \ + get_builtin_firmware(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" (SOC##_BAREBOX_LOAD_ADDRESS - 16) : \ + "cc"); \ + \ + bl31_entry(bl31, optee_load_address, \ + SOC##_BAREBOX_LOAD_ADDRESS, (uintptr_t)fdt); \ +} while (0) \ - 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); +void rk3568_atf_load_bl31(void *fdt) +{ + rockchip_atf_load_bl31(RK3568, rk3568_bl31_bin, rk3568_op_tee_bin, fdt); } -- cgit v1.2.3 From a1511452b8eb44cdce2e7e879b82d147e213654e Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Mon, 8 Nov 2021 08:52:09 +0100 Subject: ARM: Rockchip: add delimiter between boards and board features The CONFIG_ARCH_RK3568_OPTEE is directly after the boards, has a very generic name and is selectable without CONFIG_ARCH_RK3568. Fix these. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20211108075209.2366770-9-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/arm/mach-rockchip/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 2786fadeaf..5ac3c0432d 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -53,8 +53,11 @@ config MACH_RK3568_EVB endmenu +comment "select board features:" + config ARCH_RK3568_OPTEE - bool "Build OP-TEE binary into barebox" + bool "Build rk3568 OP-TEE binary into barebox" + depends on ARCH_RK3568 help With this option enabled the RK3568 OP-TEE binary is compiled into barebox and started along with the BL31 trusted firmware. -- cgit v1.2.3