aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2024-10-27 17:14:22 -0600
committerTom Rini <trini@konsulko.com>2024-10-27 18:44:13 -0600
commit2800aecce08b47b169d8e9824dd23b1297b2cedc (patch)
tree2f8b61eaee1520b6fd5bd6cedb111aa3ee13f2f7 /arch/arm
parent568407fab5336c00cf0265e9de6c507078988504 (diff)
parent25081abf081880930365ff2bc6afc6c0273ca4bf (diff)
downloadu-boot-2800aecce08b47b169d8e9824dd23b1297b2cedc.tar.gz
Merge patch series "Implement ACPI on aarch64"WIP/27Oct2024
Patrick Rudolph <patrick.rudolph@9elements.com> says: Based on the existing work done by Simon Glass this series adds support for booting aarch64 devices using ACPI only. As first target QEMU SBSA support is added, which relies on ACPI only to boot an OS. As secondary target the Raspberry Pi4 was used, which is broadly available and allows easy testing of the proposed solution. The series is split into ACPI cleanups and code movements, adding Arm specific ACPI tables and finally SoC and mainboard related changes to boot a Linux on the QEMU SBSA and RPi4. Currently only the mandatory ACPI tables are supported, allowing to boot into Linux without errors. The QEMU SBSA support is feature complete and provides the same functionality as the EDK2 implementation. The changes were tested on real hardware as well on QEMU v9.0: qemu-system-aarch64 -machine sbsa-ref -nographic -cpu cortex-a57 \ -pflash secure-world.rom \ -pflash unsecure-world.rom qemu-system-aarch64 -machine raspi4b -kernel u-boot.bin -cpu cortex-a72 \ -smp 4 -m 2G -drive file=raspbian.img,format=raw,index=0 \ -dtb bcm2711-rpi-4-b.dtb -nographic Tested against FWTS V24.03.00. Known issues: - The QEMU rpi4 support is currently limited as it doesn't emulate PCI, USB or ethernet devices! - The SMP bringup doesn't work on RPi4, but works in QEMU (Possibly cache related). - PCI on RPI4 isn't working on real hardware since the pcie_brcmstb Linux kernel module doesn't support ACPI yet. Link: https://lore.kernel.org/r/20241023132116.970117-1-patrick.rudolph@9elements.com
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig11
-rw-r--r--arch/arm/cpu/armv8/Makefile1
-rw-r--r--arch/arm/cpu/armv8/acpi_park_v8.S113
-rw-r--r--arch/arm/cpu/armv8/start.S12
-rw-r--r--arch/arm/dts/qemu-sbsa.dts138
-rw-r--r--arch/arm/include/asm/acpi_table.h147
-rw-r--r--arch/arm/include/asm/arch-qemu-sbsa/boot0.h34
-rw-r--r--arch/arm/include/asm/system.h9
-rw-r--r--arch/arm/lib/Makefile2
-rw-r--r--arch/arm/lib/acpi_table.c276
-rw-r--r--arch/arm/lib/gic-v2.c89
-rw-r--r--arch/arm/lib/gic-v3-its.c121
-rw-r--r--arch/arm/mach-bcm283x/Kconfig16
-rw-r--r--arch/arm/mach-bcm283x/Makefile4
-rw-r--r--arch/arm/mach-bcm283x/bcm2711_acpi.c128
-rw-r--r--arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h152
-rw-r--r--arch/arm/mach-bcm283x/include/mach/acpi/bcm2836.h127
-rw-r--r--arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpio.h19
-rw-r--r--arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpu.h47
-rw-r--r--arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_pwm.h33
-rw-r--r--arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdhost.h18
-rw-r--r--arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdio.h21
-rw-r--r--arch/arm/mach-bcm283x/init.c2
-rw-r--r--arch/arm/mach-qemu/Kconfig36
24 files changed, 1542 insertions, 14 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 060636e9e2d..787f983ffd4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -113,6 +113,13 @@ config GICV2
config GICV3
bool
+config DRIVER_GICV2
+ bool "ARM GICV2 driver"
+ select IRQ
+ help
+ ARM GICV2 driver.
+ Basic support for parsing the GICV2 node and generate ACPI tables.
+
config GIC_V3_ITS
bool "ARM GICV3 ITS"
select IRQ
@@ -644,6 +651,7 @@ config ARCH_ORION5X
config ARCH_BCM283X
bool "Broadcom BCM283X family"
+ select CPU
select DM
select DM_GPIO
select DM_SERIAL
@@ -1047,7 +1055,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
@@ -2374,6 +2382,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/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index 8747d2eb186..2e71ff2dc97 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_ARM_SMCCC) += smccc-call.o
ifndef CONFIG_XPL_BUILD
obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o
+obj-$(CONFIG_ACPI_PARKING_PROTOCOL) += acpi_park_v8.o
else
obj-$(CONFIG_ARCH_SUNXI) += fel_utils.o
endif
diff --git a/arch/arm/cpu/armv8/acpi_park_v8.S b/arch/arm/cpu/armv8/acpi_park_v8.S
new file mode 100644
index 00000000000..0bc605d28df
--- /dev/null
+++ b/arch/arm/cpu/armv8/acpi_park_v8.S
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2024 9elements GmbH
+ * Author: Patrick Rudolph <patrick.rudolph@9elements.com>
+ *
+ * This file provides ARMv8 specific code for the generic part of the
+ * ACPI parking protocol implementation. It contains the spinning code
+ * that will be installed into the parking protocol and it points the
+ * secondary CPUs to their own parking protocol page once it has been
+ * set up by the generic part.
+ */
+
+#include <asm/acpi_table.h>
+#include <linux/linkage.h>
+
+/* Filled by C code */
+.global acpi_pp_tables
+acpi_pp_tables:
+ .quad 0
+
+.global acpi_pp_etables
+acpi_pp_etables:
+ .quad 0
+
+/* Read by C code */
+.global acpi_pp_code_size
+acpi_pp_code_size:
+ .word __secondary_pp_code_end - __secondary_pp_code_start
+
+.global acpi_pp_secondary_jump
+ENTRY(acpi_pp_secondary_jump)
+0:
+ /*
+ * Cannot use atomic operations since the MMU and D-cache
+ * might be off. Use the MPIDR instead to find the spintable.
+ */
+
+ /* Check if parking protocol table is ready */
+ ldr x1, =acpi_pp_tables
+ ldr x0, [x1]
+ cbnz x0, 0f
+ wfe
+ b 0b
+
+0: /* Get end of page tables in x3 */
+ ldr x1, =acpi_pp_etables
+ ldr x3, [x1]
+
+ /* Get own CPU ID in w2 */
+ mrs x2, mpidr_el1
+ lsr x9, x2, #32
+ bfi x2, x9, #24, #8 /* w2 is aff3:aff2:aff1:aff0 */
+
+0: /* Loop over all parking protocol pages */
+ cmp x0, x3
+ b.ge hlt
+
+ /* Fetch CPU_ID from current page */
+ ldr x1, [x0, #ACPI_PP_CPU_ID_OFFSET]
+ lsr x9, x1, #32
+ bfi x1, x9, #24, #8 /* w1 is aff3:aff2:aff1:aff0 */
+
+ /* Compare CPU_IDs */
+ cmp w1, w2
+ b.eq 0f
+
+ add x0, x0, #ACPI_PP_PAGE_SIZE
+ b 0b
+
+hlt: wfi
+ b hlt /* Should never happen. */
+
+0: /* x0 points to the 4K-aligned, parking protocol page */
+ add x2, x0, #ACPI_PP_CPU_CODE_OFFSET
+
+ /* Jump to spin code in own parking protocol page */
+ br x2
+ENDPROC(acpi_pp_secondary_jump)
+
+.align 8
+__secondary_pp_code_start:
+.global acpi_pp_code_start
+ENTRY(acpi_pp_code_start)
+ /* x0 points to the 4K-aligned, parking protocol page */
+
+ /* Prepare defines for spinning code */
+ mov w3, #ACPI_PP_CPU_ID_INVALID
+ mov x2, #ACPI_PP_JMP_ADR_INVALID
+
+ /* Mark parking protocol page as ready */
+ str w3, [x0, #ACPI_PP_CPU_ID_OFFSET]
+ dsb sy
+
+0: wfe
+ ldr w1, [x0, #ACPI_PP_CPU_ID_OFFSET]
+
+ /* Check CPU ID is valid */
+ cmp w1, w3
+ b.eq 0b
+
+ /* Check jump address valid */
+ ldr x1, [x0, #ACPI_PP_CPU_JMP_OFFSET]
+ cmp x1, x2
+ b.eq 0b
+
+ /* Clear jump address before jump */
+ str x2, [x0, #ACPI_PP_CPU_JMP_OFFSET]
+ dsb sy
+
+ br x1
+ENDPROC(acpi_pp_code_start)
+ /* Secondary Boot Code ends here */
+__secondary_pp_code_end:
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S
index 4a3b9f60e46..d3a8a7c4787 100644
--- a/arch/arm/cpu/armv8/start.S
+++ b/arch/arm/cpu/armv8/start.S
@@ -178,6 +178,18 @@ pie_fixup_done:
branch_if_master x0, master_cpu
b spin_table_secondary_jump
/* never return */
+#elif defined(CONFIG_ACPI_PARKING_PROTOCOL) && !defined(CONFIG_SPL_BUILD)
+ branch_if_master x0, master_cpu
+ /*
+ * Waits for ACPI parking protocol memory to be allocated and the spin-table
+ * code to be written. Once ready the secondary CPUs will jump and spin in
+ * their own 4KiB memory region, which is also used as mailbox, until released
+ * by the OS.
+ * The mechanism is similar to the DT enable-method = "spin-table", but works
+ * with ACPI enabled platforms.
+ */
+ b acpi_pp_secondary_jump
+ /* never return */
#elif defined(CONFIG_ARMV8_MULTIENTRY)
branch_if_master x0, master_cpu
diff --git a/arch/arm/dts/qemu-sbsa.dts b/arch/arm/dts/qemu-sbsa.dts
new file mode 100644
index 00000000000..ed00e501366
--- /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/acpi_table.h b/arch/arm/include/asm/acpi_table.h
index e69de29bb2d..7386f55ad34 100644
--- a/arch/arm/include/asm/acpi_table.h
+++ b/arch/arm/include/asm/acpi_table.h
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __ASM_ACPI_TABLE_H__
+#define __ASM_ACPI_TABLE_H__
+
+#ifndef __ACPI__
+#ifndef __ASSEMBLY__
+
+#include <acpi/acpi_table.h>
+
+/**
+ * acpi_write_madt_gicc() - Write out a MADT GICC sub-table
+ *
+ * Write out the GIC CPU Interface sub-table.
+ *
+ * @gicc: Pointer to place to put the sub-table
+ * @cpu_num: GIC's CPU Interface Number
+ * @perf_gsiv: The GSIV used for Performance Monitoring Interrupts
+ * @phys_base: Address at which the processor can access this
+ * GIC CPU Interface
+ * @gicv: Address of the GIC virtual CPU interface registers
+ * @gich: Address of the GIC virtual interface control block
+ * registers
+ * @vgic_maint_irq: GSIV for Virtual GIC maintenance interrupt
+ * @gicr_base: Physical address of the associated Redistributor
+ * @mpidr: MPIDR as defined by ARM architecture
+ * @efficiency: Describes the relative power efficiency
+ */
+void acpi_write_madt_gicc(struct acpi_madt_gicc *gicc, uint cpu_num,
+ uint perf_gsiv, ulong phys_base, ulong gicv,
+ ulong gich, uint vgic_maint_irq, u64 gicr_base,
+ ulong mpidr, uint efficiency);
+
+/**
+ * acpi_write_madt_gicd() - Write out a MADT GICD sub-table
+ *
+ * Write out the GIC Distributor sub-table.
+ *
+ * @gicd: Pointer to place to put the sub-table
+ * @gic_id: This GIC Distributor's hardware ID
+ * @phys_base: The 64-bit physical address for this Distributor
+ * @gic_version: GIC version
+ */
+void acpi_write_madt_gicd(struct acpi_madt_gicd *gicd, uint gic_id,
+ ulong phys_base, uint gic_version);
+
+/**
+ * acpi_write_madt_gicr() - Write out a MADT GICR sub-table
+ *
+ * Write out the GIC Redistributor sub-table.
+ *
+ * @gicr: Pointer to place to put the sub-table
+ * @discovery_range_base_address: Physical address of a page range
+ * containing all GIC Redistributors
+ * @discovery_range_length: Length of the GIC Redistributor
+ * Discovery page range
+ */
+void acpi_write_madt_gicr(struct acpi_madt_gicr *gicr,
+ u64 discovery_range_base_address,
+ u32 discovery_range_length);
+
+/**
+ * acpi_write_madt_its() - Write out a MADT ITS sub-table
+ *
+ * Write out the GIC Interrupt Translation Service sub-table.
+ *
+ * @its: Pointer to place to put the sub-table
+ * @its_id: Uniqueue GIC ITS ID
+ * @physical_base_address: Physical address for the Interrupt
+ * Translation Service
+ */
+void acpi_write_madt_its(struct acpi_madt_its *its,
+ u32 its_id,
+ u64 physical_base_address);
+
+/**
+ * acpi_pptt_add_proc() - Write out a PPTT processor sub-table
+ *
+ * Write out the Processor Properties Topology Table processor sub-table.
+ *
+ * @ctx: ACPI context pointer
+ * @flags: Processor Structure Flags
+ * @parent: Reference to parent processor
+ * @proc_id: ACPI processor ID as defined in MADT
+ * @num_resources: Number of resource structure references
+ * @resource_list: References to other PPTT structures
+ * Return: offset from start of PPTT in bytes
+ */
+int acpi_pptt_add_proc(struct acpi_ctx *ctx, const u32 flags, const u32 parent,
+ const u32 proc_id, const u32 num_resources,
+ const u32 *resource_list);
+
+/**
+ * acpi_pptt_add_cache() - Write out a PPTT cache sub-table
+ *
+ * Write out the Processor Properties Topology Table cache sub-table.
+ *
+ * @ctx: ACPI context pointer
+ * @flags: Cache Structure Flags
+ * @next_cache_level: Reference to next level of cache
+ * @size: Size of the cache in bytes
+ * @sets: Number of sets in the cache
+ * @assoc: Integer number of ways
+ * @attributes: Allocation type, Cache type, policy
+ * @line_size: Line size in bytes
+ * Return: offset from start of PPTT in bytes
+ */
+int acpi_pptt_add_cache(struct acpi_ctx *ctx, const u32 flags,
+ const u32 next_cache_level, const u32 size,
+ const u32 sets, const u8 assoc, const u8 attributes,
+ const u16 line_size);
+
+/* Multi-processor Startup for ARM Platforms */
+/**
+ * struct acpi_pp_page - MP startup handshake mailbox
+ *
+ * Defines a 4096 byte memory region that is used for starting secondary CPUs on
+ * an Arm system that follows the "Multi-processor Startup for ARM Platforms" spec.
+ *
+ * @cpu_id: MPIDR as returned by the Multiprocessor Affinity Register.
+ * On 32bit Arm systems the upper bits are unused.
+ * @jumping_address: On 32bit Arm systems the address must be below 4 GiB
+ * @os_reserved: Reserved for OS use. Firmware must not access this memory.
+ * @spinning_code: Reserved for firmware use. OS must not access this memory.
+ * The spinning code will be installed by firmware and the secondary
+ * CPUs will enter it before the control is handed over to the OS.
+ */
+struct acpi_pp_page {
+ u64 cpu_id;
+ u64 jumping_address;
+ u8 os_reserved[2032];
+ u8 spinning_code[2048];
+} __packed;
+
+#endif /* !__ASSEMBLY__ */
+#endif /* !__ACPI__ */
+
+/* Multi-processor Startup for ARM Platforms defines */
+#define ACPI_PP_CPU_ID_INVALID 0xffffffff
+#define ACPI_PP_JMP_ADR_INVALID 0
+#define ACPI_PP_PAGE_SIZE 4096
+#define ACPI_PP_CPU_ID_OFFSET 0
+#define ACPI_PP_CPU_JMP_OFFSET 8
+#define ACPI_PP_CPU_CODE_OFFSET 2048
+#define ACPI_PP_VERSION 1
+
+#endif /* __ASM_ACPI_TABLE_H__ */
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 00000000000..4a1a254b923
--- /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/include/asm/system.h b/arch/arm/include/asm/system.h
index 2237d7d0066..9eb30c2ade8 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -394,6 +394,15 @@ void switch_to_hypervisor_ret(void);
#define wfi()
#endif
+static inline unsigned long read_mpidr(void)
+{
+ unsigned long val;
+
+ asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (val));
+
+ return val;
+}
+
static inline unsigned long get_cpsr(void)
{
unsigned long cpsr;
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index f254186c525..1c95dd6fed2 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_FSL_LAYERSCAPE) += ccn504.o
ifneq ($(CONFIG_GICV2)$(CONFIG_GICV3),)
obj-y += gic_64.o
endif
+obj-$(CONFIG_DRIVER_GICV2) += gic-v2.o
obj-$(CONFIG_GIC_V3_ITS) += gic-v3-its.o
obj-y += interrupts_64.o
else
@@ -86,6 +87,7 @@ obj-y += psci-dt.o
obj-$(CONFIG_DEBUG_LL) += debug.o
obj-$(CONFIG_BLOBLIST) += xferlist.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
# For EABI conformant tool chains, provide eabi_compat()
ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
diff --git a/arch/arm/lib/acpi_table.c b/arch/arm/lib/acpi_table.c
new file mode 100644
index 00000000000..f760b7fbce4
--- /dev/null
+++ b/arch/arm/lib/acpi_table.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Based on acpi.c from coreboot
+ *
+ * Copyright (C) 2024 9elements GmbH
+ */
+
+#define LOG_CATEGORY LOGC_ACPI
+
+#include <bloblist.h>
+#include <cpu_func.h>
+#include <efi_loader.h>
+#include <malloc.h>
+#include <string.h>
+#include <tables_csum.h>
+#include <acpi/acpigen.h>
+#include <acpi/acpi_device.h>
+#include <acpi/acpi_table.h>
+#include <asm-generic/io.h>
+#include <dm/acpi.h>
+#include <dm/uclass.h>
+#include <linux/log2.h>
+#include <linux/sizes.h>
+
+/* defined in assembly file */
+/**
+ * acpi_pp_code_size - Spinloop code size *
+ */
+extern u16 acpi_pp_code_size;
+
+/**
+ * acpi_pp_tables - Start of ACPI PP tables.
+ */
+extern ulong acpi_pp_tables;
+
+/**
+ * acpi_pp_etables - End of ACPI PP tables.
+ */
+extern ulong acpi_pp_etables;
+
+/**
+ * acpi_pp_code_start() - Spinloop code
+ *
+ * Architectural spinloop code to be installed in each parking protocol
+ * page. The spinloop code must be less than 2048 bytes.
+ *
+ * The spinloop code will be entered after calling
+ * acpi_parking_protocol_install().
+ *
+ */
+void acpi_pp_code_start(void);
+
+void acpi_write_madt_gicc(struct acpi_madt_gicc *gicc, uint cpu_num,
+ uint perf_gsiv, ulong phys_base, ulong gicv,
+ ulong gich, uint vgic_maint_irq, u64 gicr_base,
+ ulong mpidr, uint efficiency)
+{
+ memset(gicc, '\0', sizeof(struct acpi_madt_gicc));
+ gicc->type = ACPI_APIC_GICC;
+ gicc->length = sizeof(struct acpi_madt_gicc);
+ gicc->cpu_if_num = cpu_num;
+ gicc->processor_id = cpu_num;
+ gicc->flags = ACPI_MADTF_ENABLED;
+ gicc->perf_gsiv = perf_gsiv;
+ gicc->phys_base = phys_base;
+ gicc->gicv = gicv;
+ gicc->gich = gich;
+ gicc->vgic_maint_irq = vgic_maint_irq;
+ gicc->gicr_base = gicr_base;
+ gicc->mpidr = mpidr;
+ gicc->efficiency = efficiency;
+}
+
+void acpi_write_madt_gicd(struct acpi_madt_gicd *gicd, uint gic_id,
+ ulong phys_base, uint gic_version)
+{
+ memset(gicd, '\0', sizeof(struct acpi_madt_gicd));
+ gicd->type = ACPI_APIC_GICD;
+ gicd->length = sizeof(struct acpi_madt_gicd);
+ gicd->gic_id = gic_id;
+ gicd->phys_base = phys_base;
+ gicd->gic_version = gic_version;
+}
+
+void acpi_write_madt_gicr(struct acpi_madt_gicr *gicr,
+ u64 discovery_range_base_address,
+ u32 discovery_range_length)
+{
+ memset(gicr, '\0', sizeof(struct acpi_madt_gicr));
+ gicr->type = ACPI_APIC_GICR;
+ gicr->length = sizeof(struct acpi_madt_gicr);
+ gicr->discovery_range_base_address = discovery_range_base_address;
+ gicr->discovery_range_length = discovery_range_length;
+}
+
+void acpi_write_madt_its(struct acpi_madt_its *its,
+ u32 its_id,
+ u64 physical_base_address)
+{
+ memset(its, '\0', sizeof(struct acpi_madt_its));
+ its->type = ACPI_APIC_ITS;
+ its->length = sizeof(struct acpi_madt_its);
+ its->gic_its_id = its_id;
+ its->physical_base_address = physical_base_address;
+}
+
+int acpi_pptt_add_proc(struct acpi_ctx *ctx, const u32 flags, const u32 parent,
+ const u32 proc_id, const u32 num_resources,
+ const u32 *resource_list)
+{
+ struct acpi_pptt_proc *proc = ctx->current;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+ proc->hdr.type = ACPI_PPTT_TYPE_PROC;
+ proc->flags = flags;
+ proc->parent = parent;
+ proc->proc_id = proc_id;
+ proc->num_resources = num_resources;
+ proc->hdr.length = sizeof(struct acpi_pptt_proc) +
+ sizeof(u32) * num_resources;
+
+ if (resource_list)
+ memcpy(proc + 1, resource_list, sizeof(u32) * num_resources);
+
+ acpi_inc(ctx, proc->hdr.length);
+
+ return offset;
+}
+
+int acpi_pptt_add_cache(struct acpi_ctx *ctx, const u32 flags,
+ const u32 next_cache_level, const u32 size,
+ const u32 sets, const u8 assoc, const u8 attributes,
+ const u16 line_size)
+{
+ struct acpi_pptt_cache *cache = ctx->current;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+ cache->hdr.type = ACPI_PPTT_TYPE_CACHE;
+ cache->hdr.length = sizeof(struct acpi_pptt_cache);
+ cache->flags = flags;
+ cache->next_cache_level = next_cache_level;
+ cache->size = size;
+ cache->sets = sets;
+ cache->assoc = assoc;
+ cache->attributes = attributes;
+ cache->line_size = line_size;
+ acpi_inc(ctx, cache->hdr.length);
+
+ return offset;
+}
+
+void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
+{
+ uclass_probe_all(UCLASS_CPU);
+ uclass_probe_all(UCLASS_IRQ);
+
+ /* All SoCs must use the driver model */
+ acpi_fill_madt_subtbl(ctx);
+
+ return ctx->current;
+}
+
+/**
+ * acpi_write_pp_setup_one_page() - Fill out one page used by the PP
+ *
+ * Fill out the struct acpi_pp_page to contain the spin-loop
+ * code and the mailbox area. After this function the page is ready for
+ * the secondary core's to enter the spin-loop code.
+ *
+ * @page: Pointer to current parking protocol page
+ * @gicc: Pointer to corresponding GICC sub-table
+ */
+static void acpi_write_pp_setup_one_page(struct acpi_pp_page *page,
+ struct acpi_madt_gicc *gicc)
+{
+ void *reloc;
+
+ /* Update GICC. Mark parking protocol as available. */
+ gicc->parking_proto = ACPI_PP_VERSION;
+ gicc->parked_addr = virt_to_phys(page);
+
+ /* Prepare parking protocol page */
+ memset(page, '\0', sizeof(struct acpi_pp_page));
+
+ /* Init mailbox. Set MPIDR so core's will find their page. */
+ page->cpu_id = gicc->mpidr;
+ page->jumping_address = ACPI_PP_JMP_ADR_INVALID;
+
+ /* Relocate spinning code */
+ reloc = &page->spinning_code[0];
+
+ log_debug("Relocating spin table from %lx to %lx (size %x)\n",
+ (ulong)&acpi_pp_code_start, (ulong)reloc, acpi_pp_code_size);
+ memcpy(reloc, &acpi_pp_code_start, acpi_pp_code_size);
+
+ if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+ flush_dcache_range((unsigned long)page,
+ (unsigned long)(page + 1));
+}
+
+void acpi_write_park(struct acpi_madt *madt)
+{
+ struct acpi_pp_page *start, *page;
+ struct acpi_madt_gicc *gicc;
+ int ret, i, ncpus = 0;
+
+ /*
+ * According to the "Multi-processor Startup for ARM Platforms":
+ * - Every CPU as specified by MADT GICC has it's own 4K page
+ * - Every page is divided into two sections: OS and FW reserved
+ * - Memory occupied by "Parking Protocol" must be marked 'Reserved'
+ * - Spinloop code should reside in FW reserved 2048 bytes
+ * - Spinloop code will check the mailbox in OS reserved area
+ */
+
+ if (acpi_pp_code_size > sizeof(page->spinning_code)) {
+ log_err("Spinning code too big to fit: %d\n",
+ acpi_pp_code_size);
+ return;
+ }
+
+ /* Count all MADT GICCs including BSP */
+ for (i = sizeof(struct acpi_madt); i < madt->header.length;
+ i += gicc->length) {
+ gicc = (struct acpi_madt_gicc *)((void *)madt + i);
+ if (gicc->type != ACPI_APIC_GICC)
+ continue;
+ ncpus++;
+ }
+ log_debug("Found %#x GICCs in MADT\n", ncpus);
+
+ /* Allocate pages linearly due to assembly code requirements */
+ start = bloblist_add(BLOBLISTT_ACPI_PP, ACPI_PP_PAGE_SIZE * ncpus,
+ ilog2(SZ_4K));
+ if (!start) {
+ log_err("Failed to allocate memory for ACPI-parking-protocol pages\n");
+ return;
+ }
+ log_debug("Allocated parking protocol at %p\n", start);
+ page = start;
+
+ if (IS_ENABLED(CONFIG_EFI_LOADER)) {
+ /* Default mapping is 'BOOT CODE'. Mark as reserved instead. */
+ ret = efi_add_memory_map((u64)(uintptr_t)start,
+ ncpus * ACPI_PP_PAGE_SIZE,
+ EFI_RESERVED_MEMORY_TYPE);
+
+ if (ret)
+ log_err("Reserved memory mapping failed addr %p size %x\n",
+ start, ncpus * ACPI_PP_PAGE_SIZE);
+ }
+
+ /* Prepare the parking protocol pages */
+ for (i = sizeof(struct acpi_madt); i < madt->header.length;
+ i += gicc->length) {
+ gicc = (struct acpi_madt_gicc *)((void *)madt + i);
+ if (gicc->type != ACPI_APIC_GICC)
+ continue;
+
+ acpi_write_pp_setup_one_page(page++, gicc);
+ }
+
+ acpi_pp_etables = virt_to_phys(start) +
+ ACPI_PP_PAGE_SIZE * ncpus;
+ acpi_pp_tables = virt_to_phys(start);
+
+ /* Make sure other cores see written value in memory */
+ if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+ flush_dcache_all();
+
+ /* Send an event to wake up the secondary CPU. */
+ asm("dsb ishst\n"
+ "sev");
+}
diff --git a/arch/arm/lib/gic-v2.c b/arch/arm/lib/gic-v2.c
new file mode 100644
index 00000000000..b70434a45d4
--- /dev/null
+++ b/arch/arm/lib/gic-v2.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Broadcom.
+ */
+#include <dm.h>
+#include <irq.h>
+#include <asm/gic.h>
+#include <asm/acpi_table.h>
+#include <cpu_func.h>
+#include <dm/acpi.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#ifdef CONFIG_ACPIGEN
+/**
+ * acpi_gicv2_fill_madt() - Fill out the body of the MADT
+ *
+ * Write GICD and GICR tables based on collected devicetree data.
+ *
+ * @dev: Device to write ACPI tables for
+ * @ctx: ACPI context to write MADT sub-tables to
+ * Return: 0 if OK
+ */
+static int acpi_gicv2_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ struct acpi_madt_gicd *gicd;
+ fdt_addr_t addr;
+
+ addr = dev_read_addr_index(dev, 0);
+ if (addr == FDT_ADDR_T_NONE) {
+ pr_err("%s: failed to get GICD address\n", __func__);
+ return -EINVAL;
+ }
+
+ gicd = ctx->current;
+ acpi_write_madt_gicd(gicd, dev_seq(dev), addr, 2);
+ acpi_inc(ctx, gicd->length);
+
+ return 0;
+}
+
+static struct acpi_ops gic_v2_acpi_ops = {
+ .fill_madt = acpi_gicv2_fill_madt,
+};
+#endif
+
+static const struct udevice_id gic_v2_ids[] = {
+ { .compatible = "arm,arm11mp-gic" },
+ { .compatible = "arm,cortex-a15-gic" },
+ { .compatible = "arm,cortex-a7-gic" },
+ { .compatible = "arm,cortex-a5-gic" },
+ { .compatible = "arm,cortex-a9-gic" },
+ { .compatible = "arm,eb11mp-gic" },
+ { .compatible = "arm,gic-400" },
+ { .compatible = "arm,pl390" },
+ { .compatible = "arm,tc11mp-gic" },
+ { .compatible = "qcom,msm-8660-qgic" },
+ { .compatible = "qcom,msm-qgic2" },
+ {}
+};
+
+static int arm_gic_v2_of_xlate(struct irq *irq, struct ofnode_phandle_args *args)
+{
+ if (args->args_count != 3) {
+ log_debug("Invalid args_count: %d\n", args->args_count);
+ return -EINVAL;
+ }
+
+ /* ARM Generic Interrupt Controller v1 and v2 */
+ if (args->args[0] == GIC_SPI)
+ irq->id = args->args[1] + 32;
+ else
+ irq->id = args->args[1] + 16;
+
+ irq->flags = args->args[2];
+
+ return 0;
+}
+
+static const struct irq_ops arm_gic_v2_ops = {
+ .of_xlate = arm_gic_v2_of_xlate,
+};
+
+U_BOOT_DRIVER(arm_gic_v2) = {
+ .name = "gic-v2",
+ .id = UCLASS_IRQ,
+ .of_match = gic_v2_ids,
+ .ops = &arm_gic_v2_ops,
+ ACPI_OPS_PTR(&gic_v2_acpi_ops)
+};
diff --git a/arch/arm/lib/gic-v3-its.c b/arch/arm/lib/gic-v3-its.c
index 2cc0a32f9d4..51cc2397768 100644
--- a/arch/arm/lib/gic-v3-its.c
+++ b/arch/arm/lib/gic-v3-its.c
@@ -4,9 +4,13 @@
*/
#include <cpu_func.h>
#include <dm.h>
+#include <irq.h>
+#include <asm/acpi_table.h>
#include <asm/gic.h>
#include <asm/gic-v3.h>
#include <asm/io.h>
+#include <dm/acpi.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <linux/bitops.h>
#include <linux/printk.h>
#include <linux/sizes.h>
@@ -26,19 +30,21 @@ static u32 lpi_id_bits;
struct gic_v3_its_priv {
ulong gicd_base;
ulong gicr_base;
+ ulong gicr_length;
};
static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv)
{
struct udevice *dev;
fdt_addr_t addr;
+ fdt_size_t size;
int ret;
ret = uclass_get_device_by_driver(UCLASS_IRQ,
- DM_DRIVER_GET(arm_gic_v3_its), &dev);
+ DM_DRIVER_GET(arm_gic_v3), &dev);
if (ret) {
pr_err("%s: failed to get %s irq device\n", __func__,
- DM_DRIVER_GET(arm_gic_v3_its)->name);
+ DM_DRIVER_GET(arm_gic_v3)->name);
return ret;
}
@@ -49,12 +55,13 @@ static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv)
}
priv->gicd_base = addr;
- addr = dev_read_addr_index(dev, 1);
+ addr = dev_read_addr_size_index(dev, 1, &size);
if (addr == FDT_ADDR_T_NONE) {
pr_err("%s: failed to get GICR address\n", __func__);
return -EINVAL;
}
priv->gicr_base = addr;
+ priv->gicr_length = size;
return 0;
}
@@ -158,13 +165,117 @@ int gic_lpi_tables_init(u64 base, u32 num_redist)
return 0;
}
-static const struct udevice_id gic_v3_its_ids[] = {
+#ifdef CONFIG_ACPIGEN
+/**
+ * acpi_gicv3_fill_madt() - Fill out the body of the MADT
+ *
+ * Write GICD and GICR tables based on collected devicetree data.
+ *
+ * @dev: Device to write ACPI tables for
+ * @ctx: ACPI context to write MADT sub-tables to
+ * Return: 0 if OK
+ */
+static int acpi_gicv3_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ struct acpi_madt_gicd *gicd;
+ struct acpi_madt_gicr *gicr;
+
+ struct gic_v3_its_priv priv;
+
+ if (gic_v3_its_get_gic_addr(&priv))
+ return -EINVAL;
+
+ gicd = ctx->current;
+ acpi_write_madt_gicd(gicd, dev_seq(dev), priv.gicd_base, 3);
+ acpi_inc(ctx, gicd->length);
+
+ gicr = ctx->current;
+ acpi_write_madt_gicr(gicr, priv.gicr_base, priv.gicr_length);
+ acpi_inc(ctx, gicr->length);
+
+ return 0;
+}
+
+struct acpi_ops gic_v3_acpi_ops = {
+ .fill_madt = acpi_gicv3_fill_madt,
+};
+#endif
+
+static const struct udevice_id gic_v3_ids[] = {
{ .compatible = "arm,gic-v3" },
{}
};
-U_BOOT_DRIVER(arm_gic_v3_its) = {
+static int arm_gic_v3_of_xlate(struct irq *irq, struct ofnode_phandle_args *args)
+{
+ if (args->args_count < 3) {
+ log_debug("Invalid args_count: %d\n", args->args_count);
+ return -EINVAL;
+ }
+
+ if (args->args[0] == GIC_SPI)
+ irq->id = args->args[1] + 32;
+ else
+ irq->id = args->args[1] + 16;
+
+ irq->flags = args->args[2];
+
+ return 0;
+}
+
+static const struct irq_ops arm_gic_v3_ops = {
+ .of_xlate = arm_gic_v3_of_xlate,
+};
+
+U_BOOT_DRIVER(arm_gic_v3) = {
.name = "gic-v3",
.id = UCLASS_IRQ,
+ .of_match = gic_v3_ids,
+ .ops = &arm_gic_v3_ops,
+ ACPI_OPS_PTR(&gic_v3_acpi_ops)
+};
+
+#ifdef CONFIG_ACPIGEN
+/**
+ * acpi_gic_its_fill_madt() - Fill out the body of the MADT
+ *
+ * Write ITS tables based on collected devicetree data.
+ *
+ * @dev: Device to write ACPI tables for
+ * @ctx: ACPI context to write MADT sub-tables to
+ * Return: 0 if OK
+ */
+static int acpi_gic_its_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ struct acpi_madt_its *its;
+ fdt_addr_t addr;
+
+ addr = dev_read_addr_index(dev, 0);
+ if (addr == FDT_ADDR_T_NONE) {
+ pr_err("%s: failed to get GIC ITS address\n", __func__);
+ return -EINVAL;
+ }
+
+ its = ctx->current;
+ acpi_write_madt_its(its, dev_seq(dev), addr);
+ acpi_inc(ctx, its->length);
+
+ return 0;
+}
+
+struct acpi_ops gic_v3_its_acpi_ops = {
+ .fill_madt = acpi_gic_its_fill_madt,
+};
+#endif
+
+static const struct udevice_id gic_v3_its_ids[] = {
+ { .compatible = "arm,gic-v3-its" },
+ {}
+};
+
+U_BOOT_DRIVER(arm_gic_v3_its) = {
+ .name = "gic-v3-its",
+ .id = UCLASS_IRQ,
.of_match = gic_v3_its_ids,
+ ACPI_OPS_PTR(&gic_v3_its_acpi_ops)
};
diff --git a/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig
index b3287ce8bce..d9303e8c281 100644
--- a/arch/arm/mach-bcm283x/Kconfig
+++ b/arch/arm/mach-bcm283x/Kconfig
@@ -24,7 +24,13 @@ config BCM2837_64B
bool "Broadcom BCM2837 SoC 64-bit support"
depends on ARCH_BCM283X
select BCM2837
+ select DRIVER_GICV2
select ARM64
+ select CPU_ARMV8
+ select ARMV8_MULTIENTRY if GENERATE_ACPI_TABLE
+ select BLOBLIST if GENERATE_ACPI_TABLE
+ select BLOBLIST_ALLOC if GENERATE_ACPI_TABLE
+ select BLOBLIST_TABLES if GENERATE_ACPI_TABLE
config BCM2711
bool "Broadcom BCM2711 SoC support"
@@ -42,11 +48,16 @@ config BCM2711_64B
bool "Broadcom BCM2711 SoC 64-bit support"
depends on ARCH_BCM283X
select BCM2711
+ select DRIVER_GICV2
select ARM64
+ select CPU_ARMV8
+ select ARMV8_MULTIENTRY if GENERATE_ACPI_TABLE
+ select BLOBLIST if GENERATE_ACPI_TABLE
+ select BLOBLIST_ALLOC if GENERATE_ACPI_TABLE
+ select BLOBLIST_TABLES if GENERATE_ACPI_TABLE
menu "Broadcom BCM283X family"
depends on ARCH_BCM283X
-
choice
prompt "Broadcom BCM283X board select"
optional
@@ -210,6 +221,9 @@ config SYS_SOC
config SYS_CONFIG_NAME
default "rpi"
+config BLOBLIST_SIZE_RELOC
+ default 0x20000
+
source "board/raspberrypi/rpi/Kconfig"
endmenu
diff --git a/arch/arm/mach-bcm283x/Makefile b/arch/arm/mach-bcm283x/Makefile
index 7cd068832f3..38e320307d9 100644
--- a/arch/arm/mach-bcm283x/Makefile
+++ b/arch/arm/mach-bcm283x/Makefile
@@ -4,3 +4,7 @@
obj-$(CONFIG_BCM2835) += lowlevel_init.o
obj-y += init.o reset.o mbox.o msg.o phys2bus.o
+
+ifeq ($(CONFIG_GENERATE_ACPI_TABLE),y)
+obj-$(CONFIG_BCM2711) += bcm2711_acpi.o
+endif \ No newline at end of file
diff --git a/arch/arm/mach-bcm283x/bcm2711_acpi.c b/arch/arm/mach-bcm283x/bcm2711_acpi.c
new file mode 100644
index 00000000000..79b283353cf
--- /dev/null
+++ b/arch/arm/mach-bcm283x/bcm2711_acpi.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2024 9elements GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ */
+
+#include <string.h>
+#include <tables_csum.h>
+#include <acpi/acpi_table.h>
+#include <asm/acpi_table.h>
+#include <asm/armv8/sec_firmware.h>
+#include <asm/arch/acpi/bcm2711.h>
+#include <dm/uclass.h>
+
+void acpi_fill_fadt(struct acpi_fadt *fadt)
+{
+ fadt->flags = ACPI_FADT_HW_REDUCED_ACPI | ACPI_FADT_LOW_PWR_IDLE_S0;
+
+ if (CONFIG_IS_ENABLED(SEC_FIRMWARE_ARMV8_PSCI) &&
+ sec_firmware_support_psci_version() != PSCI_INVALID_VER)
+ fadt->arm_boot_arch = ACPI_ARM_PSCI_COMPLIANT;
+}
+
+#define L3_ATTRIBUTES (ACPI_PPTT_READ_ALLOC | ACPI_PPTT_WRITE_ALLOC | \
+ (ACPI_PPTT_CACHE_TYPE_UNIFIED << \
+ ACPI_PPTT_CACHE_TYPE_SHIFT))
+#define L3_SIZE 0x100000
+#define L3_SETS 0x400
+#define L3_WAYS 0x10
+
+#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 0xc000
+#define L1I_SETS 0x100
+#define L1I_WAYS 3
+
+static int acpi_write_pptt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_header *header;
+ int cluster_offset, l3_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));
+
+ l3_offset = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_VALID, 0, L3_SIZE,
+ L3_SETS, L3_WAYS, L3_ATTRIBUTES, 64);
+
+ cluster_offset = acpi_pptt_add_proc(ctx, ACPI_PPTT_PHYSICAL_PACKAGE |
+ ACPI_PPTT_CHILDREN_IDENTICAL,
+ 0, 0, 1, &l3_offset);
+
+ offsets[0] = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_VALID, 0, L1D_SIZE,
+ L1D_SETS, L1D_WAYS, L1D_ATTRIBUTES, 64);
+
+ offsets[1] = acpi_pptt_add_cache(ctx, ACPI_PPTT_ALL_BUT_WRITE_POL, 0,
+ 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);
+
+static int rpi_write_gtdt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_header *header;
+ struct acpi_gtdt *gtdt;
+
+ gtdt = ctx->current;
+ header = &gtdt->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 = BCM2711_ARM_LOCAL_BASE_ADDRESS + 0x1c;
+ 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;
+
+ 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", rpi_write_gtdt, 0);
diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h
new file mode 100644
index 00000000000..a86875b1833
--- /dev/null
+++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: BSD-2-Clause-Patent */
+/**
+ *
+ * Copyright (c) 2019, Jeremy Linton
+ * Copyright (c) 2019, Pete Batard <pete@akeo.ie>.
+ *
+ **/
+
+#ifndef BCM2711_H__
+#define BCM2711_H__
+
+#define BCM2711_SOC_REGISTERS 0xfc000000
+#define BCM2711_SOC_REGISTER_LENGTH 0x02000000
+
+#define BCM2711_ARM_LOCAL_REGISTERS 0xfe000000
+#define BCM2711_ARM_LOCAL_REGISTER_LENGTH 0x02000000
+
+/* arm local addresses */
+#define BCM2711_ARMC_OFFSET 0x0000b000
+#define BCM2711_ARMC_BASE_ADDRESS (BCM2711_ARM_LOCAL_REGISTERS + BCM2711_ARMC_OFFSET)
+#define BCM2711_ARMC_LENGTH 0x00000400
+
+#define BCM2711_ARM_LOCAL_OFFSET 0x01800000
+#define BCM2711_ARM_LOCAL_BASE_ADDRESS (BCM2711_ARM_LOCAL_REGISTERS + BCM2711_ARM_LOCAL_OFFSET)
+#define BCM2711_ARM_LOCAL_LENGTH 0x00000080
+
+#define BCM2711_GIC400_OFFSET 0x01840000
+#define BCM2711_GIC400_BASE_ADDRESS (BCM2711_ARM_LOCAL_REGISTERS + BCM2711_GIC400_OFFSET)
+#define BCM2711_GIC400_LENGTH 0x00008000
+
+/* Generic PCI addresses */
+#define PCIE_TOP_OF_MEM_WIN 0xf8000000
+#define PCIE_CPU_MMIO_WINDOW 0x600000000
+#define PCIE_BRIDGE_MMIO_LEN 0x3ffffff
+
+/* PCI root bridge control registers location */
+#define PCIE_REG_BASE 0xfd500000
+#define PCIE_REG_LIMIT 0x9310
+
+/* PCI root bridge control registers */
+#define BRCM_PCIE_CAP_REGS 0x00ac
+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 0x0188
+#define VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN 0x0
+#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
+#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc
+#define LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00
+
+#define PCIE_RC_DL_MDIO_ADDR 0x1100
+#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
+#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
+
+#define PCIE_MISC_MISC_CTRL 0x4008
+#define MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
+#define MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
+#define MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
+#define MISC_CTRL_MAX_BURST_SIZE_128 0x0
+#define MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
+
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
+#define PCIE_MEM_WIN0_LO(win) \
+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + ((win) * 4)
+
+#define PCIE_MEM_WIN0_HI(win) \
+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + ((win) * 4)
+#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
+#define RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
+#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
+#define RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
+#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
+#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
+#define RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
+#define PCIE_MISC_PCIE_STATUS 0x4068
+#define STATUS_PCIE_PORT_MASK 0x80
+#define STATUS_PCIE_PORT_SHIFT 7
+#define STATUS_PCIE_DL_ACTIVE_MASK 0x20
+#define STATUS_PCIE_DL_ACTIVE_SHIFT 5
+#define STATUS_PCIE_PHYLINKUP_MASK 0x10
+#define STATUS_PCIE_PHYLINKUP_SHIFT 4
+#define PCIE_MISC_REVISION 0x406c
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
+#define MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
+#define MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
+#define MEM_WIN0_BASE_LIMIT_BASE_HI_SHIFT 12
+#define PCIE_MEM_WIN0_BASE_LIMIT(win) \
+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT + ((win) * 4)
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080
+#define MEM_WIN0_BASE_HI_BASE_MASK 0xff
+#define PCIE_MEM_WIN0_BASE_HI(win) \
+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI + ((win) * 8)
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
+#define PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
+#define PCIE_MEM_WIN0_LIMIT_HI(win) \
+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
+
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
+#define PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
+
+#define PCIE_INTR2_CPU_STATUS 0x4300
+#define PCIE_INTR2_CPU_SET 0x4304
+#define PCIE_INTR2_CPU_CLR 0x4308
+#define PCIE_INTR2_CPU_MASK_STATUS 0x430c
+#define PCIE_INTR2_CPU_MASK_SET 0x4310
+#define PCIE_INTR2_CPU_MASK_CLR 0x4314
+
+#define PCIE_MSI_INTR2_CLR 0x4508
+#define PCIE_MSI_INTR2_MASK_SET 0x4510
+
+#define PCIE_RGR1_SW_INIT_1 0x9210
+#define PCIE_EXT_CFG_INDEX 0x9000
+/* A small window pointing at the ECAM of the device selected by CFG_INDEX */
+#define PCIE_EXT_CFG_DATA 0x8000
+
+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
+#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
+
+#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
+#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
+#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
+#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
+#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK 0x7c00000
+#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK 0x1f
+#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
+
+#define PCIE_RGR1_SW_INIT_1_INIT_MASK 0x2
+#define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1
+
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
+
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
+
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK 0xff
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_MASK_BITS 0xc
+
+#define PCIE_MISC_REVISION_MAJMIN_MASK 0xffff
+
+#define BURST_SIZE_128 0
+#define BURST_SIZE_256 1
+#define BURST_SIZE_512 2
+
+#define BCM2711_THERM_SENSOR_OFFSET 0x015d2200
+#define BCM2711_THERM_SENSOR_BASE_ADDRESS (BCM2711_SOC_REGISTERS + BCM2711_THERM_SENSOR_OFFSET)
+#define BCM2711_THERM_SENSOR_LENGTH 0x00000008
+
+#define BCM2711_GENET_BASE_OFFSET 0x01580000
+#define BCM2711_GENET_BASE_ADDRESS (BCM2711_SOC_REGISTERS + BCM2711_GENET_BASE_OFFSET)
+#define BCM2711_GENET_LENGTH 0x10000
+
+#endif /* BCM2711_H__ */
diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836.h b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836.h
new file mode 100644
index 00000000000..64cec36a948
--- /dev/null
+++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: BSD-2-Clause-Patent */
+/**
+ *
+ * Copyright (c) 2019, ARM Limited. All rights reserved.
+ * Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) 2016, Linaro Limited. All rights reserved.
+ *
+ **/
+
+#ifndef __BCM2836_H__
+#define __BCM2836_H__
+
+/*
+ * Both "core" and SoC perpherals (1M each).
+ */
+#define BCM2836_SOC_REGISTERS 0xfe000000
+#define BCM2836_SOC_REGISTER_LENGTH 0x02000000
+
+/*
+ * Offset between the CPU's view and the VC's view of system memory.
+ */
+#define BCM2836_DMA_DEVICE_OFFSET 0xc0000000
+
+/* watchdog constants */
+#define BCM2836_WDOG_OFFSET 0x00100000
+#define BCM2836_WDOG_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_WDOG_OFFSET)
+#define BCM2836_WDOG_PASSWORD 0x5a000000
+#define BCM2836_WDOG_RSTC_OFFSET 0x0000001c
+#define BCM2836_WDOG_WDOG_OFFSET 0x00000024
+#define BCM2836_WDOG_RSTC_WRCFG_MASK 0x00000030
+#define BCM2836_WDOG_RSTC_WRCFG_FULL_RESET 0x00000020
+
+/* clock manager constants */
+#define BCM2836_CM_OFFSET 0x00101000
+#define BCM2836_CM_BASE (BCM2836_SOC_REGISTERS + BCM2836_CM_OFFSET)
+#define BCM2836_CM_GEN_CLOCK_CONTROL 0x0000
+#define BCM2836_CM_GEN_CLOCK_DIVISOR 0x0004
+#define BCM2836_CM_VPU_CLOCK_CONTROL 0x0008
+#define BCM2836_CM_VPU_CLOCK_DIVISOR 0x000c
+#define BCM2836_CM_SYSTEM_CLOCK_CONTROL 0x0010
+#define BCM2836_CM_SYSTEM_CLOCK_DIVISOR 0x0014
+#define BCM2836_CM_H264_CLOCK_CONTROL 0x0028
+#define BCM2836_CM_H264_CLOCK_DIVISOR 0x002c
+#define BCM2836_CM_PWM_CLOCK_CONTROL 0x00a0
+#define BCM2836_CM_PWM_CLOCK_DIVISOR 0x00a4
+#define BCM2836_CM_UART_CLOCK_CONTROL 0x00f0
+#define BCM2836_CM_UART_CLOCK_DIVISOR 0x00f4
+#define BCM2836_CM_SDC_CLOCK_CONTROL 0x01a8
+#define BCM2836_CM_SDC_CLOCK_DIVISOR 0x01ac
+#define BCM2836_CM_ARM_CLOCK_CONTROL 0x01b0
+#define BCM2836_CM_ARM_CLOCK_DIVISOR 0x01b4
+#define BCM2836_CM_EMMC_CLOCK_CONTROL 0x01c0
+#define BCM2836_CM_EMMC_CLOCK_DIVISOR 0x01c4
+
+/* mailbox interface constants */
+#define BCM2836_MBOX_OFFSET 0x0000b880
+#define BCM2836_MBOX_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_MBOX_OFFSET)
+#define BCM2836_MBOX_LENGTH 0x00000024
+#define BCM2836_MBOX_READ_OFFSET 0x00000000
+#define BCM2836_MBOX_STATUS_OFFSET 0x00000018
+#define BCM2836_MBOX_CONFIG_OFFSET 0x0000001c
+#define BCM2836_MBOX_WRITE_OFFSET 0x00000020
+
+#define BCM2836_MBOX_STATUS_FULL 0x1f
+#define BCM2836_MBOX_STATUS_EMPTY 0x1e
+
+#define BCM2836_MBOX_NUM_CHANNELS 16
+
+/* interrupt controller constants */
+#define BCM2836_INTC_TIMER_CONTROL_OFFSET 0x00000040
+#define BCM2836_INTC_TIMER_PENDING_OFFSET 0x00000060
+
+/* usb constants */
+#define BCM2836_USB_OFFSET 0x00980000
+#define BCM2836_USB_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_USB_OFFSET)
+#define BCM2836_USB_LENGTH 0x00010000
+
+/* serial based protocol constants */
+#define BCM2836_PL011_UART_OFFSET 0x00201000
+#define BCM2836_PL011_UART_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PL011_UART_OFFSET)
+#define BCM2836_PL011_UART_LENGTH 0x00001000
+
+#define BCM2836_MINI_UART_OFFSET 0x00215000
+#define BCM2836_MINI_UART_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_MINI_UART_OFFSET)
+#define BCM2836_MINI_UART_LENGTH 0x00000070
+
+#define BCM2836_I2C0_OFFSET 0x00205000
+#define BCM2836_I2C0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_I2C0_OFFSET)
+#define BCM2836_I2C0_LENGTH 0x00000020
+
+#define BCM2836_I2C1_OFFSET 0x00804000
+#define BCM2836_I2C1_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_I2C1_OFFSET)
+#define BCM2836_I2C1_LENGTH 0x00000020
+
+#define BCM2836_I2C2_OFFSET 0x00805000
+#define BCM2836_I2C2_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_I2C2_OFFSET)
+#define BCM2836_I2C2_LENGTH 0x00000020
+
+#define BCM2836_SPI0_OFFSET 0x00204000
+#define BCM2836_SPI0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_SPI0_OFFSET)
+#define BCM2836_SPI0_LENGTH 0x00000020
+
+#define BCM2836_SPI1_OFFSET 0x00215080
+#define BCM2836_SPI1_LENGTH 0x00000040
+#define BCM2836_SPI1_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_SPI1_OFFSET)
+
+#define BCM2836_SPI2_OFFSET 0x002150C0
+#define BCM2836_SPI2_LENGTH 0x00000040
+#define BCM2836_SPI2_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_SPI2_OFFSET)
+
+#define BCM2836_SYSTEM_TIMER_OFFSET 0x00003000
+#define BCM2836_SYSTEM_TIMER_LENGTH 0x00000020
+#define BCM2836_SYSTEM_TIMER_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_SYSTEM_TIMER_OFFSET)
+
+/* dma constants */
+#define BCM2836_DMA0_OFFSET 0x00007000
+#define BCM2836_DMA0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_DMA0_OFFSET)
+
+#define BCM2836_DMA15_OFFSET 0x00E05000
+#define BCM2836_DMA15_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_DMA15_OFFSET)
+
+#define BCM2836_DMA_CTRL_OFFSET 0x00007FE0
+#define BCM2836_DMA_CTRL_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_DMA_CTRL_OFFSET)
+
+#define BCM2836_DMA_CHANNEL_LENGTH 0x00000100
+
+#endif /*__BCM2836_H__ */
diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpio.h b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpio.h
new file mode 100644
index 00000000000..c5b858b412d
--- /dev/null
+++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpio.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-2-Clause-Patent */
+/**
+ *
+ * Copyright (c) 2020, Pete Batard <pete@akeo.ie>
+ * Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ **/
+
+#include <asm/arch/acpi/bcm2836.h>
+
+#ifndef __BCM2836_GPIO_H__
+#define __BCM2836_GPIO_H__
+
+#define GPIO_OFFSET 0x00200000
+#define GPIO_BASE_ADDRESS (BCM2836_SOC_REGISTERS + GPIO_OFFSET)
+#define GPIO_LENGTH 0x000000B4
+
+#endif /* __BCM2836_GPIO_H__ */
diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpu.h b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpu.h
new file mode 100644
index 00000000000..5857d7581a9
--- /dev/null
+++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_gpu.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: BSD-2-Clause-Patent */
+/**
+ *
+ * Copyright (c) 2020, Pete Batard <pete@akeo.ie>
+ *
+ **/
+
+#include <asm/arch/acpi/bcm2836.h>
+
+#ifndef __BCM2836_GPU_H__
+#define __BCM2836_GPU_H__
+
+/* VideoCore constants */
+
+#define BCM2836_VCHIQ_OFFSET 0x0000B840
+#define BCM2836_VCHIQ_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_VCHIQ_OFFSET)
+#define BCM2836_VCHIQ_LENGTH 0x00000010
+
+#define BCM2836_V3D_BUS_OFFSET 0x00C00000
+#define BCM2836_V3D_BUS_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_V3D_BUS_OFFSET)
+#define BCM2836_V3D_BUS_LENGTH 0x00001000
+
+#define BCM2836_HVS_OFFSET 0x00400000
+#define BCM2836_HVS_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_HVS_OFFSET)
+#define BCM2836_HVS_LENGTH 0x00006000
+
+#define BCM2836_PV0_OFFSET 0x00206000
+#define BCM2836_PV0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PV0_OFFSET)
+#define BCM2836_PV0_LENGTH 0x00000100
+
+#define BCM2836_PV1_OFFSET 0x00207000
+#define BCM2836_PV1_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PV1_OFFSET)
+#define BCM2836_PV1_LENGTH 0x00000100
+
+#define BCM2836_PV2_OFFSET 0x00807000
+#define BCM2836_PV2_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PV2_OFFSET)
+#define BCM2836_PV2_LENGTH 0x00000100
+
+#define BCM2836_HDMI0_OFFSET 0x00902000
+#define BCM2836_HDMI0_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_HDMI0_OFFSET)
+#define BCM2836_HDMI0_LENGTH 0x00000600
+
+#define BCM2836_HDMI1_OFFSET 0x00808000
+#define BCM2836_HDMI1_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_HDMI1_OFFSET)
+#define BCM2836_HDMI1_LENGTH 0x00000100
+
+#endif /* __BCM2836_MISC_H__ */
diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_pwm.h b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_pwm.h
new file mode 100644
index 00000000000..78a84866732
--- /dev/null
+++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_pwm.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: BSD-2-Clause-Patent */
+/**
+ *
+ * Copyright (c) 2020, Pete Batard <pete@akeo.ie>
+ *
+ **/
+
+#include <asm/arch/acpi/bcm2836.h>
+
+#ifndef __BCM2836_PWM_H__
+#define __BCM2836_PWM_H__
+
+/* PWM controller constants */
+
+#define BCM2836_PWM_DMA_OFFSET 0x00007B00
+#define BCM2836_PWM_DMA_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PWM_DMA_OFFSET)
+#define BCM2836_PWM_DMA_LENGTH 0x00000100
+
+#define BCM2836_PWM_CLK_OFFSET 0x001010A0
+#define BCM2836_PWM_CLK_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PWM_CLK_OFFSET)
+#define BCM2836_PWM_CLK_LENGTH 0x00000008
+
+#define BCM2836_PWM_CTRL_OFFSET 0x0020C000
+#define BCM2836_PWM_CTRL_BASE_ADDRESS (BCM2836_SOC_REGISTERS + BCM2836_PWM_CTRL_OFFSET)
+#define BCM2836_PWM_CTRL_LENGTH 0x00000028
+
+#define BCM2836_PWM_BUS_BASE_ADDRESS 0x7E20C000
+#define BCM2836_PWM_BUS_LENGTH 0x00000028
+
+#define BCM2836_PWM_CTRL_UNCACHED_BASE_ADDRESS 0xFF20C000
+#define BCM2836_PWM_CTRL_UNCACHED_LENGTH 0x00000028
+
+#endif /* __BCM2836_PWM_H__ */
diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdhost.h b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdhost.h
new file mode 100644
index 00000000000..9b1afe84401
--- /dev/null
+++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdhost.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-2-Clause-Patent */
+/**
+ *
+ * Copyright (c) 2017, Andrei Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ **/
+
+#include <asm/arch/acpi/bcm2836.h>
+
+#ifndef __BCM2836_SDHOST_H__
+#define __BCM2836_SDHOST_H__
+
+#define SDHOST_OFFSET 0x00202000
+#define SDHOST_BASE_ADDRESS (BCM2836_SOC_REGISTERS + SDHOST_OFFSET)
+#define SDHOST_LENGTH 0x00000100
+
+#endif /*__BCM2836_SDHOST_H__ */
diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdio.h b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdio.h
new file mode 100644
index 00000000000..48d073d4340
--- /dev/null
+++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2836_sdio.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-2-Clause-Patent */
+/**
+ *
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ **/
+
+#include <asm/arch/acpi/bcm2836.h>
+
+#ifndef __BCM2836_SDIO_H__
+#define __BCM2836_SDIO_H__
+
+// MMC/SD/SDIO1 register definitions.
+#define MMCHS1_OFFSET 0x00300000
+#define MMCHS2_OFFSET 0x00340000
+#define MMCHS1_BASE (BCM2836_SOC_REGISTERS + MMCHS1_OFFSET)
+#define MMCHS2_BASE (BCM2836_SOC_REGISTERS + MMCHS2_OFFSET)
+#define MMCHS1_LENGTH 0x00000100
+#define MMCHS2_LENGTH 0x00000100
+
+#endif /* __BCM2836_SDIO_H__ */
diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
index 1b459707bc6..7a1de22e0ae 100644
--- a/arch/arm/mach-bcm283x/init.c
+++ b/arch/arm/mach-bcm283x/init.c
@@ -50,7 +50,7 @@ static struct mm_region bcm2711_mem_map[MEM_MAP_MAX_ENTRIES] = {
}, {
.virt = 0xfc000000UL,
.phys = 0xfc000000UL,
- .size = 0x03800000UL,
+ .size = 0x04000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
diff --git a/arch/arm/mach-qemu/Kconfig b/arch/arm/mach-qemu/Kconfig
index 186c3582ebf..9c06c6a3a5c 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