summaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2021-11-15 14:21:20 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2021-11-15 14:21:20 +0100
commit0fdbd47ac4ff832f1c950db0b6ccb2eda3824158 (patch)
treeb6f121ca8017c89be96af2ff96d07f1f20e8f52c /arch/arm
parent42cdd1452a51ca970a6cda76e3bdbe4f04d6e13f (diff)
parenta1511452b8eb44cdce2e7e879b82d147e213654e (diff)
downloadbarebox-0fdbd47ac4ff832f1c950db0b6ccb2eda3824158.tar.gz
barebox-0fdbd47ac4ff832f1c950db0b6ccb2eda3824158.tar.xz
Merge branch 'for-next/rockchip'
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/boards/rockchip-rk3568-evb/board.c7
-rw-r--r--arch/arm/dts/rk3568-evb1-v10.dts22
-rw-r--r--arch/arm/include/asm/barebox-arm-head.h2
-rw-r--r--arch/arm/mach-rockchip/Kconfig5
-rw-r--r--arch/arm/mach-rockchip/Makefile1
-rw-r--r--arch/arm/mach-rockchip/atf.c53
-rw-r--r--arch/arm/mach-rockchip/bbu.c141
-rw-r--r--arch/arm/mach-rockchip/include/mach/bbu.h9
-rw-r--r--arch/arm/mach-rockchip/include/mach/rockchip.h2
-rw-r--r--arch/arm/mach-rockchip/rk3568.c16
-rw-r--r--arch/arm/mach-rockchip/rockchip.c15
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);