[PATCH v8 25/37] board: emulation: Add QEMU sbsa support
Moritz Fischer
moritzf at google.com
Tue Oct 15 11:11:54 CEST 2024
Hi Patrick,
On Mon, Oct 14, 2024 at 6:17 AM Patrick Rudolph
<patrick.rudolph at 9elements.com> wrote:
>
> 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 at 9elements.com>
> Cc: Peter Robinson <pbrobinson at gmail.com>
> Cc: Simon Glass <sjg at chromium.org>
> Cc: Tom Rini <trini at konsulko.com>
> ---
> Changelog v3:
> - Add GIC and GIC-ITS to devicetree
> - Select GICv3 driver
> - Drop acpi_fill_madt and use driver model instead
> Changelog v4:
> - Drop CPU platform code
> - Enhance the DT to allow MADT generation from DT
> Changelog v5:
> - Add full DT and place it at the end of U-Boot
> - Merge DT with QEMU's DT
> - Drop DT generation code
> - Fix flash region length
> - Drop enable_caches()
> - Support platforms that do not pass FDT in x0
> Changelog v6:
> - Update header order
> - Drop pad-byte from DT
> - select BINMAN_FDT
> - select E1000_NO_NVM
> - drop config.h include
> - drop a few CFG_ defines that were used for SPL
> Changelog v8:
> - Use /bits/ 64 in DT
> - Drop flash access helper functions
> - Add cfi-flash to DT
> - Mark secure-flash as no execute
> - Only use defines in DT when it's also used in other files
> ---
> arch/arm/Kconfig | 3 +-
> arch/arm/dts/qemu-sbsa.dts | 137 ++++++
> arch/arm/include/asm/arch-qemu-sbsa/boot0.h | 34 ++
> arch/arm/mach-qemu/Kconfig | 36 +-
> board/emulation/qemu-arm/MAINTAINERS | 2 +
> board/emulation/qemu-sbsa/Kconfig | 58 +++
> board/emulation/qemu-sbsa/Makefile | 8 +
> board/emulation/qemu-sbsa/acpi.c | 192 ++++++++
> board/emulation/qemu-sbsa/dsdt.asl | 483 ++++++++++++++++++++
> board/emulation/qemu-sbsa/lowlevel_init.S | 22 +
> board/emulation/qemu-sbsa/qemu-sbsa.c | 273 +++++++++++
> board/emulation/qemu-sbsa/qemu-sbsa.env | 14 +
> board/emulation/qemu-sbsa/qemu-sbsa.h | 38 ++
> board/emulation/qemu-sbsa/smc.c | 71 +++
> configs/qemu-arm-sbsa_defconfig | 10 +
> doc/board/emulation/index.rst | 1 +
> doc/board/emulation/qemu-sbsa.rst | 98 ++++
> doc/develop/driver-model/virtio.rst | 1 +
> include/configs/qemu-sbsa.h | 89 ++++
> 19 files changed, 1563 insertions(+), 7 deletions(-)
> create mode 100644 arch/arm/dts/qemu-sbsa.dts
> create mode 100644 arch/arm/include/asm/arch-qemu-sbsa/boot0.h
> create mode 100644 board/emulation/qemu-sbsa/Kconfig
> create mode 100644 board/emulation/qemu-sbsa/Makefile
> create mode 100644 board/emulation/qemu-sbsa/acpi.c
> create mode 100644 board/emulation/qemu-sbsa/dsdt.asl
> create mode 100644 board/emulation/qemu-sbsa/lowlevel_init.S
> create mode 100644 board/emulation/qemu-sbsa/qemu-sbsa.c
> create mode 100644 board/emulation/qemu-sbsa/qemu-sbsa.env
> create mode 100644 board/emulation/qemu-sbsa/qemu-sbsa.h
> create mode 100644 board/emulation/qemu-sbsa/smc.c
> create mode 100644 configs/qemu-arm-sbsa_defconfig
> create mode 100644 doc/board/emulation/qemu-sbsa.rst
> create mode 100644 include/configs/qemu-sbsa.h
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 263f85b0d0..0d0c731dd0 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1054,7 +1054,7 @@ config ARCH_QEMU
> 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/broadcom/bcmns3/Kconfig"
> 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 0000000000..d6f8a3ac58
> --- /dev/null
> +++ b/arch/arm/dts/qemu-sbsa.dts
> @@ -0,0 +1,137 @@
> +// 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"
> +
> +/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 = <1>;
> + status = "okay";
> + interrupt-controller;
> + interrupts = <25>;
> + 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";
> + };
I think usually its nodes are subnodes of the intc / gic node. See
examples here:
https://www.kernel.org/doc/Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic-v3.txt
> +};
> +
> +&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 0000000000..4a1a254b92
> --- /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 186c3582eb..9c06c6a3a5 100644
> --- a/arch/arm/mach-qemu/Kconfig
> +++ b/arch/arm/mach-qemu/Kconfig
> @@ -3,12 +3,6 @@ if ARCH_QEMU
> 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 @@ config TARGET_QEMU_ARM_64BIT
> 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
> diff --git a/board/emulation/qemu-arm/MAINTAINERS b/board/emulation/qemu-arm/MAINTAINERS
> index 5154262f29..7bc0ee698c 100644
> --- a/board/emulation/qemu-arm/MAINTAINERS
> +++ b/board/emulation/qemu-arm/MAINTAINERS
> @@ -4,5 +4,7 @@ S: Maintained
> F: board/emulation/qemu-arm/
> F: board/emulation/common/
> F: include/configs/qemu-arm.h
> +F: include/configs/qemu-sbsa.h
> F: configs/qemu_arm_defconfig
> F: configs/qemu_arm64_defconfig
> +F: configs/qemu-arm-sbsa_defconfig
> diff --git a/board/emulation/qemu-sbsa/Kconfig b/board/emulation/qemu-sbsa/Kconfig
> new file mode 100644
> index 0000000000..e8de29306c
> --- /dev/null
> +++ b/board/emulation/qemu-sbsa/Kconfig
> @@ -0,0 +1,58 @@
> +if TARGET_QEMU_ARM_SBSA
> +
> +config SYS_SOC
> + default "qemu-sbsa"
> +
> +config TEXT_BASE
> + default 0x10000100000
> +
> +config SYS_LOAD_ADDR
> + default 0x10000100000
> +
> +config PRE_CON_BUF_ADDR
> + default 0x100000FF000
> +
> +config DEFAULT_DEVICE_TREE
> + default "qemu-sbsa"
> +
> +config BOARD_SPECIFIC_OPTIONS # dummy
> + def_bool y
> + select AHCI
> + select ACPIGEN
> + select ACPI
> + select CPU
> + select CPU_ARMV8
> + select DM
> + select DM_USB
> + select DM_MTD
> + select GENERATE_ACPI_TABLE
> + select HAS_ROM
> + select MTD
> + select OF_LIBFDT_OVERLAY
> + select OF_SEPARATE
> + select PCI
> + select PCIE_ECAM_GENERIC
> + select USB
> + select GIC_V3
> + select GIC_V3_ITS
> + select SYS_FLASH_CFI_WIDTH_16BIT
> + imply AHCI_GENERIC
> + imply USB_XHCI_HCD
> + imply USB_XHCI_GENERIC
> + imply USB_STORAGE
> + imply E1000
> + imply E1000_NO_NVM
> + imply NET_RANDOM_ETHADDR
> + imply VIDEO_BOCHS
> + imply CFI_FLASH
> + imply SYS_MTDPARTS_RUNTIME
> + imply SET_DFU_ALT_INFO
> +
> +if DEBUG_UART
> +
> +config DEBUG_UART_BASE
> + default 0x60000000
> +endif
> +
> +source "board/emulation/common/Kconfig"
> +endif
> diff --git a/board/emulation/qemu-sbsa/Makefile b/board/emulation/qemu-sbsa/Makefile
> new file mode 100644
> index 0000000000..bacae320e7
> --- /dev/null
> +++ b/board/emulation/qemu-sbsa/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +obj-y += qemu-sbsa.o
> +obj-y += lowlevel_init.o
> +obj-y += smc.o
> +
> +obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt_generated.o
> +obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o
> diff --git a/board/emulation/qemu-sbsa/acpi.c b/board/emulation/qemu-sbsa/acpi.c
> new file mode 100644
> index 0000000000..ba85e08fc7
> --- /dev/null
> +++ b/board/emulation/qemu-sbsa/acpi.c
> @@ -0,0 +1,192 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2024 9elements GmbH
> + */
> +
> +#include <cpu.h>
> +#include <tables_csum.h>
> +#include <string.h>
> +#include <acpi/acpi_table.h>
> +#include <asm/acpi_table.h>
> +#include <asm/armv8/sec_firmware.h>
> +#include <configs/qemu-sbsa.h>
> +#include <dm/uclass.h>
> +#include <dm/device.h>
> +#include "qemu-sbsa.h"
> +
> +#define SBSAQEMU_MADT_GIC_VBASE 0x2c020000
> +#define SBSAQEMU_MADT_GIC_HBASE 0x2c010000
> +#define SBSAQEMU_MADT_GIC_PMU_IRQ 23
> +
> +#define SBSA_PLATFORM_WATCHDOG_COUNT 1
> +#define SBSA_PLATFORM_TIMER_COUNT (SBSA_PLATFORM_WATCHDOG_COUNT)
> +
> +#define L2_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | ACPI_PPTT_WRITE_ALLOC | \
> + (ACPI_PPTT_CACHE_TYPE_UNIFIED << \
> + ACPI_PPTT_CACHE_TYPE_SHIFT))
> +#define L2_SIZE 0x80000
> +#define L2_SETS 0x400
> +#define L2_WAYS 8
> +
> +#define L1D_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | ACPI_PPTT_WRITE_ALLOC | \
> + (ACPI_PPTT_CACHE_TYPE_DATA << \
> + ACPI_PPTT_CACHE_TYPE_SHIFT))
> +#define L1D_SIZE 0x8000
> +#define L1D_SETS 0x100
> +#define L1D_WAYS 2
> +
> +#define L1I_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | \
> + (ACPI_PPTT_CACHE_TYPE_INSTR << \
> + ACPI_PPTT_CACHE_TYPE_SHIFT))
> +#define L1I_SIZE 0x8000
> +#define L1I_SETS 0x100
> +#define L1I_WAYS 2
> +
> +int acpi_fill_iort(struct acpi_ctx *ctx)
> +{
> + u32 its_offset, smmu_offset;
> + u64 gic_its_base = 0;
> +
> + smc_get_gic_its_base(&gic_its_base);
> + if (gic_its_base == 0)
> + return 0;
> +
> + u32 identifiers[] = { 0 };
> +
> + its_offset = acpi_iort_add_its_group(ctx, ARRAY_SIZE(identifiers),
> + identifiers);
> +
> + struct acpi_iort_id_mapping map_smmu[] = {{
> + 0, 0xffff, 0, its_offset, 0
> + }};
> +
> + smmu_offset = acpi_iort_add_smmu_v3(ctx,
> + SBSA_SMMU_BASE_ADDR, // Base address
> + ACPI_IORT_SMMU_V3_COHACC_OVERRIDE, // Flags
> + 0, // VATOS address
> + 0, // SMMUv3 Model
> + 74, // Event
> + 75, // Pri
> + 77, // Gerror
> + 76, // Sync
> + 0, // Proximity domain
> + 1, // DevIDMappingIndex
> + ARRAY_SIZE(map_smmu),
> + map_smmu);
> +
> + struct acpi_iort_id_mapping map_rc[] = {{
> + 0, 0xffff, 0, smmu_offset, 0
> + }};
> +
> + acpi_iort_add_rc(ctx,
> + BIT(0) | BIT(56), // CacheCoherent + CPM
> + 0, // AtsAttribute
> + 0, // PciSegmentNumber
> + 64, // MemoryAddressSizeLimit
> + ARRAY_SIZE(map_rc),
> + map_rc);
> + return 0;
> +}
> +
> +void acpi_fill_fadt(struct acpi_fadt *fadt)
> +{
> + fadt->flags = ACPI_FADT_HW_REDUCED_ACPI | ACPI_FADT_LOW_PWR_IDLE_S0;
> + fadt->preferred_pm_profile = ACPI_PM_PERFORMANCE_SERVER;
> + fadt->arm_boot_arch = ACPI_ARM_PSCI_COMPLIANT;
> +}
> +
> +int acpi_fill_mcfg(struct acpi_ctx *ctx)
> +{
> + size_t size;
> +
> + /* PCI Segment Group 0, Start Bus Number 0, End Bus Number is 255 */
> + size = acpi_create_mcfg_mmconfig((void *)ctx->current,
> + SBSA_PCIE_ECAM_BASE_ADDR, 0, 0, 255);
> + acpi_inc(ctx, size);
> +
> + return 0;
> +}
> +
> +static int sbsa_write_gtdt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
> +{
> + struct acpi_table_header *header;
> + struct acpi_gtdt *gtdt;
> +
> + gtdt = ctx->current;
> + header = >dt->header;
> +
> + memset(gtdt, '\0', sizeof(struct acpi_gtdt));
> +
> + acpi_fill_header(header, "GTDT");
> + header->length = sizeof(struct acpi_gtdt);
> + header->revision = acpi_get_table_revision(ACPITAB_GTDT);
> +
> + gtdt->cnt_ctrl_base = 0xFFFFFFFFFFFFFFFF;
> + gtdt->sec_el1_gsiv = 29;
> + gtdt->sec_el1_flags = GTDT_FLAG_INT_ACTIVE_LOW;
> + gtdt->el1_gsiv = 30;
> + gtdt->el1_flags = GTDT_FLAG_INT_ACTIVE_LOW;
> + gtdt->virt_el1_gsiv = 27;
> + gtdt->virt_el1_flags = GTDT_FLAG_INT_ACTIVE_LOW;
> + gtdt->el2_gsiv = 26;
> + gtdt->el2_flags = GTDT_FLAG_INT_ACTIVE_LOW;
> + gtdt->cnt_read_base = 0xffffffffffffffff;
> +
> + // FIXME: VirtualPL2Timer
> + header->checksum = table_compute_checksum(header, header->length);
> +
> + acpi_add_table(ctx, gtdt);
> +
> + acpi_inc(ctx, sizeof(struct acpi_gtdt));
> +
> + return 0;
> +};
> +
> +ACPI_WRITER(5gtdt, "GTDT", sbsa_write_gtdt, 0);
> +
> +static int acpi_write_pptt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
> +{
> + struct acpi_table_header *header;
> + int cluster_offset, l2_offset;
> + u32 offsets[2];
> +
> + header = ctx->current;
> + ctx->tab_start = ctx->current;
> +
> + memset(header, '\0', sizeof(struct acpi_table_header));
> +
> + acpi_fill_header(header, "PPTT");
> + header->revision = acpi_get_table_revision(ACPITAB_PPTT);
> + acpi_inc(ctx, sizeof(*header));
> +
> + cluster_offset = acpi_pptt_add_proc(ctx, ACPI_PPTT_PHYSICAL_PACKAGE |
> + ACPI_PPTT_CHILDREN_IDENTICAL,
> + 0, 0, 0, NULL);
> +
> + l2_offset = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_VALID, 0, L2_SIZE,
> + L2_SETS, L2_WAYS, L2_ATTRIBUTES, 64);
> +
> + offsets[0] = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_VALID, l2_offset,
> + L1D_SIZE, L1D_SETS, L1D_WAYS,
> + L1D_ATTRIBUTES, 64);
> +
> + offsets[1] = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_BUT_WRITE_POL,
> + l2_offset, L1I_SIZE, L1I_SETS,
> + L1I_WAYS, L1I_ATTRIBUTES, 64);
> +
> + for (int i = 0; i < uclass_id_count(UCLASS_CPU); i++) {
> + acpi_pptt_add_proc(ctx, ACPI_PPTT_CHILDREN_IDENTICAL |
> + ACPI_PPTT_NODE_IS_LEAF | ACPI_PPTT_PROC_ID_VALID,
> + cluster_offset, i, 2, offsets);
> + }
> +
> + header->length = ctx->current - ctx->tab_start;
> + header->checksum = table_compute_checksum(header, header->length);
> +
> + acpi_inc(ctx, header->length);
> + acpi_add_table(ctx, header);
> +
> + return 0;
> +};
> +
> +ACPI_WRITER(5pptt, "PPTT", acpi_write_pptt, 0);
> diff --git a/board/emulation/qemu-sbsa/dsdt.asl b/board/emulation/qemu-sbsa/dsdt.asl
> new file mode 100644
> index 0000000000..f12cca04e2
> --- /dev/null
> +++ b/board/emulation/qemu-sbsa/dsdt.asl
> @@ -0,0 +1,483 @@
> +/** @file
> +* Differentiated System Description Table Fields (DSDT).
> +*
> +* Copyright (c) 2020, Linaro Ltd. All rights reserved.
> +*
> +* SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <configs/qemu-sbsa.h>
> +
> +#define LINK_DEVICE(Uid, LinkName, Irq) \
> + Device (LinkName) { \
> + Name (_HID, EISAID("PNP0C0F")) \
> + Name (_UID, Uid) \
> + Name (_PRS, ResourceTemplate() { \
> + Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { Irq } \
> + }) \
> + Method (_STA) { \
> + Return (0xF) \
> + } \
> + Method (_CRS, 0) { Return (_PRS) } \
> + Method (_SRS, 1) { } \
> + Method (_DIS) { } \
> + }
> +
> +#define PRT_ENTRY(Address, Pin, Link) \
> + Package (4) { \
> + Address, Pin, Link, Zero \
> + }
> +
> +DefinitionBlock ("Dsdt.aml", "DSDT", 2, "U-Boot", "SBSAQEMU", 2) {
> + Scope (_SB) {
> + // UART PL011
> + Device (COM0) {
> + Name (_HID, "ARMH0011")
> + Name (_UID, Zero)
> + Name (_CRS, ResourceTemplate () {
> + Memory32Fixed (ReadWrite,
> + SBSA_UART_BASE_ADDR,
> + SBSA_UART_LENGTH)
> + Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 33 }
> + })
> + Method (_STA) {
> + Return (0xF)
> + }
> + }
> +
> + // AHCI Host Controller
> + Device (AHC0) {
> + Name (_HID, "LNRO001E")
> + Name (_CLS, Package (3) {
> + 0x01,
> + 0x06,
> + 0x01,
> + })
> + Name (_CCA, 1)
> + Name (_CRS, ResourceTemplate() {
> + Memory32Fixed (ReadWrite,
> + SBSA_AHCI_BASE_ADDR,
> + SBSA_AHCI_LENGTH)
> + Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 42 }
> + })
> + Method (_STA) {
> + Return (0xF)
> + }
> + }
> +
> +
> + // USB XHCI Host Controller
> + Device (USB0) {
> + Name (_HID, "PNP0D10") // _HID: Hardware ID
> + Name (_UID, 0x00) // _UID: Unique ID
> + Name (_CCA, 0x01) // _CCA: Cache Coherency Attribute
> + Name (XHCI, 0xF) // will be set using AcpiLib
> + Method (_STA) {
> + Return (XHCI)
> + }
> + Name (_CRS, ResourceTemplate() {
> + Memory32Fixed (ReadWrite,
> + SBSA_XHCI_BASE_ADDR,
> + SBSA_XHCI_LENGTH)
> + Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 43 }
> + })
> +
> + // Root Hub
> + Device (RHUB) {
> + Name (_ADR, 0x00000000) // Address of Root Hub should be 0 as per ACPI 5.0 spec
> + Method (_STA) {
> + Return (0xF)
> + }
> +
> + // Ports connected to Root Hub
> + Device (HUB1) {
> + Name (_ADR, 0x00000001)
> + Name (_UPC, Package() {
> + 0x00, // Port is NOT connectable
> + 0xFF, // Don't care
> + 0x00000000, // Reserved 0 must be zero
> + 0x00000000 // Reserved 1 must be zero
> + })
> + Method (_STA) {
> + Return (0xF)
> + }
> +
> + Device (PRT1) {
> + Name (_ADR, 0x00000001)
> + Name (_UPC, Package() {
> + 0xFF, // Port is connectable
> + 0x00, // Port connector is A
> + 0x00000000,
> + 0x00000000
> + })
> + Name (_PLD, Package() {
> + Buffer(0x10) {
> + 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> + 0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> + }
> + })
> + Method (_STA) {
> + Return (0xF)
> + }
> + } // USB0_RHUB_HUB1_PRT1
> + Device (PRT2) {
> + Name (_ADR, 0x00000002)
> + Name (_UPC, Package() {
> + 0xFF, // Port is connectable
> + 0x00, // Port connector is A
> + 0x00000000,
> + 0x00000000
> + })
> + Name (_PLD, Package() {
> + Buffer(0x10) {
> + 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> + 0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> + }
> + })
> + Method (_STA) {
> + Return (0xF)
> + }
> + } // USB0_RHUB_HUB1_PRT2
> +
> + Device (PRT3) {
> + Name (_ADR, 0x00000003)
> + Name (_UPC, Package() {
> + 0xFF, // Port is connectable
> + 0x09, // Type C connector - USB2 and SS with Switch
> + 0x00000000,
> + 0x00000000
> + })
> + Name (_PLD, Package() {
> + Buffer (0x10) {
> + 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> + 0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> + }
> + })
> + Method (_STA) {
> + Return (0xF)
> + }
> + } // USB0_RHUB_HUB1_PRT3
> +
> + Device (PRT4) {
> + Name (_ADR, 0x00000004)
> + Name (_UPC, Package() {
> + 0xFF, // Port is connectable
> + 0x09, // Type C connector - USB2 and SS with Switch
> + 0x00000000,
> + 0x00000000
> + })
> + Name (_PLD, Package() {
> + Buffer (0x10){
> + 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> + 0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> + }
> + })
> + Method (_STA) {
> + Return (0xF)
> + }
> + } // USB0_RHUB_HUB1_PRT4
> + } // USB0_RHUB_HUB1
> + } // USB0_RHUB
> + } // USB0
> +
> + Device (PCI0)
> + {
> + Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge
> + Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge
> + Name (_SEG, Zero) // PCI Segment Group number
> + Name (_BBN, Zero) // PCI Base Bus Number
> + Name (_UID, "PCI0")
> + Name (_CCA, One) // Initially mark the PCI coherent (for JunoR1)
> +
> + Method (_STA) {
> + Return (0xF)
> + }
> +
> + Method (_CBA, 0, NotSerialized) {
> + return (SBSA_PCIE_ECAM_BASE_ADDR)
> + }
> +
> + LINK_DEVICE(0, GSI0, 0x23)
> + LINK_DEVICE(1, GSI1, 0x24)
> + LINK_DEVICE(2, GSI2, 0x25)
> + LINK_DEVICE(3, GSI3, 0x26)
> +
> + Name (_PRT, Package () // _PRT: PCI Routing Table
> + {
> + PRT_ENTRY(0x0000FFFF, 0, GSI0),
> + PRT_ENTRY(0x0000FFFF, 0, GSI1),
> + PRT_ENTRY(0x0000FFFF, 0, GSI2),
> + PRT_ENTRY(0x0000FFFF, 0, GSI3),
> +
> + PRT_ENTRY(0x0001FFFF, 0, GSI1),
> + PRT_ENTRY(0x0001FFFF, 1, GSI2),
> + PRT_ENTRY(0x0001FFFF, 2, GSI3),
> + PRT_ENTRY(0x0001FFFF, 3, GSI0),
> +
> + PRT_ENTRY(0x0002FFFF, 0, GSI2),
> + PRT_ENTRY(0x0002FFFF, 1, GSI3),
> + PRT_ENTRY(0x0002FFFF, 2, GSI0),
> + PRT_ENTRY(0x0002FFFF, 3, GSI1),
> +
> + PRT_ENTRY(0x0003FFFF, 0, GSI3),
> + PRT_ENTRY(0x0003FFFF, 1, GSI0),
> + PRT_ENTRY(0x0003FFFF, 2, GSI1),
> + PRT_ENTRY(0x0003FFFF, 3, GSI2),
> +
> + PRT_ENTRY(0x0004FFFF, 0, GSI0),
> + PRT_ENTRY(0x0004FFFF, 1, GSI1),
> + PRT_ENTRY(0x0004FFFF, 2, GSI2),
> + PRT_ENTRY(0x0004FFFF, 3, GSI3),
> +
> + PRT_ENTRY(0x0005FFFF, 0, GSI1),
> + PRT_ENTRY(0x0005FFFF, 1, GSI2),
> + PRT_ENTRY(0x0005FFFF, 2, GSI3),
> + PRT_ENTRY(0x0005FFFF, 3, GSI0),
> +
> + PRT_ENTRY(0x0006FFFF, 0, GSI2),
> + PRT_ENTRY(0x0006FFFF, 1, GSI3),
> + PRT_ENTRY(0x0006FFFF, 2, GSI0),
> + PRT_ENTRY(0x0006FFFF, 3, GSI1),
> +
> + PRT_ENTRY(0x0007FFFF, 0, GSI3),
> + PRT_ENTRY(0x0007FFFF, 1, GSI0),
> + PRT_ENTRY(0x0007FFFF, 2, GSI1),
> + PRT_ENTRY(0x0007FFFF, 3, GSI2),
> +
> + PRT_ENTRY(0x0008FFFF, 0, GSI0),
> + PRT_ENTRY(0x0008FFFF, 1, GSI1),
> + PRT_ENTRY(0x0008FFFF, 2, GSI2),
> + PRT_ENTRY(0x0008FFFF, 3, GSI3),
> +
> + PRT_ENTRY(0x0009FFFF, 0, GSI1),
> + PRT_ENTRY(0x0009FFFF, 1, GSI2),
> + PRT_ENTRY(0x0009FFFF, 2, GSI3),
> + PRT_ENTRY(0x0009FFFF, 3, GSI0),
> +
> + PRT_ENTRY(0x000AFFFF, 0, GSI2),
> + PRT_ENTRY(0x000AFFFF, 1, GSI3),
> + PRT_ENTRY(0x000AFFFF, 2, GSI0),
> + PRT_ENTRY(0x000AFFFF, 3, GSI1),
> +
> + PRT_ENTRY(0x000BFFFF, 0, GSI3),
> + PRT_ENTRY(0x000BFFFF, 1, GSI0),
> + PRT_ENTRY(0x000BFFFF, 2, GSI1),
> + PRT_ENTRY(0x000BFFFF, 3, GSI2),
> +
> + PRT_ENTRY(0x000CFFFF, 0, GSI0),
> + PRT_ENTRY(0x000CFFFF, 1, GSI1),
> + PRT_ENTRY(0x000CFFFF, 2, GSI2),
> + PRT_ENTRY(0x000CFFFF, 3, GSI3),
> +
> + PRT_ENTRY(0x000DFFFF, 0, GSI1),
> + PRT_ENTRY(0x000DFFFF, 1, GSI2),
> + PRT_ENTRY(0x000DFFFF, 2, GSI3),
> + PRT_ENTRY(0x000DFFFF, 3, GSI0),
> +
> + PRT_ENTRY(0x000EFFFF, 0, GSI2),
> + PRT_ENTRY(0x000EFFFF, 1, GSI3),
> + PRT_ENTRY(0x000EFFFF, 2, GSI0),
> + PRT_ENTRY(0x000EFFFF, 3, GSI1),
> +
> + PRT_ENTRY(0x000FFFFF, 0, GSI3),
> + PRT_ENTRY(0x000FFFFF, 1, GSI0),
> + PRT_ENTRY(0x000FFFFF, 2, GSI1),
> + PRT_ENTRY(0x000FFFFF, 3, GSI2),
> +
> + PRT_ENTRY(0x0010FFFF, 0, GSI0),
> + PRT_ENTRY(0x0010FFFF, 1, GSI1),
> + PRT_ENTRY(0x0010FFFF, 2, GSI2),
> + PRT_ENTRY(0x0010FFFF, 3, GSI3),
> +
> + PRT_ENTRY(0x0011FFFF, 0, GSI1),
> + PRT_ENTRY(0x0011FFFF, 1, GSI2),
> + PRT_ENTRY(0x0011FFFF, 2, GSI3),
> + PRT_ENTRY(0x0011FFFF, 3, GSI0),
> +
> + PRT_ENTRY(0x0012FFFF, 0, GSI2),
> + PRT_ENTRY(0x0012FFFF, 1, GSI3),
> + PRT_ENTRY(0x0012FFFF, 2, GSI0),
> + PRT_ENTRY(0x0012FFFF, 3, GSI1),
> +
> + PRT_ENTRY(0x0013FFFF, 0, GSI3),
> + PRT_ENTRY(0x0013FFFF, 1, GSI0),
> + PRT_ENTRY(0x0013FFFF, 2, GSI1),
> + PRT_ENTRY(0x0013FFFF, 3, GSI2),
> +
> + PRT_ENTRY(0x0014FFFF, 0, GSI0),
> + PRT_ENTRY(0x0014FFFF, 1, GSI1),
> + PRT_ENTRY(0x0014FFFF, 2, GSI2),
> + PRT_ENTRY(0x0014FFFF, 3, GSI3),
> +
> + PRT_ENTRY(0x0015FFFF, 0, GSI1),
> + PRT_ENTRY(0x0015FFFF, 1, GSI2),
> + PRT_ENTRY(0x0015FFFF, 2, GSI3),
> + PRT_ENTRY(0x0015FFFF, 3, GSI0),
> +
> + PRT_ENTRY(0x0016FFFF, 0, GSI2),
> + PRT_ENTRY(0x0016FFFF, 1, GSI3),
> + PRT_ENTRY(0x0016FFFF, 2, GSI0),
> + PRT_ENTRY(0x0016FFFF, 3, GSI1),
> +
> + PRT_ENTRY(0x0017FFFF, 0, GSI3),
> + PRT_ENTRY(0x0017FFFF, 1, GSI0),
> + PRT_ENTRY(0x0017FFFF, 2, GSI1),
> + PRT_ENTRY(0x0017FFFF, 3, GSI2),
> +
> + PRT_ENTRY(0x0018FFFF, 0, GSI0),
> + PRT_ENTRY(0x0018FFFF, 1, GSI1),
> + PRT_ENTRY(0x0018FFFF, 2, GSI2),
> + PRT_ENTRY(0x0018FFFF, 3, GSI3),
> +
> + PRT_ENTRY(0x0019FFFF, 0, GSI1),
> + PRT_ENTRY(0x0019FFFF, 1, GSI2),
> + PRT_ENTRY(0x0019FFFF, 2, GSI3),
> + PRT_ENTRY(0x0019FFFF, 3, GSI0),
> +
> + PRT_ENTRY(0x001AFFFF, 0, GSI2),
> + PRT_ENTRY(0x001AFFFF, 1, GSI3),
> + PRT_ENTRY(0x001AFFFF, 2, GSI0),
> + PRT_ENTRY(0x001AFFFF, 3, GSI1),
> +
> + PRT_ENTRY(0x001BFFFF, 0, GSI3),
> + PRT_ENTRY(0x001BFFFF, 1, GSI0),
> + PRT_ENTRY(0x001BFFFF, 2, GSI1),
> + PRT_ENTRY(0x001BFFFF, 3, GSI2),
> +
> + PRT_ENTRY(0x001CFFFF, 0, GSI0),
> + PRT_ENTRY(0x001CFFFF, 1, GSI1),
> + PRT_ENTRY(0x001CFFFF, 2, GSI2),
> + PRT_ENTRY(0x001CFFFF, 3, GSI3),
> +
> + PRT_ENTRY(0x001DFFFF, 0, GSI1),
> + PRT_ENTRY(0x001DFFFF, 1, GSI2),
> + PRT_ENTRY(0x001DFFFF, 2, GSI3),
> + PRT_ENTRY(0x001DFFFF, 3, GSI0),
> +
> + PRT_ENTRY(0x001EFFFF, 0, GSI2),
> + PRT_ENTRY(0x001EFFFF, 1, GSI3),
> + PRT_ENTRY(0x001EFFFF, 2, GSI0),
> + PRT_ENTRY(0x001EFFFF, 3, GSI1),
> +
> + PRT_ENTRY(0x001FFFFF, 0, GSI3),
> + PRT_ENTRY(0x001FFFFF, 1, GSI0),
> + PRT_ENTRY(0x001FFFFF, 2, GSI1),
> + PRT_ENTRY(0x001FFFFF, 3, GSI2),
> + })
> +
> + // Root complex resources
> + Name (_CRS, ResourceTemplate () {
> + WordBusNumber ( // Bus numbers assigned to this root
> + ResourceProducer,
> + MinFixed, MaxFixed, PosDecode,
> + 0, // AddressGranularity
> + 0, // AddressMinimum - Minimum Bus Number
> + 0xff,// AddressMaximum - Maximum Bus Number
> + 0, // AddressTranslation - Set to 0
> + 256 // RangeLength - Number of Busses
> + )
> +
> + // IO to mmio window
> + QWordIO (
> + ResourceProducer, MinFixed,
> + MaxFixed, PosDecode,
> + EntireRange,
> + 0x00000000, // Granularity
> + 0x0000, // Min Base Address
> + 0xffff, // Max Base Address
> + SBSA_PIO_BASE_ADDR, // Translate
> + SBSA_PIO_LENGTH // Length
> + )
> +
> + DWordMemory ( // 32-bit BAR Windows
> + ResourceProducer, PosDecode,
> + MinFixed, MaxFixed,
> + Cacheable, ReadWrite,
> + 0x00000000, // Granularity
> + SBSA_PCIE_MMIO_BASE_ADDR, // Min Base Address
> + SBSA_PCIE_MMIO_END, // Max Base Address
> + 0, // Translate
> + SBSA_PCIE_MMIO_LENGTH // Length
> + )
> +
> + QWordMemory ( // 64-bit BAR Windows
> + ResourceProducer, PosDecode,
> + MinFixed, MaxFixed,
> + Cacheable, ReadWrite,
> + 0x00000000, // Granularity
> + SBSA_PCIE_MMIO_HIGH_BASE_ADDR, // Min Base Address
> + SBSA_PCIE_MMIO_HIGH_END, // Max Base Address
> + 0, // Translate
> + SBSA_PCIE_MMIO_HIGH_LENGTH // Length
> + )
> + }) // Name(_CRS)
> +
> + Device (RES0)
> + {
> + Name (_HID, "PNP0C02" /* PNP Motherboard Resources */) // _HID: Hardware ID
> + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
> + {
> + QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
> + 0x0000000000000000, // Granularity
> + SBSA_PCIE_ECAM_BASE_ADDR, // Range Minimum
> + SBSA_PCIE_ECAM_END, // Range Maximum
> + 0x0000000000000000, // Translation Offset
> + SBSA_PCIE_ECAM_LENGTH, // Length
> + ,, , AddressRangeMemory, TypeStatic)
> + })
> + Method (_STA) {
> + Return (0xF)
> + }
> + }
> +
> + // OS Control Handoff
> + Name (SUPP, Zero) // PCI _OSC Support Field value
> + Name (CTRL, Zero) // PCI _OSC Control Field value
> +
> + /*
> + * See [1] 6.2.10, [2] 4.5
> + */
> + Method (_OSC,4) {
> + // Check for proper UUID
> + If (Arg0 == ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")) {
> + // Create DWord-adressable fields from the Capabilities Buffer
> + CreateDWordField (Arg3,0,CDW1)
> + CreateDWordField (Arg3,4,CDW2)
> + CreateDWordField (Arg3,8,CDW3)
> +
> + // Save Capabilities DWord2 & 3
> + Store (CDW2,SUPP)
> + Store (CDW3,CTRL)
> +
> + // Only allow native hot plug control if OS supports:
> + // * ASPM
> + // * Clock PM
> + // * MSI/MSI-X
> + If ((SUPP & 0x16) != 0x16) {
> + CTRL &= 0x1E // Mask bit 0 (and undefined bits)
> + }
> +
> + // Always allow native PME, AER (no dependencies)
> +
> + // Never allow SHPC (no SHPC controller in this system)
> + CTRL &= 0x1D
> +
> + If (Arg1 != One) { // Unknown revision
> + CDW1 |= 0x08
> + }
> +
> + If (CDW3 != CTRL) { // Capabilities bits were masked
> + CDW1 |= 0x10
> + }
> +
> + // Update DWORD3 in the buffer
> + Store (CTRL,CDW3)
> + Return (Arg3)
> + } Else {
> + CDW1 |= 4 // Unrecognized UUID
> + Return (Arg3)
> + }
> + } // End _OSC
> + }
> + } // Scope (_SB)
> +}
> diff --git a/board/emulation/qemu-sbsa/lowlevel_init.S b/board/emulation/qemu-sbsa/lowlevel_init.S
> new file mode 100644
> index 0000000000..c997721af9
> --- /dev/null
> +++ b/board/emulation/qemu-sbsa/lowlevel_init.S
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2016
> + * Cédric Schieli <cschieli at gmail.com>
> + */
> +
> +#include <config.h>
> +
> +/*
> + * Routine: save_boot_params (called after reset from start.S)
> + * Description: save ATAG/FDT address provided by the firmware at boot time
> + */
> +
> +.global save_boot_params
> +save_boot_params:
> + /* The firmware provided ATAG/FDT address can be found in r2/x0 */
> + adr x8, fw_dtb_pointer
> + str x0, [x8]
> +
> +
> + /* Returns */
> + b save_boot_params_ret
> diff --git a/board/emulation/qemu-sbsa/qemu-sbsa.c b/board/emulation/qemu-sbsa/qemu-sbsa.c
> new file mode 100644
> index 0000000000..3943c92432
> --- /dev/null
> +++ b/board/emulation/qemu-sbsa/qemu-sbsa.c
> @@ -0,0 +1,273 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2017 Tuomas Tynkkynen
> + */
> +
> +#include <cpu_func.h>
> +#include <dm.h>
> +#include <env.h>
> +#include <fdtdec.h>
> +#include <fdt_support.h>
> +#include <init.h>
> +#include <log.h>
> +#include <usb.h>
> +#include <asm/armv8/mmu.h>
> +
> +#include "qemu-sbsa.h"
> +
> +/* Assigned in lowlevel_init.S
> + * Push the variable into the .data section so that it
> + * does not get cleared later.
> + */
> +unsigned long __section(".data") fw_dtb_pointer;
> +
> +static struct mm_region qemu_sbsa_mem_map[] = {
> + {
> + /* Secure flash */
> + .virt = SBSA_SECURE_FLASH_BASE_ADDR,
> + .phys = SBSA_SECURE_FLASH_BASE_ADDR,
> + .size = SBSA_SECURE_FLASH_LENGTH,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> + PTE_BLOCK_INNER_SHARE |
> + PTE_BLOCK_PXN | PTE_BLOCK_UXN
> + }, {
> + /* Flash */
> + .virt = SBSA_FLASH_BASE_ADDR,
> + .phys = SBSA_FLASH_BASE_ADDR,
> + .size = SBSA_FLASH_LENGTH,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> + PTE_BLOCK_INNER_SHARE
> + }, {
> + /* Lowmem peripherals */
> + .virt = SBSA_PERIPH_BASE_ADDR,
> + .phys = SBSA_PERIPH_BASE_ADDR,
> + .size = SBSA_PCIE_MMIO_BASE_ADDR - SBSA_PERIPH_BASE_ADDR,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> + PTE_BLOCK_NON_SHARE |
> + PTE_BLOCK_PXN | PTE_BLOCK_UXN
> + }, {
> + /* 32-bit address PCIE MMIO space */
> + .virt = SBSA_PCIE_MMIO_BASE_ADDR,
> + .phys = SBSA_PCIE_MMIO_BASE_ADDR,
> + .size = SBSA_PCIE_MMIO_LENGTH,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> + PTE_BLOCK_NON_SHARE |
> + PTE_BLOCK_PXN | PTE_BLOCK_UXN
> + }, {
> + /* PCI-E ECAM memory area */
> + .virt = SBSA_PCIE_ECAM_BASE_ADDR,
> + .phys = SBSA_PCIE_ECAM_BASE_ADDR,
> + .size = SBSA_PCIE_ECAM_LENGTH,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> + PTE_BLOCK_NON_SHARE |
> + PTE_BLOCK_PXN | PTE_BLOCK_UXN
> + }, {
> + /* Highmem PCI-E MMIO memory area */
> + .virt = SBSA_PCIE_MMIO_HIGH_BASE_ADDR,
> + .phys = SBSA_PCIE_MMIO_HIGH_BASE_ADDR,
> + .size = SBSA_PCIE_MMIO_HIGH_LENGTH,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> + PTE_BLOCK_NON_SHARE |
> + PTE_BLOCK_PXN | PTE_BLOCK_UXN
> + }, {
> + /* DRAM */
> + .virt = SBSA_MEM_BASE_ADDR,
> + .phys = SBSA_MEM_BASE_ADDR,
> + .size = 0x800000000000ULL,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> + PTE_BLOCK_INNER_SHARE
> + }, {
> + /* List terminator */
> + 0,
> + }
> +};
> +
> +struct mm_region *mem_map = qemu_sbsa_mem_map;
> +
> +int board_late_init(void)
> +{
> + /* start usb so that usb keyboard can be used as input device */
> + if (CONFIG_IS_ENABLED(USB_KEYBOARD))
> + usb_init();
> +
> + return 0;
> +}
> +
> +int board_init(void)
> +{
> + return 0;
> +}
> +
> +/**
> + * dtb_dt_qemu - Return the address of the QEMU provided FDT.
> + *
> + * @return: Pointer to FDT or NULL on failure
> + */
> +static void *dtb_dt_qemu(void)
> +{
> + /* FDT might be at start of DRAM */
> + if (fdt_magic(SBSA_MEM_BASE_ADDR) == FDT_MAGIC)
> + return (void *)(u64)SBSA_MEM_BASE_ADDR;
> +
> + /* When ARM_LINUX_KERNEL_AS_BL33 is enabled in ATF, it's passed in x0 */
> + if (fw_dtb_pointer >= SBSA_MEM_BASE_ADDR &&
> + fdt_magic(fw_dtb_pointer) == FDT_MAGIC) {
> + return (void *)fw_dtb_pointer;
> + }
> +
> + return NULL;
> +}
> +
> +/*
> + * QEMU doesn't set compatible on cpus.
> + * Add them to make sure the U-Boot driver properly bind.
> + */
> +static int fdtdec_fix_cpus(void *fdt_blob)
> +{
> + int cpus_offset, off, ret;
> + u64 mpidr, i = 0;
> +
> + cpus_offset = fdt_path_offset(fdt_blob, "/cpus");
> + if (cpus_offset < 0) {
> + puts("couldn't find /cpus node\n");
> + return cpus_offset;
> + }
> +
> + fdt_for_each_subnode(off, fdt_blob, cpus_offset) {
> + if (strncmp(fdt_get_name(fdt_blob, off, NULL), "cpu@", 4))
> + continue;
> +
> + mpidr = 0;
> + ret = smc_get_mpidr(i, &mpidr);
> + if (ret) {
> + log_warning("Failed to get MPIDR for processor %lld from SMC: %d\n",
> + i, ret);
> + mpidr = i;
> + }
> +
> + ret = fdt_setprop_string(fdt_blob, off, "compatible", "arm,armv8");
> + if (ret < 0)
> + return ret;
> +
> + ret = fdt_setprop_string(fdt_blob, off, "device_type", "cpu");
> + if (ret < 0)
> + return ret;
> +
> + ret = fdt_setprop_u64(fdt_blob, off, "reg", mpidr);
> + if (ret < 0)
> + return ret;
> + i++;
> + }
> + return 0;
> +}
> +
> +/*
> + * Update the GIC node when necessary and add optional ITS when it has a
> + * non zero base-address.
> + */
> +static int fdtdec_fix_gic(void *fdt)
> +{
> + u64 gic_dist_base = SBSA_GIC_DIST_BASE_ADDR;
> + u64 gic_redist_base = SBSA_GIC_REDIST_BASE_ADDR;
> + u64 gic_its_base = 0;
> + int offs, ret;
> + u64 reg[10];
> +
> + /* Invoke SMC to get real base-address */
> + smc_get_gic_dist_base(&gic_dist_base);
> + smc_get_gic_redist_base(&gic_redist_base);
> +
> + if ((gic_dist_base != SBSA_GIC_DIST_BASE_ADDR) ||
> + (gic_redist_base != SBSA_GIC_REDIST_BASE_ADDR)) {
> + offs = fdt_path_offset(fdt, "/interrupt-controller");
> + if (offs < 0) {
> + puts("couldn't find /interrupt-controller node\n");
> + return offs;
> + }
> +
> + reg[0] = cpu_to_fdt64(gic_dist_base);
> + reg[1] = cpu_to_fdt64((u64)SBSA_GIC_DIST_LENGTH);
> + reg[2] = cpu_to_fdt64(gic_redist_base);
> + reg[3] = cpu_to_fdt64((u64)SBSA_GIC_REDIST_LENGTH);
> + reg[4] = cpu_to_fdt64(0);
> + reg[5] = cpu_to_fdt64(0);
> + reg[6] = cpu_to_fdt64(SBSA_GIC_HBASE_ADDR);
> + reg[7] = cpu_to_fdt64((u64)SBSA_GIC_HBASE_LENGTH);
> + reg[8] = cpu_to_fdt64(SBSA_GIC_VBASE_ADDR);
> + reg[9] = cpu_to_fdt64((u64)SBSA_GIC_VBASE_LENGTH);
> +
> + ret = fdt_setprop_inplace(fdt, offs, "reg", reg, sizeof(reg));
> + }
> +
> + smc_get_gic_its_base(&gic_its_base);
> +
> + if (gic_its_base != 0) {
> + offs = fdt_path_offset(fdt, "/its");
> + if (offs < 0)
> + return offs;
> +
> + ret = fdt_setprop_string(fdt, offs, "status", "okay");
> + if (ret < 0)
> + return ret;
> +
> + reg[0] = cpu_to_fdt64(gic_its_base);
> + reg[1] = 0;
> +
> + ret = fdt_setprop(fdt, offs, "reg", reg, sizeof(u64) * 2);
> + if (ret < 0)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +int fdtdec_board_setup(const void *fdt_blob)
> +{
> + void *qemu_fdt;
> + int ret;
> +
> + /*
> + * Locate the QEMU provided DTB that contains the CPUs and amount of DRAM.
> + */
> + qemu_fdt = dtb_dt_qemu();
> + if (!qemu_fdt) {
> + log_err("QEMU FDT not found\n");
> + return -ENODEV;
> + }
> +
> + ret = fdt_increase_size((void *)fdt_blob, 1024 + fdt_totalsize(qemu_fdt));
> + if (ret)
> + return -ENOMEM;
> +
> + /*
> + * Merge the QEMU DTB as overlay into the U-Boot provided DTB.
> + */
> + ret = fdt_overlay_apply_node((void *)fdt_blob, 0, qemu_fdt, 0);
> + if (ret < 0)
> + log_err("Failed to apply overlay: %d\n", ret);
> +
> + /* Fix QEMU nodes to make sure U-Boot drivers are properly working */
> + ret = fdtdec_fix_cpus((void *)fdt_blob);
> + if (ret < 0)
> + log_err("Failed to fix CPUs in FDT: %d\n", ret);
> +
> + ret = fdtdec_fix_gic((void *)fdt_blob);
> + if (ret < 0)
> + log_err("Failed to fix INTC in FDT: %d\n", ret);
> +
> + return 0;
> +}
> +
> +int misc_init_r(void)
> +{
> + return env_set_hex("fdt_addr", (uintptr_t)gd->fdt_blob);
> +}
> +
> +void reset_cpu(void)
> +{
> +}
> +
> +int dram_init(void)
> +{
> + return fdtdec_setup_mem_size_base();
> +}
> \ No newline at end of file
> diff --git a/board/emulation/qemu-sbsa/qemu-sbsa.env b/board/emulation/qemu-sbsa/qemu-sbsa.env
> new file mode 100644
> index 0000000000..88fdb0ec1c
> --- /dev/null
> +++ b/board/emulation/qemu-sbsa/qemu-sbsa.env
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +/* environment for qemu-arm and qemu-arm64 */
> +
> +stdin=serial,usbkbd
> +stdout=serial,vidconsole
> +stderr=serial,vidconsole
> +fdt_high=0xffffffffffffffff
> +initrd_high=0xffffffffffffffff
> +scriptaddr=0x100000300000
> +pxefile_addr_r=0x10000400000
> +kernel_addr_r=0x10000200000
> +ramdisk_addr_r=0x10001000000
> +boot_targets=qfw usb scsi virtio nvme dhcp
> diff --git a/board/emulation/qemu-sbsa/qemu-sbsa.h b/board/emulation/qemu-sbsa/qemu-sbsa.h
> new file mode 100644
> index 0000000000..391a70bdc4
> --- /dev/null
> +++ b/board/emulation/qemu-sbsa/qemu-sbsa.h
> @@ -0,0 +1,38 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2024 9elements GmbH
> + */
> +
> +/**
> + * smc_get_mpidr() - Call into SMC and get the MPIDR for given CPU
> + *
> + * @id: CPU index
> + * @mpidr: Pointer where to place the MPIDR
> + * @return 0 if OK, other -ve on error
> + */
> +int smc_get_mpidr(unsigned long id, u64 *mpidr);
> +
> +/**
> + * smc_get_gic_dist_base() - Call into SMC and get GIC dist base address
> + *
> + * @mpidr: Pointer where to place the base address
> + * @return 0 if OK, other -ve on error
> + */
> +int smc_get_gic_dist_base(u64 *base);
> +
> +/**
> + * smc_get_gic_redist_base() - Call into SMC and get the GIC redistributor
> + * base address
> + *
> + * @mpidr: Pointer where to place the base address
> + * @return 0 if OK, other -ve on error
> + */
> +int smc_get_gic_redist_base(u64 *base);
> +
> +/**
> + * smc_get_gic_its_base() - Call into SMC and get the ITS base address
> + *
> + * @mpidr: Pointer where to place the base address
> + * @return 0 if OK, other -ve on error
> + */
> +int smc_get_gic_its_base(u64 *base);
> diff --git a/board/emulation/qemu-sbsa/smc.c b/board/emulation/qemu-sbsa/smc.c
> new file mode 100644
> index 0000000000..9a2d091bea
> --- /dev/null
> +++ b/board/emulation/qemu-sbsa/smc.c
> @@ -0,0 +1,71 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2024 9elements GmbH
> + */
> +
> +#include <cpu.h>
> +#include <init.h>
> +#include <log.h>
> +#include <linux/arm-smccc.h>
> +
> +#define SMC_SIP_FUNCTION_ID(n) (0xC2000000 | (n))
> +
> +#define SIP_SVC_VERSION SMC_SIP_FUNCTION_ID(1)
> +#define SIP_SVC_GET_GIC SMC_SIP_FUNCTION_ID(100)
> +#define SIP_SVC_GET_GIC_ITS SMC_SIP_FUNCTION_ID(101)
> +#define SIP_SVC_GET_CPU_COUNT SMC_SIP_FUNCTION_ID(200)
> +#define SIP_SVC_GET_CPU_NODE SMC_SIP_FUNCTION_ID(201)
> +#define SIP_SVC_GET_MEMORY_NODE_COUNT SMC_SIP_FUNCTION_ID(300)
> +#define SIP_SVC_GET_MEMORY_NODE SMC_SIP_FUNCTION_ID(301)
> +
> +int smc_get_mpidr(unsigned long id, u64 *mpidr)
> +{
> + struct arm_smccc_res res;
> +
> + res.a0 = ~0;
> + arm_smccc_smc(SIP_SVC_GET_CPU_NODE, id, 0, 0, 0, 0, 0, 0, &res);
> +
> + if (!res.a0)
> + *mpidr = res.a2;
> +
> + return res.a0;
> +}
> +
> +int smc_get_gic_dist_base(u64 *base)
> +{
> + struct arm_smccc_res res;
> +
> + res.a0 = ~0;
> + arm_smccc_smc(SIP_SVC_GET_GIC, 0, 0, 0, 0, 0, 0, 0, &res);
> +
> + if (!res.a0)
> + *base = res.a1;
> +
> + return res.a0;
> +}
> +
> +int smc_get_gic_redist_base(u64 *base)
> +{
> + struct arm_smccc_res res;
> +
> + res.a0 = ~0;
> + arm_smccc_smc(SIP_SVC_GET_GIC, 0, 0, 0, 0, 0, 0, 0, &res);
> +
> + if (!res.a0)
> + *base = res.a2;
> +
> + return res.a0;
> +}
> +
> +int smc_get_gic_its_base(u64 *base)
> +{
> + struct arm_smccc_res res;
> +
> + res.a0 = ~0;
> + arm_smccc_smc(SIP_SVC_GET_GIC_ITS, 0, 0, 0, 0, 0, 0, 0, &res);
> +
> + if (!res.a0)
> + *base = res.a1;
> +
> + return res.a0;
> +}
> diff --git a/configs/qemu-arm-sbsa_defconfig b/configs/qemu-arm-sbsa_defconfig
> new file mode 100644
> index 0000000000..a58c3dec4c
> --- /dev/null
> +++ b/configs/qemu-arm-sbsa_defconfig
> @@ -0,0 +1,10 @@
> +CONFIG_ARM=y
> +CONFIG_ARCH_QEMU=y
> +CONFIG_TARGET_QEMU_ARM_SBSA=y
> +CONFIG_USE_BOOTCOMMAND=y
> +CONFIG_BOOTCOMMAND="bootflow scan"
> +CONFIG_EFI_PARTITION=y
> +CONFIG_PARTITION_TYPE_GUID=y
> +CONFIG_EFI_MEDIA=y
> +CONFIG_FS_FAT=y
> +CONFIG_EFI_VARIABLE_NO_STORE=y
> diff --git a/doc/board/emulation/index.rst b/doc/board/emulation/index.rst
> index 98a0b26ad2..0419d72415 100644
> --- a/doc/board/emulation/index.rst
> +++ b/doc/board/emulation/index.rst
> @@ -13,5 +13,6 @@ Emulation
> qemu-mips
> qemu-ppce500
> qemu-riscv
> + qemu-sbsa
> qemu-x86
> qemu-xtensa
> diff --git a/doc/board/emulation/qemu-sbsa.rst b/doc/board/emulation/qemu-sbsa.rst
> new file mode 100644
> index 0000000000..fe1dc3249e
> --- /dev/null
> +++ b/doc/board/emulation/qemu-sbsa.rst
> @@ -0,0 +1,98 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +.. Copyright (C) 2024, Patrick Rudolph <patrick.rudolph at 9elements.com>
> +
> +QEMU ARM SBSA
> +=============
> +
> +QEMU for ARM supports Arm Server Base System Architecture Reference board,
> +short 'sbsa-ref' that utilizes ACPI over FDT. This document describes how to run
> +U-Boot under it. Only AArch64 is supported.
> +
> +The 'sbsa' platform provides the following as the basic functionality:
> +
> + - A freely configurable amount of CPU cores
> + - U-Boot loaded and executing in the emulated flash at address 0x10000000
> + - No device tree blob
> + - A freely configurable amount of RAM
> + - A PL011 serial port
> + - An ARMv8/ARMv8 architected timer
> + - PSCI for rebooting the system
> + - A generic ECAM-based PCI host controller
> +
> +Additionally, a number of optional peripherals can be added to the PCI bus.
> +
> +Compile ARM Trusted Firmware (ATF)
> +----------------------------------
> +
> +Get and Build the ARM Trusted firmware
> +--------------------------------------
> +
> +Note: srctree is U-Boot source directory
> +Get ATF from: https://github.com/ARM-software/arm-trusted-firmware
> +
> +.. code-block:: bash
> +
> + git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git tfa
> + cd tfa
> + make CROSS_COMPILE=aarch64-linux-gnu- all fip \
> + ARM_LINUX_KERNEL_AS_BL33=1 DEBUG=1 PLAT=qemu_sbsa
> +
> +Copy the resulting FIP and BL1 binary
> +
> +.. code-block:: bash
> +
> + cp build/qemu_sbsa/debug/fip.bin ../
> + cp build/qemu_sbsa/debug/bl1.bin ../
> +
> +Building U-Boot
> +---------------
> +Set the CROSS_COMPILE environment variable as usual, and run:
> +
> +.. code-block:: bash
> +
> + make qemu-arm-sbsa_defconfig
> + make
> +
> +Running U-Boot
> +--------------
> +The minimal QEMU command line to get U-Boot up and running is:
> +
> +.. code-block:: bash
> +
> + qemu-system-aarch64 -machine sbsa-ref -nographic -cpu cortex-a57 \
> + -pflash secure-world.rom \
> + -pflash unsecure-world.rom
> +
> +Note that for some odd reason qemu-system-aarch64 needs to be explicitly
> +told to use a 64-bit CPU or it will boot in 32-bit mode. The -nographic argument
> +ensures that output appears on the terminal. Use Ctrl-A X to quit.
> +
> +Booting distros
> +---------------
> +
> +It is possible to install and boot a standard Linux distribution using
> +sbsa by setting up a root disk::
> +
> +.. code-block:: bash
> +
> + qemu-img create root.img 20G
> +
> +then using the installer to install. For example, with Debian 12::
> +
> +.. code-block:: bash
> +
> + qemu-system-aarch64 \
> + -machine sbsa-ref -cpu cortex-a57 -m 4G -smp 4 \
> + -pflash secure-world.rom \
> + -pflash unsecure-world.rom \
> + -device virtio-rng-pci \
> + -device usb-kbd -device usb-tablet \
> + -cdrom debian-12.0.0-arm64-netinst.iso \
> + -hda root.img
> +
> +Debug UART
> +----------
> +
> +The debug UART on the ARM sbsa board uses these settings::
> +
> + CONFIG_DEBUG_UART=y
> diff --git a/doc/develop/driver-model/virtio.rst b/doc/develop/driver-model/virtio.rst
> index 8ac9c94caf..31b94d0467 100644
> --- a/doc/develop/driver-model/virtio.rst
> +++ b/doc/develop/driver-model/virtio.rst
> @@ -34,6 +34,7 @@ The following QEMU targets are supported.
>
> - qemu_arm_defconfig
> - qemu_arm64_defconfig
> + - qemu-arm-sbsa_defconfig
> - qemu-riscv32_defconfig
> - qemu-riscv64_defconfig
> - qemu-x86_defconfig
> diff --git a/include/configs/qemu-sbsa.h b/include/configs/qemu-sbsa.h
> new file mode 100644
> index 0000000000..aff78160e1
> --- /dev/null
> +++ b/include/configs/qemu-sbsa.h
> @@ -0,0 +1,89 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2024 9elements GmbH
> + */
> +
> +#ifndef __CONFIG_H
> +#define __CONFIG_H
> +
> +/* Physical memory map */
> +
> +/* SECURE_FLASH */
> +#define SBSA_SECURE_FLASH_BASE_ADDR 0x00000000
> +#define SBSA_SECURE_FLASH_LENGTH 0x10000000
> +
> +/* FLASH */
> +#define SBSA_FLASH_BASE_ADDR 0x10000000
> +#define SBSA_FLASH_LENGTH 0x10000000
> +
> +/* PERIPH */
> +#define SBSA_PERIPH_BASE_ADDR 0x40000000
> +
> +/* GIC_DIST */
> +#define SBSA_GIC_DIST_BASE_ADDR 0x40060000
> +#define SBSA_GIC_DIST_LENGTH 0x00020000
> +
> +#define SBSA_GIC_VBASE_ADDR 0x2c020000
> +#define SBSA_GIC_VBASE_LENGTH 0x00010000
> +
> +#define SBSA_GIC_HBASE_ADDR 0x2c010000
> +#define SBSA_GIC_HBASE_LENGTH 0x00010000
> +
> +/* GIC_REDIST */
> +#define SBSA_GIC_REDIST_BASE_ADDR 0x40080000
> +#define SBSA_GIC_REDIST_LENGTH 0x04000000
> +
> +/* GIC_ITS */
> +#define SBSA_GIC_ITS_BASE_ADDR 0x44081000
> +
> +/* UART */
> +#define SBSA_UART_BASE_ADDR 0x60000000
> +#define SBSA_UART_LENGTH 0x00001000
> +
> +/* SMMU */
> +#define SBSA_SMMU_BASE_ADDR 0x60050000
> +
> +/* SATA */
> +#define SBSA_AHCI_BASE_ADDR 0x60100000
> +#define SBSA_AHCI_LENGTH 0x00010000
> +
> +/* xHCI */
> +#define SBSA_XHCI_BASE_ADDR 0x60110000
> +#define SBSA_XHCI_LENGTH 0x00010000
> +
> +/* PIO */
> +#define SBSA_PIO_BASE_ADDR 0x7fff0000
> +#define SBSA_PIO_LENGTH 0x00010000
> +
> +/* PCIE_MMIO */
> +#define SBSA_PCIE_MMIO_BASE_ADDR 0x80000000
> +#define SBSA_PCIE_MMIO_LENGTH 0x70000000
> +#define SBSA_PCIE_MMIO_END 0xefffffff
> +
> +/* PCIE_ECAM */
> +#define SBSA_PCIE_ECAM_BASE_ADDR 0xf0000000
> +#define SBSA_PCIE_ECAM_LENGTH 0x10000000
> +#define SBSA_PCIE_ECAM_END 0xffffffff
> +
> +/* PCIE_MMIO_HIGH */
> +#ifdef __ACPI__
> +#define SBSA_PCIE_MMIO_HIGH_BASE_ADDR 0x100000000
> +#define SBSA_PCIE_MMIO_HIGH_LENGTH 0xFF00000000
> +#define SBSA_PCIE_MMIO_HIGH_END 0xFFFFFFFFFF
> +#else
> +#define SBSA_PCIE_MMIO_HIGH_BASE_ADDR 0x100000000ULL
> +#define SBSA_PCIE_MMIO_HIGH_LENGTH 0xFF00000000ULL
> +#define SBSA_PCIE_MMIO_HIGH_END 0xFFFFFFFFFFULL
> +#endif
> +
> +/* MEM */
> +#ifdef __ACPI__
> +#define SBSA_MEM_BASE_ADDR 0x10000000000
> +#else
> +#define SBSA_MEM_BASE_ADDR 0x10000000000ULL
> +#endif
> +
> +#define CFG_SYS_INIT_RAM_ADDR SBSA_MEM_BASE_ADDR
> +#define CFG_SYS_INIT_RAM_SIZE 0x1000000
> +
> +#endif /* __CONFIG_H */
> --
> 2.46.2
>
Thanks,
Moritz
More information about the U-Boot
mailing list