diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/boards/rockchip-rk3568-evb/board.c | 7 | ||||
-rw-r--r-- | arch/arm/dts/rk3568-evb1-v10.dts | 22 | ||||
-rw-r--r-- | arch/arm/include/asm/barebox-arm-head.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-rockchip/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/mach-rockchip/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-rockchip/atf.c | 53 | ||||
-rw-r--r-- | arch/arm/mach-rockchip/bbu.c | 141 | ||||
-rw-r--r-- | arch/arm/mach-rockchip/include/mach/bbu.h | 9 | ||||
-rw-r--r-- | arch/arm/mach-rockchip/include/mach/rockchip.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-rockchip/rk3568.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-rockchip/rockchip.c | 15 |
11 files changed, 209 insertions, 64 deletions
diff --git a/arch/arm/boards/rockchip-rk3568-evb/board.c b/arch/arm/boards/rockchip-rk3568-evb/board.c index 9cd84d7fb9..09385bea29 100644 --- a/arch/arm/boards/rockchip-rk3568-evb/board.c +++ b/arch/arm/boards/rockchip-rk3568-evb/board.c @@ -10,6 +10,7 @@ #include <environment.h> #include <globalvar.h> #include <magicvar.h> +#include <deep-probe.h> static bool machine_is_rk3568_evb = false; @@ -27,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; } @@ -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; diff --git a/arch/arm/dts/rk3568-evb1-v10.dts b/arch/arm/dts/rk3568-evb1-v10.dts index bd583015e8..6f1eebc619 100644 --- a/arch/arm/dts/rk3568-evb1-v10.dts +++ b/arch/arm/dts/rk3568-evb1-v10.dts @@ -472,17 +472,12 @@ partitions { compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@8000 { - label = "barebox"; - reg = <0x8000 0x400000>; - }; + #address-cells = <2>; + #size-cells = <2>; environment_emmc: partition@408000 { label = "barebox-environment"; - reg = <0x408000 0x8000>; + reg = <0x0 0x408000 0x0 0x8000>; }; }; }; @@ -503,17 +498,12 @@ partitions { compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@8000 { - label = "barebox"; - reg = <0x8000 0x400000>; - }; + #address-cells = <2>; + #size-cells = <2>; environment_sd: partition@408000 { label = "barebox-environment"; - reg = <0x408000 0x8000>; + reg = <0x0 0x408000 0x0 0x8000>; }; }; }; 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" diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index b2376c18d0..1ad7ccedf6 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -50,8 +50,11 @@ config MACH_RK3568_EVB help Say Y here if you are using a RK3568 EVB +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. 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/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); } 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 <common.h> +#include <malloc.h> +#include <bbu.h> +#include <filetype.h> +#include <errno.h> +#include <fs.h> +#include <fcntl.h> +#include <linux/sizes.h> +#include <linux/stat.h> +#include <ioctl.h> +#include <environment.h> +#include <mach/bbu.h> +#include <libfile.h> +#include <linux/bitfield.h> +#include <mach/rk3568-regs.h> + +/* 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 <bbu.h> +#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 */ 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 fcf3cb7053..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 { @@ -145,12 +143,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) 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); |