Modern Rockchip SoCs such as RK3576 require TF-A to be running to provide
firmware services to the OS. To enable booting Linux in Falcon mode on
such SoCs, add a binman template for generation of FIT images containing
appropriately split TF-A and TEE binaries (as is currently done by binman
for U-boot proper images), externally provided Linux kernel and optionally
an initrd.

Any FDTs provided to the generator will be pre-patched with a /chosen
node containing an initrd load address and size (if an initrd is provided)
and a bootargs property containing the kernel command line (if provided),
so that the kernel can be booted directly without external preprocessing.

A config fragment rockchip-falcon.config can be used to enable Falcon
mode boot and the building of TF-A+Falcon with binman, e.g.:

  make nanopi-m5-rk3576_defconfig \
        rockchip-falcon.config

This will produce a FIT image u-boot-rockchip-falcon.itb containing TF-A,
TEE, Linux kernel and optionally an initrd, which can be flashed to UFS
and booted in Falcon mode.

This can also be combined with the existing rockchip-ramboot.config
fragment to obtain images suitable for booting from RAM, e.g.:

  make nanopi-m5-rk3576_defconfig \
        rockchip-falcon.config \
        rockchip-ramboot.config

The resulting images can be uploaded directly to RAM via Maskrom with no
storage or USB loader required, e.g.:

  rockusb download-sram u-boot-rockchip-usb471.bin
  rockusb download-ddr u-boot-rockchip-usb472-falcon.bin

Signed-off-by: Alexey Charkov <[email protected]>
---
 arch/arm/dts/rockchip-u-boot.dtsi     | 204 ++++++++++++++++++++++++++++------
 arch/arm/mach-rockchip/Kconfig        |  49 ++++++++
 board/rockchip/rockchip-falcon.config |   3 +
 3 files changed, 225 insertions(+), 31 deletions(-)

diff --git a/arch/arm/dts/rockchip-u-boot.dtsi 
b/arch/arm/dts/rockchip-u-boot.dtsi
index 4ba6a87e78ab..5e23ff761751 100644
--- a/arch/arm/dts/rockchip-u-boot.dtsi
+++ b/arch/arm/dts/rockchip-u-boot.dtsi
@@ -35,6 +35,16 @@
 #define HAS_FIT
 #endif
 
