board: emulation: Add QEMU sbsa support
Add support for Arm sbsa [1] v0.3+ that is supported by QEMU [2].
Unlike other Arm based platforms the machine only provides a minimal
FDT that contains number of CPUs, ammount of memory and machine-version.
The boot firmware has to provide ACPI tables to the OS.
Due to this design a full DTB is added here as well that allows U-Boot's
driver to properly function. The DTB is appended at the end of the U-Boot
image and will be merged with the QEMU provided DTB.
In addition provide documentation how to use, enable binman to fabricate both
ROMs that are required to boot and add ACPI tables to make it full compatible
to the EDK2 reference implementation.
The board was tested using Fedora 40 Aarch64 Workstation. It's able
to boot from USB and AHCI or network.
Tested and found working:
- serial
- PCI
- xHCI
- Bochs display
- AHCI
- network using e1000e
- CPU init
- Booting Fedora 40
1: Server Base System Architecture (SBSA)
2: https://www.qemu.org/docs/master/system/arm/sbsa.html
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Cc: Peter Robinson <pbrobinson@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 263f85b..0d0c731 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1054,7 +1054,7 @@
imply DM_RNG
imply DM_RTC
imply RTC_PL031
- imply OF_HAS_PRIOR_STAGE
+ imply OF_HAS_PRIOR_STAGE if !TARGET_QEMU_ARM_SBSA
imply VIDEO
imply VIDEO_BOCHS
imply SYS_WHITE_ON_BLACK
@@ -2381,6 +2381,7 @@
source "board/cavium/thunderx/Kconfig"
source "board/eets/pdu001/Kconfig"
source "board/emulation/qemu-arm/Kconfig"
+source "board/emulation/qemu-sbsa/Kconfig"
source "board/freescale/ls2080aqds/Kconfig"
source "board/freescale/ls2080ardb/Kconfig"
source "board/freescale/ls1088a/Kconfig"
diff --git a/arch/arm/dts/qemu-sbsa.dts b/arch/arm/dts/qemu-sbsa.dts
new file mode 100644
index 0000000..ed00e50
--- /dev/null
+++ b/arch/arm/dts/qemu-sbsa.dts
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Devicetree with onboard devices for qemu_sbsa-ref for internal use only!
+ * DO NOT PASS TO THE OS!
+ *
+ * As QEMU provides only a minimal devicetree this one is merged with
+ * it and then fixed at runtime.
+ *
+ * Copyright 2024 9elements GmbH
+ */
+#include "configs/qemu-sbsa.h"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/dts-v1/;
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&intc>;
+ compatible = "linux,sbsa-ref";
+
+ binman: binman {
+ multiple-images;
+ };
+
+ cpus {
+ /* Filled by fdtdec_board_setup() */
+ };
+
+ memory {
+ /* Filled by fdtdec_board_setup() */
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ cfi_flash {
+ compatible = "cfi-flash";
+ reg = /bits/ 64 <SBSA_FLASH_BASE_ADDR
+ SBSA_FLASH_LENGTH>;
+ status = "okay";
+ };
+
+ uart0 {
+ compatible = "arm,pl011";
+ status = "okay";
+ reg = /bits/ 64 <SBSA_UART_BASE_ADDR
+ SBSA_UART_LENGTH>;
+ };
+
+ ahci {
+ compatible = "generic-ahci";
+ status = "okay";
+ reg = /bits/ 64 <0x60100000 0x00010000>;
+ };
+
+ xhci {
+ compatible = "generic-xhci";
+ status = "okay";
+ reg = /bits/ 64 <0x60110000 0x00010000>;
+ };
+
+ pci {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ compatible = "pci-host-ecam-generic";
+ device_type = "pci";
+ status = "okay";
+ reg = /bits/ 64 <0xf0000000 0x10000000>;
+ bus-range = <0 0xff>;
+ ranges = /bits/ 32 <0x01000000>,
+ /bits/ 64 <0
+ SBSA_PIO_BASE_ADDR
+ SBSA_PIO_LENGTH>,
+ /bits/ 32 <0x02000000>,
+ /bits/ 64 <SBSA_PCIE_MMIO_BASE_ADDR
+ SBSA_PCIE_MMIO_BASE_ADDR
+ SBSA_PCIE_MMIO_LENGTH>,
+ /bits/ 32 <0x43000000>,
+ /bits/ 64 <SBSA_PCIE_MMIO_HIGH_BASE_ADDR
+ SBSA_PCIE_MMIO_HIGH_BASE_ADDR
+ SBSA_PCIE_MMIO_HIGH_LENGTH>;
+ };
+ };
+
+ intc: interrupt-controller {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ status = "okay";
+ interrupt-controller;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ reg = /bits/ 64 <SBSA_GIC_DIST_BASE_ADDR SBSA_GIC_DIST_LENGTH>,
+ /bits/ 64 <SBSA_GIC_REDIST_BASE_ADDR SBSA_GIC_REDIST_LENGTH>,
+ /bits/ 64 <0 0>,
+ /bits/ 64 <SBSA_GIC_HBASE_ADDR SBSA_GIC_HBASE_LENGTH>,
+ /bits/ 64 <SBSA_GIC_VBASE_ADDR SBSA_GIC_VBASE_LENGTH>;
+ };
+
+ its {
+ compatible = "arm,gic-v3-its";
+ status = "disabled";
+ };
+};
+
+&binman {
+ secure-world {
+ filename = "secure-world.rom";
+ size = <SBSA_SECURE_FLASH_LENGTH>;
+
+ bl1 {
+ offset = <0x0>;
+ description = "ARM Trusted Firmware BL1";
+ filename = "bl1.bin";
+ type = "blob-ext";
+ };
+
+ fip {
+ offset = <0x12000>;
+ description = "ARM Trusted Firmware FIP";
+ filename = "fip.bin";
+ type = "blob-ext";
+ };
+ };
+
+ unsecure-world {
+ filename = "unsecure-world.rom";
+ size = <SBSA_FLASH_LENGTH>;
+
+ u-boot {
+ };
+ u-boot-dtb {
+ compress = "lz4";
+ };
+ };
+};
diff --git a/arch/arm/include/asm/arch-qemu-sbsa/boot0.h b/arch/arm/include/asm/arch-qemu-sbsa/boot0.h
new file mode 100644
index 0000000..4a1a254
--- /dev/null
+++ b/arch/arm/include/asm/arch-qemu-sbsa/boot0.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * sbsa-ref starts U-Boot in XIP memory. Need to relocate U-Boot
+ * to DRAM which is already up. Instead of using SPL this simple loader
+ * is being used.
+ */
+relocate_check:
+ /* x0 contains the pointer to FDT provided by ATF */
+ adr x1, _start /* x1 <- Runtime value of _start */
+ ldr x2, _TEXT_BASE /* x2 <- Linked value of _start */
+ subs x9, x1, x2 /* x9 <- Run-vs-link offset */
+ beq reset
+
+ adrp x1, __image_copy_start /* x2 <- address bits [31:12] */
+ add x1, x1, :lo12:__image_copy_start/* x2 <- address bits [11:00] */
+ adrp x3, __image_copy_end /* x3 <- address bits [31:12] */
+ add x3, x3, :lo12:__image_copy_end /* x3 <- address bits [11:00] */
+ add x3, x3, #0x100000 /* 1 MiB for the DTB found at _end */
+
+copy_loop:
+ ldp x10, x11, [x1], #16 /* copy from source address [x1] */
+ stp x10, x11, [x2], #16 /* copy to target address [x2] */
+ cmp x1, x3 /* until source end address [x3] */
+ b.lo copy_loop
+
+ isb
+ ldr x2, _TEXT_BASE /* x2 <- Linked value of _start */
+ br x2 /* Jump to linked address */
+ /* Never reaches this point */
+1:
+ wfi
+ b 1b
+
+relocate_done:
\ No newline at end of file
diff --git a/arch/arm/mach-qemu/Kconfig b/arch/arm/mach-qemu/Kconfig
index 186c358..9c06c6a 100644
--- a/arch/arm/mach-qemu/Kconfig
+++ b/arch/arm/mach-qemu/Kconfig
@@ -3,12 +3,6 @@
config SYS_VENDOR
default "emulation"
-config SYS_BOARD
- default "qemu-arm"
-
-config SYS_CONFIG_NAME
- default "qemu-arm"
-
choice
prompt "QEMU ARM architecture"
default TARGET_QEMU_ARM_64BIT
@@ -25,6 +19,36 @@
select ARM64
select BOARD_LATE_INIT
+config TARGET_QEMU_ARM_SBSA
+ bool "SBSA Reference"
+ select ARM64
+ select BINMAN
+ select BOARD_LATE_INIT
+ select ENABLE_ARM_SOC_BOOT0_HOOK
+ select MISC_INIT_R
endchoice
+if TARGET_QEMU_ARM_32BIT || TARGET_QEMU_ARM_64BIT
+
+config SYS_BOARD
+ default "qemu-arm"
+
+config SYS_CONFIG_NAME
+ default "qemu-arm"
+
+endif
+
+if TARGET_QEMU_ARM_SBSA
+
+config SYS_BOARD
+ default "qemu-sbsa"
+
+config SYS_CONFIG_NAME
+ default "qemu-sbsa"
+
+config SYS_SOC
+ default "qemu-sbsa"
+
+endif
+
endif