+#ifdef CONFIG_ROCKCHIP_FALCON_IMAGE
+/* Falcon-mode load addresses, relative to the SoC DRAM base. */
+#define FALCON_KERNEL_LOAD \
+       (CFG_SYS_SDRAM_BASE + CONFIG_ROCKCHIP_FALCON_KERNEL_LOAD)
+#define FALCON_FDT_LOAD \
+       (CFG_SYS_SDRAM_BASE + CONFIG_ROCKCHIP_FALCON_FDT_LOAD)
+#define FALCON_INITRD_LOAD \
+       (CFG_SYS_SDRAM_BASE + CONFIG_ROCKCHIP_FALCON_INITRD_LOAD)
+#endif
+
 / {
        binman: binman {
                multiple-images;
@@ -44,37 +54,13 @@
 #ifdef CONFIG_SPL
 &binman {
 #ifdef HAS_FIT
-       fit_template: template-1 {
-               type = "fit";
 #ifdef CONFIG_ARM64
-               description = "FIT image for U-Boot with bl31 (TF-A)";
-#else
-               description = "FIT image with OP-TEE";
-#endif
-               #address-cells = <1>;
-               fit,fdt-list = "of-list";
-               fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
-               fit,align = <512>;
+       /*
+        * Shared ARM Trusted Firmware (BL31) and optional OP-TEE split-elf
+        * images, reused by both the U-Boot and Falcon Linux FIT templates.
+        */
+       fit_firmware_template: template-firmware {
                images {
-                       u-boot {
-                               description = "U-Boot";
-                               type = "standalone";
-                               os = "u-boot";
-                               arch = FIT_ARCH;
-                               compression = FIT_UBOOT_COMP;
-                               load = <CONFIG_TEXT_BASE>;
-                               entry = <CONFIG_TEXT_BASE>;
-                               u-boot-nodtb {
-                                       compress = FIT_UBOOT_COMP;
-                               };
-#ifdef FIT_HASH_ALGO
-                               hash {
-                                       algo = FIT_HASH_ALGO;
-                               };
-#endif
-                       };
-
-#ifdef CONFIG_ARM64
                        @atf-SEQ {
                                fit,operation = "split-elf";
                                description = "ARM Trusted Firmware";
@@ -114,7 +100,42 @@
                                };
 #endif
                        };
-#else /* !CONFIG_ARM64 */
+               };
+       };
+#endif /* CONFIG_ARM64 */
+
+       fit_template: template-1 {
+               type = "fit";
+#ifdef CONFIG_ARM64
+               description = "FIT image for U-Boot with bl31 (TF-A)";
+               insert-template = <&fit_firmware_template>;
+#else
+               description = "FIT image with OP-TEE";
+#endif
+               #address-cells = <1>;
+               fit,fdt-list = "of-list";
+               fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+               fit,align = <512>;
+               images {
+                       u-boot {
+                               description = "U-Boot";
+                               type = "standalone";
+                               os = "u-boot";
+                               arch = FIT_ARCH;
+                               compression = FIT_UBOOT_COMP;
+                               load = <CONFIG_TEXT_BASE>;
+                               entry = <CONFIG_TEXT_BASE>;
+                               u-boot-nodtb {
+                                       compress = FIT_UBOOT_COMP;
+                               };
+#ifdef FIT_HASH_ALGO
+                               hash {
+                                       algo = FIT_HASH_ALGO;
+                               };
+#endif
+                       };
+
+#ifndef CONFIG_ARM64
                        op-tee {
                                description = "OP-TEE";
                                type = "tee";
@@ -132,7 +153,7 @@
                                };
 #endif
                        };
-#endif /* CONFIG_ARM64 */
+#endif /* !CONFIG_ARM64 */
 
                        @fdt-SEQ {
                                description = "fdt-NAME";
@@ -161,6 +182,97 @@
                        };
                };
        };
+
+#ifdef CONFIG_ROCKCHIP_FALCON_IMAGE
+       fit_falcon_template: template-falcon {
+               type = "fit";
+               description = "FIT image for Falcon Linux with bl31 (TF-A)";
+               insert-template = <&fit_firmware_template>;
+               #address-cells = <1>;
+               fit,fdt-list = "of-list";
+               fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+               fit,align = <512>;
+
+               images {
+                       kernel {
+                               description = "Linux kernel";
+                               type = "kernel";
+                               arch = FIT_ARCH;
+                               os = "linux";
+                               compression = FIT_UBOOT_COMP;
+                               load = <FALCON_KERNEL_LOAD>;
+                               entry = <FALCON_KERNEL_LOAD>;
+
+                               linux-kernel {
+                                       compress = FIT_UBOOT_COMP;
+                               };
+#ifdef FIT_HASH_ALGO
+                               hash {
+                                       algo = FIT_HASH_ALGO;
+                               };
+#endif
+                       };
+
+                       ramdisk {
+                               description = "ramdisk";
+                               type = "ramdisk";
+                               arch = FIT_ARCH;
+                               compression = "none";
+                               load = <FALCON_INITRD_LOAD>;
+
+                               linux-initrd {
+                                       optional;
+                               };
+#ifdef FIT_HASH_ALGO
+                               hash {
+                                       algo = FIT_HASH_ALGO;
+                               };
+#endif
+                       };
+
+                       @fdt-SEQ {
+                               description = "fdt-NAME";
+                               type = "flat_dt";
+                               arch = FIT_ARCH;
+                               compression = "none";
+                               load = <FALCON_FDT_LOAD>;
+#ifdef CONFIG_USE_BOOTARGS
+                               fit,bootargs = CONFIG_BOOTARGS;
+#endif
+                               fit,initrd = "ramdisk";
+#ifdef FIT_HASH_ALGO
+                               hash {
+                                       algo = FIT_HASH_ALGO;
+                               };
+#endif
+                       };
+               };
+
+               configurations {
+                       default = "@config-DEFAULT-SEQ";
+                       @config-SEQ {
+                               description = "NAME.dtb";
+                               fit,firmware = "atf-1", "kernel", "ramdisk";
+                               fit,loadables;
+                               fit,compatible;
+                               fdt = "fdt-SEQ";
+#ifdef FIT_HASH_ALGO
+                               hash {
+                                       algo = FIT_HASH_ALGO;
+                               };
+#endif
+                       };
+               };
+       };
+
+       falcon-fit {
+               filename = "u-boot-rockchip-falcon.itb";
+
+               fit {
+                       insert-template = <&fit_falcon_template>;
+               };
+       };
+#endif
 #endif /* HAS_FIT */
 
        simple-bin {
@@ -260,6 +372,36 @@
                };
                };
        };
+
+#ifdef CONFIG_ROCKCHIP_FALCON_IMAGE
+       simple-bin-usb472-falcon {
+               filename = "u-boot-rockchip-usb472-falcon.bin";
+               pad-byte = <0x00>;
+
+               u-boot-spl {
+               };
+
+               payload {
+                       type = "section";
+                       align = <CONFIG_SYS_CACHELINE_SIZE>;
+                       /*
+                        * Must be named 'u-boot-any', unlike the non-Falcon
+                        * image which can call this 'fit': SPL declares
+                        * binman_sym(u_boot_any, image_pos) unconditionally, 
and
+                        * binman resolves that symbol against an entry of that
+                        * exact name or one called u-boot[-elf|-img|-nodtb].
+                        * Those only exist here by way of a U-Boot image inside
+                        * the FIT, which a Falcon FIT does not carry, so 
without
+                        * this name the symbol cannot be resolved and binman
+                        * fails. The type property is what selects the etype.
+                        */
+                       u-boot-any {
+                               type = "fit";
+                               insert-template = <&fit_falcon_template>;
+                       };
+               };
+       };
+#endif
 #endif /* CONFIG_ROCKCHIP_MASKROM_IMAGE */
 };
 #endif /* CONFIG_SPL */
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 1a2e7847c9e7..321afc0fbdf6 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -758,6 +758,55 @@ config ROCKCHIP_MASKROM_IMAGE
          Rockchip SoCs support maskrom mode boot over USB. Enable this
          option to produce maskrom mode boot images containing U-Boot.
 
+config ROCKCHIP_FALCON_IMAGE
+       bool "Build a Falcon mode image for Rockchip"
+       depends on SPL_OS_BOOT && ARM64 && SPL_ATF && SPL_FIT
+       help
+         Enable this option to produce a FIT image which SPL can use to boot
+         Linux directly via TF-A, bypassing U-Boot proper (Falcon mode).
+
+         The image bundles TF-A (BL31), an optional OP-TEE, a Linux kernel
+         and an optional initramfs, and its device trees are pre-patched with
+         a /chosen node so that no further processing is needed before boot.
+         The kernel is mandatory and must be supplied at build time with
+         LINUX_KERNEL=/path/to/Image; pass LINUX_INITRD=/path/to/initramfs to
+         include an initramfs as well.
+
+         This only controls image generation. Say N to build a Falcon-capable
+         SPL without bundling a kernel into the U-Boot image, for example when
+         the OS payload is assembled and written to storage separately.
+
+config ROCKCHIP_FALCON_KERNEL_LOAD
+       hex "Falcon mode kernel load offset"
+       depends on ROCKCHIP_FALCON_IMAGE
+       default 0x10000000
+       help
+         Offset from the start of DRAM at which the Falcon mode kernel is
+         loaded and entered.
+
+         All three Falcon mode load offsets have to be checked against the
+         memory layout of the SoC and of the firmware in use. None of the
+         three payloads may overlap each other, and none of them may overlap
+         the regions BL31 and OP-TEE are linked to run from - note that
+         binman splits their ELFs, so each of those occupies several regions
+         rather than one contiguous range.
+
+config ROCKCHIP_FALCON_FDT_LOAD
+       hex "Falcon mode devicetree load offset"
+       depends on ROCKCHIP_FALCON_IMAGE
+       default 0x1c000000
+       help
+         Offset from the start of DRAM at which the Falcon mode devicetree is
+         loaded. The same constraints as for the kernel offset apply.
+
+config ROCKCHIP_FALCON_INITRD_LOAD
+       hex "Falcon mode initramfs load offset"
+       depends on ROCKCHIP_FALCON_IMAGE
+       default 0x1e000000
+       help
+         Offset from the start of DRAM at which the Falcon mode initramfs is
+         loaded. The same constraints as for the kernel offset apply.
+
 config LNX_KRNL_IMG_TEXT_OFFSET_BASE
        default TEXT_BASE
 
diff --git a/board/rockchip/rockchip-falcon.config 
b/board/rockchip/rockchip-falcon.config
new file mode 100644
index 000000000000..ac903f16f46a
--- /dev/null
+++ b/board/rockchip/rockchip-falcon.config
@@ -0,0 +1,3 @@
+CONFIG_ROCKCHIP_FALCON_IMAGE=y
+CONFIG_SPL_OS_BOOT=y
+CONFIG_SYS_SPI_KERNEL_OFFS=0x0

-- 
2.54.0

Reply via email to