summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.azure-pipelines.yml8
-rw-r--r--.gitlab-ci.yml11
-rw-r--r--MAINTAINERS2
-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
-rw-r--r--arch/sandbox/dts/test.dts3
-rw-r--r--arch/sandbox/lib/Makefile9
-rw-r--r--arch/sandbox/lib/acpi_table.c11
-rw-r--r--arch/x86/cpu/apollolake/acpi.c20
-rw-r--r--arch/x86/cpu/baytrail/acpi.c17
-rw-r--r--arch/x86/cpu/intel_common/acpi.c22
-rw-r--r--arch/x86/cpu/quark/acpi.c19
-rw-r--r--arch/x86/cpu/tangier/acpi.c33
-rw-r--r--arch/x86/include/asm/acpi_table.h28
-rw-r--r--arch/x86/lib/acpi_table.c245
-rw-r--r--board/emulation/qemu-arm/MAINTAINERS2
-rw-r--r--board/emulation/qemu-sbsa/Kconfig59
-rw-r--r--board/emulation/qemu-sbsa/Makefile8
-rw-r--r--board/emulation/qemu-sbsa/acpi.c192
-rw-r--r--board/emulation/qemu-sbsa/dsdt.asl483
-rw-r--r--board/emulation/qemu-sbsa/lowlevel_init.S22
-rw-r--r--board/emulation/qemu-sbsa/qemu-sbsa.c273
-rw-r--r--board/emulation/qemu-sbsa/qemu-sbsa.env14
-rw-r--r--board/emulation/qemu-sbsa/qemu-sbsa.h38
-rw-r--r--board/emulation/qemu-sbsa/smc.c71
-rw-r--r--board/raspberrypi/rpi/.gitignore3
-rw-r--r--board/raspberrypi/rpi/Makefile2
-rw-r--r--board/raspberrypi/rpi/acpitables.h90
-rw-r--r--board/raspberrypi/rpi/dsdt.asl254
-rw-r--r--board/raspberrypi/rpi/emmc.asl136
-rw-r--r--board/raspberrypi/rpi/gpudevs.asl372
-rw-r--r--board/raspberrypi/rpi/pci.asl177
-rw-r--r--board/raspberrypi/rpi/pep.asl90
-rw-r--r--board/raspberrypi/rpi/rhpx.asl195
-rw-r--r--board/raspberrypi/rpi/rpi.c183
-rw-r--r--board/raspberrypi/rpi/sdhc.asl111
-rw-r--r--board/raspberrypi/rpi/uart.asl208
-rw-r--r--boot/bootflow.c8
-rw-r--r--common/Kconfig1
-rw-r--r--common/bloblist.c2
-rw-r--r--configs/clearfog_defconfig2
-rw-r--r--configs/clearfog_gt_8k_defconfig2
-rw-r--r--configs/clearfog_sata_defconfig2
-rw-r--r--configs/clearfog_spi_defconfig2
-rw-r--r--configs/db-88f6820-gp_defconfig2
-rw-r--r--configs/ds116_defconfig2
-rw-r--r--configs/helios4_defconfig2
-rw-r--r--configs/mvebu_crb_cn9130_defconfig2
-rw-r--r--configs/mvebu_db-88f3720_defconfig2
-rw-r--r--configs/mvebu_db_armada8k_defconfig2
-rw-r--r--configs/mvebu_db_cn9130_defconfig2
-rw-r--r--configs/mvebu_espressobin-88f3720_defconfig2
-rw-r--r--configs/mvebu_espressobin_ultra-88f3720_defconfig2
-rw-r--r--configs/mvebu_mcbin-88f8040_defconfig2
-rw-r--r--configs/mvebu_puzzle-m801-88f8040_defconfig2
-rw-r--r--configs/n2350_defconfig2
-rw-r--r--configs/octeon_nic23_defconfig2
-rw-r--r--configs/qemu-arm-sbsa_defconfig12
-rw-r--r--configs/rpi_4_acpi_defconfig10
-rw-r--r--configs/turris_omnia_defconfig2
-rw-r--r--doc/board/emulation/index.rst1
-rw-r--r--doc/board/emulation/qemu-sbsa.rst98
-rw-r--r--doc/develop/driver-model/virtio.rst1
-rw-r--r--drivers/ata/Kconfig12
-rw-r--r--drivers/ata/Makefile2
-rw-r--r--drivers/ata/ahci_generic.c (renamed from drivers/ata/ahci_mvebu.c)17
-rw-r--r--drivers/core/acpi.c16
-rw-r--r--drivers/cpu/Kconfig7
-rw-r--r--drivers/cpu/Makefile2
-rw-r--r--drivers/cpu/armv8_cpu.c151
-rw-r--r--drivers/cpu/armv8_cpu.h31
-rw-r--r--drivers/cpu/bcm283x_cpu.c214
-rw-r--r--drivers/misc/irq-uclass.c66
-rw-r--r--drivers/pci/pcie_brcmstb.c101
-rw-r--r--drivers/serial/serial_pl01x.c24
-rw-r--r--drivers/usb/host/Kconfig8
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/xhci-generic.c75
-rw-r--r--include/acpi/acpi_table.h324
-rw-r--r--include/acpi/acpigen.h12
-rw-r--r--include/bloblist.h1
-rw-r--r--include/configs/qemu-sbsa.h89
-rw-r--r--include/dm/acpi.h26
-rw-r--r--include/irq.h14
-rw-r--r--include/serial.h1
-rw-r--r--lib/Kconfig31
-rw-r--r--lib/acpi/acpi_table.c630
-rw-r--r--lib/acpi/acpigen.c11
-rw-r--r--test/dm/acpi.c43
-rw-r--r--test/dm/irq.c15
-rw-r--r--test/py/tests/test_event_dump.py1
113 files changed, 6519 insertions, 542 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 3ff1b44a6bc..4ecf76eaa0b 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -255,6 +255,11 @@ stages:
wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.3.1/opensbi-1.3.1-rv-bin.tar.xz | tar -C /tmp -xJ;
export OPENSBI=/tmp/opensbi-1.3.1-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
fi
+ if [[ "\${TEST_PY_BD}" == "qemu-arm-sbsa" ]]; then
+ wget -O /tmp/bl1.bin https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/latest/tf-a/bl1.bin;
+ wget -O /tmp/fip.bin https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/latest/tf-a/fip.bin;
+ export BINMAN_INDIRS=/tmp
+ fi
# the below corresponds to .gitlab-ci.yml "script"
cd \${WORK_DIR}
export UBOOT_TRAVIS_BUILD_DIR=/tmp/\${TEST_PY_BD}
@@ -426,6 +431,9 @@ stages:
qemu_arm64_lwip:
TEST_PY_BD: "qemu_arm64_lwip"
TEST_PY_TEST_SPEC: "test_net_dhcp or test_net_ping or test_net_tftpboot"
+ qemu_arm_sbsa_ref:
+ TEST_PY_BD: "qemu-arm-sbsa"
+ TEST_PY_TEST_SPEC: "not sleep"
qemu_m68k:
TEST_PY_BD: "M5208EVBE"
TEST_PY_ID: "--id qemu"
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d89657e28b3..0aeda53bc2d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -42,6 +42,11 @@ stages:
wget -O - https://github.com/riscv-software-src/opensbi/releases/download/v1.3.1/opensbi-1.3.1-rv-bin.tar.xz | tar -C /tmp -xJ;
export OPENSBI=/tmp/opensbi-1.3.1-rv-bin/share/opensbi/lp64/generic/firmware/fw_dynamic.bin;
fi
+ - if [[ "${TEST_PY_BD}" == "qemu-arm-sbsa" ]]; then
+ wget -O /tmp/bl1.bin https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/latest/tf-a/bl1.bin;
+ wget -O /tmp/fip.bin https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/latest/tf-a/fip.bin;
+ export BINMAN_INDIRS=/tmp;
+ fi
after_script:
- cp -v /tmp/${TEST_PY_BD}/*.{html,css,xml} .
@@ -357,6 +362,12 @@ qemu_arm64_lwip test.py:
TEST_PY_TEST_SPEC: "test_net_dhcp or test_net_ping or test_net_tftpboot"
<<: *buildman_and_testpy_dfn
+qemu_arm_sbsa test.py:
+ variables:
+ TEST_PY_BD: "qemu-arm-sbsa"
+ TEST_PY_TEST_SPEC: "not sleep"
+ <<: *buildman_and_testpy_dfn
+
qemu_m68k test.py:
variables:
TEST_PY_BD: "M5208EVBE"
diff --git a/MAINTAINERS b/MAINTAINERS
index 8e375e75e53..38c714cf46a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -355,7 +355,7 @@ S: Maintained
T: git https://source.denx.de/u-boot/custodians/u-boot-marvell.git
F: arch/arm/mach-kirkwood/
F: arch/arm/mach-mvebu/
-F: drivers/ata/ahci_mvebu.c
+F: drivers/ata/ahci_generic.c
F: drivers/clk/mvebu/
F: drivers/ddr/marvell/
F: drivers/gpio/mvebu_gpio.c
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
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9bf44ae3b0b..3017b33d67b 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -527,6 +527,9 @@
};
f-test {
+ #interrupt-cells = <2>;
+ interrupt-parent = <&irq>;
+ interrupts = <4 0>;
compatible = "denx,u-boot-fdt-test";
};
diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile
index d7d15a50bb6..5d7beb250cd 100644
--- a/arch/sandbox/lib/Makefile
+++ b/arch/sandbox/lib/Makefile
@@ -5,7 +5,8 @@
# (C) Copyright 2002-2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-obj-y += fdt_fixup.o interrupts.o
-obj-$(CONFIG_PCI) += pci_io.o
-obj-$(CONFIG_CMD_BOOTM) += bootm.o
-obj-$(CONFIG_CMD_BOOTZ) += bootm.o
+obj-y += fdt_fixup.o interrupts.o
+obj-$(CONFIG_PCI) += pci_io.o
+obj-$(CONFIG_CMD_BOOTM) += bootm.o
+obj-$(CONFIG_CMD_BOOTZ) += bootm.o
+obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_table.o
diff --git a/arch/sandbox/lib/acpi_table.c b/arch/sandbox/lib/acpi_table.c
new file mode 100644
index 00000000000..90bb96d1e35
--- /dev/null
+++ b/arch/sandbox/lib/acpi_table.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <acpi/acpi_table.h>
+
+void acpi_fill_fadt(struct acpi_fadt *fadt)
+{
+}
+
+void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
+{
+ return ctx->current;
+}
diff --git a/arch/x86/cpu/apollolake/acpi.c b/arch/x86/cpu/apollolake/acpi.c
index 76230aea837..93040e7bb37 100644
--- a/arch/x86/cpu/apollolake/acpi.c
+++ b/arch/x86/cpu/apollolake/acpi.c
@@ -128,8 +128,10 @@ int arch_madt_sci_irq_polarity(int sci)
return MP_IRQ_POLARITY_LOW;
}
-void fill_fadt(struct acpi_fadt *fadt)
+void acpi_fill_fadt(struct acpi_fadt *fadt)
{
+ intel_acpi_fill_fadt(fadt);
+
fadt->pm_tmr_blk = IOMAP_ACPI_BASE + PM1_TMR;
fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
@@ -143,23 +145,9 @@ void fill_fadt(struct acpi_fadt *fadt)
fadt->x_pm_tmr_blk.space_id = 1;
fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
fadt->x_pm_tmr_blk.addrl = IOMAP_ACPI_BASE + PM1_TMR;
-}
-
-static int apl_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
-{
- struct acpi_table_header *header;
- struct acpi_fadt *fadt;
-
- fadt = ctx->current;
- acpi_fadt_common(fadt, ctx->facs, ctx->dsdt);
- intel_acpi_fill_fadt(fadt);
- fill_fadt(fadt);
- header = &fadt->header;
- header->checksum = table_compute_checksum(fadt, header->length);
- return acpi_add_fadt(ctx, fadt);
+ fadt->preferred_pm_profile = ACPI_PM_MOBILE;
}
-ACPI_WRITER(5fadt, "FADT", apl_write_fadt, 0);
int apl_acpi_fill_dmar(struct acpi_ctx *ctx)
{
diff --git a/arch/x86/cpu/baytrail/acpi.c b/arch/x86/cpu/baytrail/acpi.c
index 7821964f1fc..7e1c2de3d39 100644
--- a/arch/x86/cpu/baytrail/acpi.c
+++ b/arch/x86/cpu/baytrail/acpi.c
@@ -15,20 +15,13 @@
#include <asm/arch/iomap.h>
#include <dm/uclass-internal.h>
-static int baytrail_write_fadt(struct acpi_ctx *ctx,
- const struct acpi_writer *entry)
+void acpi_fill_fadt(struct acpi_fadt *fadt)
{
struct acpi_table_header *header;
- struct acpi_fadt *fadt;
- fadt = ctx->current;
header = &fadt->header;
u16 pmbase = ACPI_BASE_ADDRESS;
- memset(fadt, '\0', sizeof(struct acpi_fadt));
-
- acpi_fill_header(header, "FACP");
- header->length = sizeof(struct acpi_fadt);
header->revision = 4;
fadt->preferred_pm_profile = ACPI_PM_MOBILE;
@@ -77,9 +70,6 @@ static int baytrail_write_fadt(struct acpi_ctx *ctx,
fadt->reset_reg.addrh = 0;
fadt->reset_value = SYS_RST | RST_CPU | FULL_RST;
- fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
- fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
-
fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
fadt->x_pm1a_evt_blk.bit_offset = 0;
@@ -135,12 +125,7 @@ static int baytrail_write_fadt(struct acpi_ctx *ctx,
fadt->x_gpe1_blk.access_size = 0;
fadt->x_gpe1_blk.addrl = 0x0;
fadt->x_gpe1_blk.addrh = 0x0;
-
- header->checksum = table_compute_checksum(fadt, header->length);
-
- return acpi_add_fadt(ctx, fadt);
}
-ACPI_WRITER(5fadt, "FADT", baytrail_write_fadt, 0);
int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
{
diff --git a/arch/x86/cpu/intel_common/acpi.c b/arch/x86/cpu/intel_common/acpi.c
index 29676b4abfa..982149b394e 100644
--- a/arch/x86/cpu/intel_common/acpi.c
+++ b/arch/x86/cpu/intel_common/acpi.c
@@ -19,6 +19,7 @@
#include <asm/global_data.h>
#include <asm/intel_acpi.h>
#include <asm/ioapic.h>
+#include <asm/lapic.h>
#include <asm/mpspec.h>
#include <asm/smm.h>
#include <asm/turbo.h>
@@ -80,33 +81,40 @@ static int acpi_sci_irq(void)
return sci_irq;
}
-static unsigned long acpi_madt_irq_overrides(unsigned long current)
+static void *acpi_madt_irq_overrides(void *current)
{
int sci = acpi_sci_irq();
u16 flags = MP_IRQ_TRIGGER_LEVEL;
- if (sci < 0)
- return log_msg_ret("sci irq", sci);
+ if (sci < 0) {
+ log_err("sci irq %d", sci);
+ return current;
+ }
/* INT_SRC_OVR */
- current += acpi_create_madt_irqoverride((void *)current, 0, 0, 2, 0);
+ current += acpi_create_madt_irqoverride(current, 0, 0, 2, 0);
flags |= arch_madt_sci_irq_polarity(sci);
/* SCI */
current +=
- acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags);
+ acpi_create_madt_irqoverride(current, 0, sci, sci, flags);
return current;
}
-u32 acpi_fill_madt(u32 current)
+void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
{
+ void *current = ctx->current;
+
+ madt->lapic_addr = LAPIC_DEFAULT_BASE;
+ madt->flags = ACPI_MADT_PCAT_COMPAT;
+
/* Local APICs */
current += acpi_create_madt_lapics(current);
/* IOAPIC */
- current += acpi_create_madt_ioapic((void *)current, 2, IO_APIC_ADDR, 0);
+ current += acpi_create_madt_ioapic(current, 2, IO_APIC_ADDR, 0);
return acpi_madt_irq_overrides(current);
}
diff --git a/arch/x86/cpu/quark/acpi.c b/arch/x86/cpu/quark/acpi.c
index 80e94600fc5..0fe5f2bafb4 100644
--- a/arch/x86/cpu/quark/acpi.c
+++ b/arch/x86/cpu/quark/acpi.c
@@ -11,23 +11,14 @@
#include <asm/arch/iomap.h>
#include <linux/string.h>
-static int quark_write_fadt(struct acpi_ctx *ctx,
- const struct acpi_writer *entry)
+void acpi_fill_fadt(struct acpi_fadt *fadt)
{
u16 pmbase = ACPI_PM1_BASE_ADDRESS;
struct acpi_table_header *header;
- struct acpi_fadt *fadt;
- fadt = ctx->current;
header = &fadt->header;
-
- memset(fadt, '\0', sizeof(struct acpi_fadt));
-
- acpi_fill_header(header, "FACP");
- header->length = sizeof(struct acpi_fadt);
header->revision = 4;
- fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
fadt->sci_int = 9;
fadt->smi_cmd = 0;
fadt->acpi_enable = 0;
@@ -73,9 +64,6 @@ static int quark_write_fadt(struct acpi_ctx *ctx,
fadt->reset_reg.addrh = 0;
fadt->reset_value = SYS_RST | RST_CPU | FULL_RST;
- fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
- fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
-
fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
fadt->x_pm1a_evt_blk.bit_offset = 0;
@@ -131,12 +119,7 @@ static int quark_write_fadt(struct acpi_ctx *ctx,
fadt->x_gpe1_blk.access_size = 0;
fadt->x_gpe1_blk.addrl = 0x0;
fadt->x_gpe1_blk.addrh = 0x0;
-
- header->checksum = table_compute_checksum(fadt, header->length);
-
- return acpi_add_fadt(ctx, fadt);
}
-ACPI_WRITER(5fadt, "FADT", quark_write_fadt, 0);
int acpi_create_gnvs(struct acpi_global_nvs *gnvs)
{
diff --git a/arch/x86/cpu/tangier/acpi.c b/arch/x86/cpu/tangier/acpi.c
index d4d0ef6f855..8ea764f7cc1 100644
--- a/arch/x86/cpu/tangier/acpi.c
+++ b/arch/x86/cpu/tangier/acpi.c
@@ -10,27 +10,15 @@
#include <mapmem.h>
#include <acpi/acpi_table.h>
#include <asm/ioapic.h>
+#include <asm/lapic.h>
#include <asm/mpspec.h>
#include <asm/tables.h>
#include <asm/arch/global_nvs.h>
#include <asm/arch/iomap.h>
#include <dm/uclass-internal.h>
-static int tangier_write_fadt(struct acpi_ctx *ctx,
- const struct acpi_writer *entry)
+void acpi_fill_fadt(struct acpi_fadt *fadt)
{
- struct acpi_table_header *header;
- struct acpi_fadt *fadt;
-
- fadt = ctx->current;
- header = &fadt->header;
-
- memset(fadt, '\0', sizeof(struct acpi_fadt));
-
- acpi_fill_header(header, "FACP");
- header->length = sizeof(struct acpi_fadt);
- header->revision = 6;
-
fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
fadt->iapc_boot_arch = ACPI_FADT_VGA_NOT_PRESENT |
@@ -40,20 +28,15 @@ static int tangier_write_fadt(struct acpi_ctx *ctx,
ACPI_FADT_POWER_BUTTON | ACPI_FADT_SLEEP_BUTTON |
ACPI_FADT_SEALED_CASE | ACPI_FADT_HEADLESS |
ACPI_FADT_HW_REDUCED_ACPI;
-
- fadt->minor_revision = 2;
-
- fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
- fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
-
- header->checksum = table_compute_checksum(fadt, header->length);
-
- return acpi_add_fadt(ctx, fadt);
}
-ACPI_WRITER(5fadt, "FADT", tangier_write_fadt, 0);
-u32 acpi_fill_madt(u32 current)
+void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
{
+ void *current = ctx->current;
+
+ madt->lapic_addr = LAPIC_DEFAULT_BASE;
+ madt->flags = ACPI_MADT_PCAT_COMPAT;
+
current += acpi_create_madt_lapics(current);
current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h
index 57e41654ce3..ff60384e620 100644
--- a/arch/x86/include/asm/acpi_table.h
+++ b/arch/x86/include/asm/acpi_table.h
@@ -24,16 +24,13 @@ struct acpi_table_header;
/* These can be used by the target port */
-int acpi_create_madt_lapics(u32 current);
+int acpi_create_madt_lapics(void *current);
int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
u32 addr, u32 gsi_base);
int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
u8 bus, u8 source, u32 gsirq, u16 flags);
int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
u8 cpu, u16 flags, u8 lint);
-u32 acpi_fill_madt(u32 current);
-int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
- u16 seg_nr, u8 start, u8 end);
/**
* acpi_write_hpet() - Write out a HPET table
@@ -46,17 +43,6 @@ int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
int acpi_write_hpet(struct acpi_ctx *ctx);
/**
- * acpi_write_dbg2_pci_uart() - Write out a DBG2 table
- *
- * @ctx: Current ACPI context
- * @dev: Debug UART device to describe
- * @access_size: Access size for UART (e.g. ACPI_ACCESS_SIZE_DWORD_ACCESS)
- * Return: 0 if OK, -ve on error
- */
-int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
- uint access_size);
-
-/**
* acpi_create_gnvs() - Create a GNVS (Global Non Volatile Storage) table
*
* @gnvs: Table to fill in
@@ -180,18 +166,6 @@ int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
pci_dev_t bdf);
/**
- * acpi_fadt_common() - Handle common parts of filling out an FADT
- *
- * This sets up the Fixed ACPI Description Table
- *
- * @fadt: Pointer to place to put FADT
- * @facs: Pointer to the FACS
- * @dsdt: Pointer to the DSDT
- */
-void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
- void *dsdt);
-
-/**
* intel_acpi_fill_fadt() - Set up the contents of the FADT
*
* This sets up parts of the Fixed ACPI Description Table that are common to
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index e38ce19ff7c..3186e48d63b 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -40,7 +40,7 @@ static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
return lapic->length;
}
-int acpi_create_madt_lapics(u32 current)
+int acpi_create_madt_lapics(void *current)
{
struct udevice *dev;
int total_length = 0;
@@ -100,23 +100,28 @@ int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
return lapic_nmi->length;
}
-static int acpi_create_madt_irq_overrides(u32 current)
+static int acpi_create_madt_irq_overrides(void *current)
{
struct acpi_madt_irqoverride *irqovr;
u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
int length = 0;
- irqovr = (void *)current;
+ irqovr = current;
length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
- irqovr = (void *)(current + length);
+ irqovr = current + length;
length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
return length;
}
-__weak u32 acpi_fill_madt(u32 current)
+__weak void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx)
{
+ void *current = ctx->current;
+
+ madt->lapic_addr = LAPIC_DEFAULT_BASE;
+ madt->flags = ACPI_MADT_PCAT_COMPAT;
+
current += acpi_create_madt_lapics(current);
current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
@@ -127,39 +132,6 @@ __weak u32 acpi_fill_madt(u32 current)
return current;
}
-int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
-{
- struct acpi_table_header *header;
- struct acpi_madt *madt;
- u32 current;
-
- madt = ctx->current;
-
- memset(madt, '\0', sizeof(struct acpi_madt));
- header = &madt->header;
-
- /* Fill out header fields */
- acpi_fill_header(header, "APIC");
- header->length = sizeof(struct acpi_madt);
- header->revision = ACPI_MADT_REV_ACPI_3_0;
-
- madt->lapic_addr = LAPIC_DEFAULT_BASE;
- madt->flags = ACPI_MADT_PCAT_COMPAT;
-
- current = (u32)madt + sizeof(struct acpi_madt);
- current = acpi_fill_madt(current);
-
- /* (Re)calculate length and checksum */
- header->length = current - (u32)madt;
-
- header->checksum = table_compute_checksum((void *)madt, header->length);
- acpi_add_table(ctx, madt);
- acpi_inc(ctx, madt->header.length);
-
- return 0;
-}
-ACPI_WRITER(5x86, NULL, acpi_write_madt, 0);
-
/**
* acpi_create_tcpa() - Create a TCPA table
*
@@ -279,140 +251,6 @@ static int acpi_write_tpm2(struct acpi_ctx *ctx,
}
ACPI_WRITER(5tpm2, "TPM2", acpi_write_tpm2, 0);
-int acpi_write_spcr(struct acpi_ctx *ctx, const struct acpi_writer *entry)
-{
- struct serial_device_info serial_info = {0};
- ulong serial_address, serial_offset;
- struct acpi_table_header *header;
- struct acpi_spcr *spcr;
- struct udevice *dev;
- uint serial_config;
- uint serial_width;
- int access_size;
- int space_id;
- int ret = -ENODEV;
-
- spcr = ctx->current;
- header = &spcr->header;
-
- memset(spcr, '\0', sizeof(struct acpi_spcr));
-
- /* Fill out header fields */
- acpi_fill_header(header, "SPCR");
- header->length = sizeof(struct acpi_spcr);
- header->revision = 2;
-
- /* Read the device once, here. It is reused below */
- dev = gd->cur_serial_dev;
- if (dev)
- ret = serial_getinfo(dev, &serial_info);
- if (ret)
- serial_info.type = SERIAL_CHIP_UNKNOWN;
-
- /* Encode chip type */
- switch (serial_info.type) {
- case SERIAL_CHIP_16550_COMPATIBLE:
- spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
- break;
- case SERIAL_CHIP_UNKNOWN:
- default:
- spcr->interface_type = ACPI_DBG2_UNKNOWN;
- break;
- }
-
- /* Encode address space */
- switch (serial_info.addr_space) {
- case SERIAL_ADDRESS_SPACE_MEMORY:
- space_id = ACPI_ADDRESS_SPACE_MEMORY;
- break;
- case SERIAL_ADDRESS_SPACE_IO:
- default:
- space_id = ACPI_ADDRESS_SPACE_IO;
- break;
- }
-
- serial_width = serial_info.reg_width * 8;
- serial_offset = serial_info.reg_offset << serial_info.reg_shift;
- serial_address = serial_info.addr + serial_offset;
-
- /* Encode register access size */
- switch (serial_info.reg_shift) {
- case 0:
- access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
- break;
- case 1:
- access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
- break;
- case 2:
- access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
- break;
- case 3:
- access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
- break;
- default:
- access_size = ACPI_ACCESS_SIZE_UNDEFINED;
- break;
- }
-
- debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
-
- /* Fill GAS */
- spcr->serial_port.space_id = space_id;
- spcr->serial_port.bit_width = serial_width;
- spcr->serial_port.bit_offset = 0;
- spcr->serial_port.access_size = access_size;
- spcr->serial_port.addrl = lower_32_bits(serial_address);
- spcr->serial_port.addrh = upper_32_bits(serial_address);
-
- /* Encode baud rate */
- switch (serial_info.baudrate) {
- case 9600:
- spcr->baud_rate = 3;
- break;
- case 19200:
- spcr->baud_rate = 4;
- break;
- case 57600:
- spcr->baud_rate = 6;
- break;
- case 115200:
- spcr->baud_rate = 7;
- break;
- default:
- spcr->baud_rate = 0;
- break;
- }
-
- serial_config = SERIAL_DEFAULT_CONFIG;
- if (dev)
- ret = serial_getconfig(dev, &serial_config);
-
- spcr->parity = SERIAL_GET_PARITY(serial_config);
- spcr->stop_bits = SERIAL_GET_STOP(serial_config);
-
- /* No PCI devices for now */
- spcr->pci_device_id = 0xffff;
- spcr->pci_vendor_id = 0xffff;
-
- /*
- * SPCR has no clue if the UART base clock speed is different
- * to the default one. However, the SPCR 1.04 defines baud rate
- * 0 as a preconfigured state of UART and OS is supposed not
- * to touch the configuration of the serial device.
- */
- if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
- spcr->baud_rate = 0;
-
- /* Fix checksum */
- header->checksum = table_compute_checksum((void *)spcr, header->length);
-
- acpi_add_table(ctx, spcr);
- acpi_inc(ctx, spcr->header.length);
-
- return 0;
-}
-ACPI_WRITER(5spcr, "SPCR", acpi_write_spcr, 0);
-
int acpi_write_gnvs(struct acpi_ctx *ctx, const struct acpi_writer *entry)
{
ulong addr;
@@ -515,69 +353,6 @@ int acpi_write_hpet(struct acpi_ctx *ctx)
return 0;
}
-int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
- uint access_size)
-{
- struct acpi_dbg2_header *dbg2 = ctx->current;
- char path[ACPI_PATH_MAX];
- struct acpi_gen_regaddr address;
- phys_addr_t addr;
- int ret;
-
- if (!device_active(dev)) {
- log_info("Device not enabled\n");
- return -EACCES;
- }
- /*
- * PCI devices don't remember their resource allocation information in
- * U-Boot at present. We assume that MMIO is used for the UART and that
- * the address space is 32 bytes: ns16550 uses 8 registers of up to
- * 32-bits each. This is only for debugging so it is not a big deal.
- */
- addr = dm_pci_read_bar32(dev, 0);
- log_debug("UART addr %lx\n", (ulong)addr);
-
- memset(&address, '\0', sizeof(address));
- address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
- address.addrl = (uint32_t)addr;
- address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
- address.access_size = access_size;
-
- ret = acpi_device_path(dev, path, sizeof(path));
- if (ret)
- return log_msg_ret("path", ret);
- acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
- ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
-
- acpi_inc_align(ctx, dbg2->header.length);
- acpi_add_table(ctx, dbg2);
-
- return 0;
-}
-
-void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
- void *dsdt)
-{
- struct acpi_table_header *header = &fadt->header;
-
- memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
-
- acpi_fill_header(header, "FACP");
- header->length = sizeof(struct acpi_fadt);
- header->revision = 4;
- memcpy(header->oem_id, OEM_ID, 6);
- memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
- memcpy(header->creator_id, ASLC_ID, 4);
-
- fadt->x_firmware_ctrl = map_to_sysmem(facs);
- fadt->x_dsdt = map_to_sysmem(dsdt);
-
- fadt->preferred_pm_profile = ACPI_PM_MOBILE;
-
- /* Use ACPI 3.0 revision */
- fadt->header.revision = 4;
-}
-
void acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
u64 bar)
{
diff --git a/board/emulation/qemu-arm/MAINTAINERS b/board/emulation/qemu-arm/MAINTAINERS
index 5154262f29e..7bc0ee698c5 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 00000000000..72c76b351fa
--- /dev/null
+++ b/board/emulation/qemu-sbsa/Kconfig
@@ -0,0 +1,59 @@
+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 BLOBLIST
+ 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 00000000000..bacae320e79
--- /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 00000000000..ba85e08fc7d
--- /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 = &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 = 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 00000000000..f12cca04e2c
--- /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 00000000000..c997721af95
--- /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@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 00000000000..3943c924320
--- /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 00000000000..88fdb0ec1c5
--- /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 00000000000..391a70bdc40
--- /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 00000000000..9a2d091bea6
--- /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/board/raspberrypi/rpi/.gitignore b/board/raspberrypi/rpi/.gitignore
new file mode 100644
index 00000000000..39e46ba0ae7
--- /dev/null
+++ b/board/raspberrypi/rpi/.gitignore
@@ -0,0 +1,3 @@
+dsdt_generated.aml
+dsdt_generated.asl.tmp
+dsdt_generated.c
diff --git a/board/raspberrypi/rpi/Makefile b/board/raspberrypi/rpi/Makefile
index b1186cdf100..bb1b7cc630f 100644
--- a/board/raspberrypi/rpi/Makefile
+++ b/board/raspberrypi/rpi/Makefile
@@ -4,3 +4,5 @@
obj-y := rpi.o
obj-y += lowlevel_init.o
+
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt_generated.o
diff --git a/board/raspberrypi/rpi/acpitables.h b/board/raspberrypi/rpi/acpitables.h
new file mode 100644
index 00000000000..3ba8f19808c
--- /dev/null
+++ b/board/raspberrypi/rpi/acpitables.h
@@ -0,0 +1,90 @@
+/** @file
+ *
+ * RPi defines for constructing ACPI tables
+ *
+ * Copyright (c) 2020, Pete Batard <pete@akeo.ie>
+ * Copyright (c) 2019, ARM Ltd. All rights reserved.
+ * Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ **/
+
+#ifndef __RPI_ACPITABLES_H__
+#define __RPI_ACPITABLES_H__
+
+#include <acpi/acpi_table.h>
+
+// The ASL compiler can't perform arithmetic on MEMORY32FIXED ()
+// parameters so you can't pass a constant like BASE + OFFSET.
+// We therefore define a macro that can perform arithmetic base
+// address update with an offset.
+#define MEMORY32SETBASE(BufName, MemName, VarName, Offset) \
+ CreateDwordField (^BufName, ^MemName._BAS, VarName) \
+ Add (BCM2836_SOC_REGISTERS, Offset, VarName)
+
+//------------------------------------------------------------------------
+// Interrupts. These are specific to each platform
+//------------------------------------------------------------------------
+#if defined(CONFIG_TARGET_RPI_3)
+#define BCM2836_V3D_BUS_INTERRUPT 0x2A
+#define BCM2836_DMA_INTERRUPT 0x3B
+#define BCM2836_SPI1_INTERRUPT 0x3D
+#define BCM2836_SPI2_INTERRUPT 0x3D
+#define BCM2836_HVS_INTERRUPT 0x41
+#define BCM2836_HDMI0_INTERRUPT 0x48
+#define BCM2836_HDMI1_INTERRUPT 0x49
+#define BCM2836_PV2_INTERRUPT 0x4A
+#define BCM2836_PV0_INTERRUPT 0x4D
+#define BCM2836_PV1_INTERRUPT 0x4E
+#define BCM2836_MBOX_INTERRUPT 0x61
+#define BCM2836_VCHIQ_INTERRUPT 0x62
+#define BCM2386_GPIO_INTERRUPT0 0x51
+#define BCM2386_GPIO_INTERRUPT1 0x52
+#define BCM2386_GPIO_INTERRUPT2 0x53
+#define BCM2386_GPIO_INTERRUPT3 0x54
+#define BCM2836_I2C1_INTERRUPT 0x55
+#define BCM2836_I2C2_INTERRUPT 0x55
+#define BCM2836_SPI0_INTERRUPT 0x56
+#define BCM2836_USB_INTERRUPT 0x29
+#define BCM2836_SDHOST_INTERRUPT 0x58
+#define BCM2836_MMCHS1_INTERRUPT 0x5E
+#define BCM2836_MINI_UART_INTERRUPT 0x3D
+#define BCM2836_PL011_UART_INTERRUPT 0x59
+#elif defined(CONFIG_TARGET_RPI_4)
+#define BCM2836_V3D_BUS_INTERRUPT 0x2A
+#define BCM2836_DMA_INTERRUPT 0x3B
+#define BCM2836_SPI1_INTERRUPT 0x7D
+#define BCM2836_SPI2_INTERRUPT 0x7D
+#define BCM2836_HVS_INTERRUPT 0x41
+#define BCM2836_HDMI0_INTERRUPT 0x48
+#define BCM2836_HDMI1_INTERRUPT 0x49
+#define BCM2836_PV2_INTERRUPT 0x4A
+#define BCM2836_PV0_INTERRUPT 0x4D
+#define BCM2836_PV1_INTERRUPT 0x4E
+#define BCM2836_MBOX_INTERRUPT 0x41
+#define BCM2836_VCHIQ_INTERRUPT 0x42
+#define BCM2386_GPIO_INTERRUPT0 0x91
+#define BCM2386_GPIO_INTERRUPT1 0x92
+#define BCM2386_GPIO_INTERRUPT2 0x93
+#define BCM2386_GPIO_INTERRUPT3 0x94
+#define BCM2836_I2C1_INTERRUPT 0x95
+#define BCM2836_I2C2_INTERRUPT 0x95
+#define BCM2836_SPI0_INTERRUPT 0x96
+#define BCM2836_USB_INTERRUPT 0x69
+#define BCM2836_SDHOST_INTERRUPT 0x98
+#define BCM2836_MMCHS1_INTERRUPT 0x9E
+#define BCM2836_MINI_UART_INTERRUPT 0x7D
+#define BCM2836_PL011_UART_INTERRUPT 0x99
+#define GENET_INTERRUPT0 0xBD
+#define GENET_INTERRUPT1 0xBE
+#define GENET_BASE_ADDRESS 0xFD580000
+#define GENET_LENGTH 0x10000
+#define THERM_SENSOR_BASE_ADDRESS 0xFD5d2200
+#define THERM_SENSOR_LENGTH 0x8
+#else
+#error "Unsupported rpi module for ACPI tables"
+#endif
+
+#endif // __ACPITABLES_H__
diff --git a/board/raspberrypi/rpi/dsdt.asl b/board/raspberrypi/rpi/dsdt.asl
new file mode 100644
index 00000000000..c89b08d5ea1
--- /dev/null
+++ b/board/raspberrypi/rpi/dsdt.asl
@@ -0,0 +1,254 @@
+/** @file
+ *
+ * Differentiated System Definition Table (DSDT)
+ *
+ * Copyright (c) 2020, Pete Batard <pete@akeo.ie>
+ * Copyright (c) 2018-2020, Andrey Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ **/
+
+#include <asm/arch/acpi/bcm2711.h>
+#include <asm/arch/acpi/bcm2836.h>
+#include <asm/arch/acpi/bcm2836_gpio.h>
+#include <asm/arch/acpi/bcm2836_gpu.h>
+#include <asm/arch/acpi/bcm2836_pwm.h>
+#include <asm/arch/acpi/bcm2836_sdio.h>
+#include <asm/arch/acpi/bcm2836_sdhost.h>
+
+#include "acpitables.h"
+
+#define BCM_ALT0 0x4
+#define BCM_ALT1 0x5
+#define BCM_ALT2 0x6
+#define BCM_ALT3 0x7
+#define BCM_ALT4 0x3
+#define BCM_ALT5 0x2
+
+//
+// The ASL compiler does not support argument arithmetic in functions
+// like QWordMemory (). So we need to instantiate dummy qword regions
+// that we can then update the Min, Max and Length attributes of.
+// The three macros below help accomplish this.
+//
+// QWORDMEMORYSET specifies a CPU memory range (whose base address is
+// BCM2836_SOC_REGISTERS + Offset), and QWORDBUSMEMORYSET specifies
+// a VPU memory range (whose base address is provided directly).
+//
+#define QWORDMEMORYBUF(Index) \
+ QWordMemory (ResourceProducer,, \
+ MinFixed, MaxFixed, NonCacheable, ReadWrite, \
+ 0x0, 0x0, 0x0, 0x0, 0x1,,, RB ## Index)
+
+#define QWORDMEMORYSET(Index, Offset, Length) \
+ CreateQwordField (RBUF, RB ## Index._MIN, MI ## Index) \
+ CreateQwordField (RBUF, RB ## Index._MAX, MA ## Index) \
+ CreateQwordField (RBUF, RB ## Index._LEN, LE ## Index) \
+ Store (Length, LE ## Index) \
+ Add (BCM2836_SOC_REGISTERS, Offset, MI ## Index) \
+ Add (MI ## Index, LE ## Index - 1, MA ## Index)
+
+#define QWORDBUSMEMORYSET(Index, Base, Length) \
+ CreateQwordField (RBUF, RB ## Index._MIN, MI ## Index) \
+ CreateQwordField (RBUF, RB ## Index._MAX, MA ## Index) \
+ CreateQwordField (RBUF, RB ## Index._LEN, LE ## Index) \
+ Store (Base, MI ## Index) \
+ Store (Length, LE ## Index) \
+ Add (MI ## Index, LE ## Index - 1, MA ## Index)
+
+DefinitionBlock ("Dsdt.aml", "DSDT", 2, "RPIFDN", "RPI", 2)
+{
+ External (\_PR.CP00, DeviceObj)
+ External (\_PR.CP01, DeviceObj)
+ External (\_PR.CP02, DeviceObj)
+ External (\_PR.CP03, DeviceObj)
+ Scope (\_SB_)
+ {
+ include ("pep.asl")
+
+ //
+ // GPU device container describes the DMA translation required
+ // when a device behind the GPU wants to access Arm memory.
+ // Only the first GB can be addressed.
+ //
+ Device (GDV0)
+ {
+ Name (_HID, "ACPI0004")
+ Name (_UID, 0x1)
+ Name (_CCA, 0x0)
+
+ Method (_CRS, 0, Serialized) {
+ //
+ // Container devices with _DMA must have _CRS, meaning GDV0
+ // to provide all resources that GpuDevs.asl consume (except
+ // interrupts).
+ //
+ Name (RBUF, ResourceTemplate () {
+ QWORDMEMORYBUF(01)
+ QWORDMEMORYBUF(02)
+ QWORDMEMORYBUF(03)
+ // QWORDMEMORYBUF(04)
+ // QWORDMEMORYBUF(05)
+ QWORDMEMORYBUF(06)
+ QWORDMEMORYBUF(07)
+ QWORDMEMORYBUF(08)
+ QWORDMEMORYBUF(09)
+ QWORDMEMORYBUF(10)
+ QWORDMEMORYBUF(11)
+ QWORDMEMORYBUF(12)
+ QWORDMEMORYBUF(13)
+ QWORDMEMORYBUF(14)
+ QWORDMEMORYBUF(15)
+ // QWORDMEMORYBUF(16)
+ QWORDMEMORYBUF(17)
+ QWORDMEMORYBUF(18)
+ QWORDMEMORYBUF(19)
+ QWORDMEMORYBUF(20)
+ QWORDMEMORYBUF(21)
+ QWORDMEMORYBUF(22)
+ QWORDMEMORYBUF(23)
+ QWORDMEMORYBUF(24)
+ QWORDMEMORYBUF(25)
+ })
+
+ // USB
+ QWORDMEMORYSET(01, BCM2836_USB_OFFSET, BCM2836_USB_LENGTH)
+
+ // GPU
+ QWORDMEMORYSET(02, BCM2836_V3D_BUS_OFFSET, BCM2836_V3D_BUS_LENGTH)
+ QWORDMEMORYSET(03, BCM2836_HVS_OFFSET, BCM2836_HVS_LENGTH)
+ // QWORDMEMORYSET(04, BCM2836_PV0_OFFSET, BCM2836_PV0_LENGTH)
+ // QWORDMEMORYSET(05, BCM2836_PV1_OFFSET, BCM2836_PV1_LENGTH)
+ QWORDMEMORYSET(06, BCM2836_PV2_OFFSET, BCM2836_PV2_LENGTH)
+ QWORDMEMORYSET(07, BCM2836_HDMI0_OFFSET, BCM2836_HDMI0_LENGTH)
+ QWORDMEMORYSET(08, BCM2836_HDMI1_OFFSET, BCM2836_HDMI1_LENGTH)
+
+ // Mailbox
+ QWORDMEMORYSET(09, BCM2836_MBOX_OFFSET, BCM2836_MBOX_LENGTH)
+
+ // VCHIQ
+ QWORDMEMORYSET(10, BCM2836_VCHIQ_OFFSET, BCM2836_VCHIQ_LENGTH)
+
+ // GPIO
+ QWORDMEMORYSET(11, GPIO_OFFSET, GPIO_LENGTH)
+
+ // I2C
+ QWORDMEMORYSET(12, BCM2836_I2C1_OFFSET, BCM2836_I2C1_LENGTH)
+ QWORDMEMORYSET(13, BCM2836_I2C2_OFFSET, BCM2836_I2C2_LENGTH)
+
+ // SPI
+ QWORDMEMORYSET(14, BCM2836_SPI0_OFFSET, BCM2836_SPI0_LENGTH)
+ QWORDMEMORYSET(15, BCM2836_SPI1_OFFSET, BCM2836_SPI1_LENGTH)
+ // QWORDMEMORYSET(16, BCM2836_SPI2_OFFSET, BCM2836_SPI2_LENGTH)
+
+ // PWM
+ QWORDMEMORYSET(17, BCM2836_PWM_DMA_OFFSET, BCM2836_PWM_DMA_LENGTH)
+ QWORDMEMORYSET(18, BCM2836_PWM_CTRL_OFFSET, BCM2836_PWM_CTRL_LENGTH)
+ QWORDBUSMEMORYSET(19, BCM2836_PWM_BUS_BASE_ADDRESS, BCM2836_PWM_BUS_LENGTH)
+ QWORDBUSMEMORYSET(20, BCM2836_PWM_CTRL_UNCACHED_BASE_ADDRESS, BCM2836_PWM_CTRL_UNCACHED_LENGTH)
+ QWORDMEMORYSET(21, BCM2836_PWM_CLK_OFFSET, BCM2836_PWM_CLK_LENGTH)
+
+ // UART
+ QWORDMEMORYSET(22, BCM2836_PL011_UART_OFFSET, BCM2836_PL011_UART_LENGTH)
+ QWORDMEMORYSET(23, BCM2836_MINI_UART_OFFSET, BCM2836_MINI_UART_LENGTH)
+
+ // SDC
+ QWORDMEMORYSET(24, MMCHS1_OFFSET, MMCHS1_LENGTH)
+ QWORDMEMORYSET(25, SDHOST_OFFSET, SDHOST_LENGTH)
+
+ Return (RBUF)
+ }
+
+ Name (_DMA, ResourceTemplate() {
+ //
+ // Only the first GB is available.
+ // Bus 0xC0000000 -> CPU 0x00000000.
+ //
+ QWordMemory (ResourceProducer,
+ ,
+ MinFixed,
+ MaxFixed,
+ NonCacheable,
+ ReadWrite,
+ 0x0,
+ 0x00000000C0000000, // MIN
+ 0x00000000FFFFFFFF, // MAX
+ 0xFFFFFFFF40000000, // TRA
+ 0x0000000040000000, // LEN
+ ,
+ ,
+ )
+ })
+#include "gpudevs.asl"
+ }
+
+#if defined(CONFIG_TARGET_RPI_4)
+ Device (ETH0)
+ {
+ Name (_HID, "BCM6E4E")
+ Name (_CID, "BCM6E4E")
+ Name (_UID, 0x0)
+ Name (_CCA, 0x0)
+
+ Method (_CRS, 0x0, Serialized)
+ {
+ Return (ResourceTemplate ()
+ {
+ // No need for MEMORY32SETBASE on Genet as we have a straight base address constant
+ MEMORY32FIXED (ReadWrite, GENET_BASE_ADDRESS, GENET_LENGTH, )
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { GENET_INTERRUPT0, GENET_INTERRUPT1 }
+ })
+ }
+ Name (_DSD, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package () { "brcm,max-dma-burst-size", 0x08 },
+ Package () { "phy-mode", "rgmii-rxid" },
+ }
+ })
+ }
+
+ // Define a simple thermal zone. The idea here is we compute the SOC temp
+ // via a register we can read, and give it to the OS. This enables basic
+ // reports from the "sensors" utility, and the OS can then poll and take
+ // actions if that temp exceeds any of the given thresholds.
+ Device (EC00)
+ {
+ Name (_HID, EISAID ("PNP0C06"))
+ Name (_CCA, 0x0)
+
+ // all temps in are tenths of K (aka 2732 is the min temps in Linux (aka 0C))
+ ThermalZone (TZ00) {
+ OperationRegion (TEMS, SystemMemory, THERM_SENSOR_BASE_ADDRESS, THERM_SENSOR_LENGTH)
+ Field (TEMS, DWordAcc, NoLock, Preserve) {
+ TMPS, 32
+ }
+ Method (_TMP, 0, Serialized) {
+ return (((410040 - ((TMPS & 0x3ff) * 487)) / 100) + 2732);
+ }
+
+ Method (_SCP, 3) { } // receive cooling policy from OS
+
+ Method (_CRT) { Return (3632) } // (90C) Critical temp point (immediate power-off)
+ Method (_HOT) { Return (3582) } // (85C) HOT state where OS should hibernate
+ Method (_PSV) { Return (3532) } // (80C) Passive cooling (CPU throttling) trip point
+
+ // SSDT inserts _AC0/_AL0 @60C here, if a FAN is configured
+
+ Name (_TZP, 10) //The OSPM must poll this device every 1 seconds
+ Name (_PSL, Package () { \_PR.CP00, \_PR.CP01, \_PR.CP02, \_PR.CP03 })
+ }
+ }
+#endif
+
+
+#include "uart.asl"
+#include "rhpx.asl"
+#include "sdhc.asl"
+#include "emmc.asl"
+#include "pci.asl"
+ }
+}
diff --git a/board/raspberrypi/rpi/emmc.asl b/board/raspberrypi/rpi/emmc.asl
new file mode 100644
index 00000000000..63f01362c91
--- /dev/null
+++ b/board/raspberrypi/rpi/emmc.asl
@@ -0,0 +1,136 @@
+/** @file
+ *
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ **/
+
+#include <asm/arch/acpi/bcm2836_sdhost.h>
+#include <asm/arch/acpi/bcm2836_sdio.h>
+#include <asm/arch/acpi/bcm2711.h>
+
+Device (GDV1) {
+ Name (_HID, "ACPI0004")
+ Name (_UID, 0x2)
+ Name (_CCA, 0x0)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, MMCHS2_LENGTH, RMEM)
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, MMCHS2_OFFSET)
+ Return (^RBUF)
+ }
+
+ // Translated DMA region for BCM2711 silicon revisions older than C0
+ Name (DMTR, ResourceTemplate() {
+ QWordMemory (ResourceProducer,
+ ,
+ MinFixed,
+ MaxFixed,
+ NonCacheable,
+ ReadWrite,
+ 0x0,
+ 0x00000000C0000000, // MIN
+ 0x00000000FFFFFFFF, // MAX
+ 0xFFFFFFFF40000000, // TRA
+ 0x0000000040000000, // LEN
+ ,
+ ,
+ )
+ })
+
+ // Non translated DMA region for BCM2711 revisions C0 and newer
+ Name (DMNT, ResourceTemplate() {
+ QWordMemory (ResourceProducer,
+ ,
+ MinFixed,
+ MaxFixed,
+ NonCacheable,
+ ReadWrite,
+ 0x0,
+ 0x0000000000000000, // MIN
+ 0x000000FFFFFFFFFF, // MAX
+ 0x0000000000000000, // TRA
+ 0x0000010000000000, // LEN
+ ,
+ ,
+ )
+ })
+
+ // emmc2 Host Controller. (brcm,bcm2711-emmc2)
+ Device (SDC3)
+ {
+ Name (_HID, "BRCME88C")
+ Name (_UID, 0x1)
+ Name (_CCA, 0x0)
+ Name (_S1D, 0x1)
+ Name (_S2D, 0x1)
+ Name (_S3D, 0x1)
+ Name (_S4D, 0x1)
+ Name (SDMA, 0x2)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, MMCHS2_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_MMCHS1_INTERRUPT }
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, MMCHS2_OFFSET)
+ Return (^RBUF)
+ }
+
+ // Unfortunately this controller doesn't honor the
+ // standard SDHCI voltage control registers
+ // (or at least Linux's standard code can't
+ // lower the voltage) So, UHS mode is disabled with caps
+ Name (DSD1, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package () { "sdhci-caps-mask", 0x0000000500080000 },
+ }
+ })
+ // Along with disabling UHS, here both SDMA and ADMA2
+ // are also disabled until the linux _DMA() mask/translate
+ // works properly.
+ Name (DSD2, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package () { "sdhci-caps-mask", 0x0000000504480000 },
+ }
+ })
+ Method (_DSD, 0x0, Serialized)
+ {
+ // Select one of the sdhci-caps-mask definitions
+ // depending on whether we also want to disable DMA
+ if (SDMA == 0)
+ {
+ return (^DSD2)
+ }
+ else
+ {
+ return (^DSD1)
+ }
+ }
+
+ //
+ // A child device that represents the
+ // sd card, which is marked as non-removable.
+ //
+ Device (SDMM)
+ {
+ Method (_ADR)
+ {
+ Return (0)
+ }
+ Method (_RMV) // Is removable
+ {
+ Return (0) // 0 - fixed
+ }
+ }
+ } //SDC3
+} //GDV1
diff --git a/board/raspberrypi/rpi/gpudevs.asl b/board/raspberrypi/rpi/gpudevs.asl
new file mode 100644
index 00000000000..a3077a9c3bd
--- /dev/null
+++ b/board/raspberrypi/rpi/gpudevs.asl
@@ -0,0 +1,372 @@
+/** @file
+ *
+ * [DSDT] Devices behind the GPU.
+ *
+ * Copyright (c) 2018-2020, Andrey Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ **/
+
+// DWC OTG Controller
+Device (USB0)
+{
+ Name (_HID, "BCM2848")
+#if defined(CONFIG_TARGET_RPI_3)
+ Name (_CID, "DWC_OTG")
+#elif defined(CONFIG_TARGET_RPI_4)
+ Name (_CID, "BCM2848")
+#endif
+ Name (_UID, 0x0)
+ Name (_CCA, 0x0)
+ Method (_STA)
+ {
+ Return (0xf)
+ }
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_USB_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_USB_INTERRUPT }
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_USB_OFFSET)
+ Return (^RBUF)
+ }
+}
+
+// Video Core 4 GPU
+Device (GPU0)
+{
+ Name (_HID, "BCM2850")
+ Name (_CID, "BCM2850")
+ Name (_UID, 0x0)
+ Name (_CCA, 0x0)
+ Method (_STA)
+ {
+ Return (0xf)
+ }
+ Name (RBUF, ResourceTemplate ()
+ {
+ // Memory and interrupt for the GPU
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_V3D_BUS_LENGTH, RM01)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_V3D_BUS_INTERRUPT }
+
+ // HVS - Hardware Video Scalar
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_HVS_LENGTH, RM02)
+ // The HVS interrupt is reserved by the VPU
+ // Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_HVS_INTERRUPT }
+
+ // PixelValve0 - DSI0 or DPI
+ // MEMORY32FIXED (ReadWrite, BCM2836_PV0_BASE_ADDRESS, BCM2836_PV0_LENGTH, RM03)
+ // Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_PV0_INTERRUPT }
+
+ // PixelValve1 - DS1 or SMI
+ // MEMORY32FIXED (ReadWrite, BCM2836_PV1_BASE_ADDRESS, BCM2836_PV1_LENGTH, RM04)
+ // Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_PV1_INTERRUPT }
+
+ // PixelValve2 - HDMI output - connected to HVS display FIFO 1
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_PV2_LENGTH, RM05)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_PV2_INTERRUPT }
+
+ // HDMI registers
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_HDMI0_LENGTH, RM06)
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_HDMI1_LENGTH, RM07)
+ // hdmi_int[0]
+ // Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_HDMI0_INTERRUPT }
+ // hdmi_int[1]
+ // Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_HDMI1_INTERRUPT }
+
+ // HDMI DDC connection
+ I2CSerialBus (0x50,, 100000,, "\\_SB.GDV0.I2C2",,,,) // EDID
+ I2CSerialBus (0x30,, 100000,, "\\_SB.GDV0.I2C2",,,,) // E-DDC Segment Pointer
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RM01, RB01, BCM2836_V3D_BUS_OFFSET)
+ MEMORY32SETBASE (RBUF, RM02, RB02, BCM2836_HVS_OFFSET)
+ MEMORY32SETBASE (RBUF, RM05, RB05, BCM2836_PV2_OFFSET)
+ MEMORY32SETBASE (RBUF, RM06, RB06, BCM2836_HDMI0_OFFSET)
+ MEMORY32SETBASE (RBUF, RM07, RB07, BCM2836_HDMI1_OFFSET)
+ Return (^RBUF)
+ }
+
+ // GPU Power Management Component Data
+ // Reference : https://github.com/Microsoft/graphics-driver-samples/wiki/Install-Driver-in-a-Windows-VM
+ Method (PMCD, 0, Serialized)
+ {
+ Name (RBUF, Package ()
+ {
+ 1, // Version
+ 1, // Number of graphics power components
+ Package () // Power components package
+ {
+ Package () // GPU component package
+ {
+ 0, // Component Index
+ 0, // DXGK_POWER_COMPONENT_MAPPING.ComponentType (0 = DXGK_POWER_COMPONENT_ENGINE)
+ 0, // DXGK_POWER_COMPONENT_MAPPING.NodeIndex
+
+ Buffer () // DXGK_POWER_RUNTIME_COMPONENT.ComponentGuid
+ { // 9B2D1E26-1575-4747-8FC0-B9EB4BAA2D2B
+ 0x26, 0x1E, 0x2D, 0x9B, 0x75, 0x15, 0x47, 0x47,
+ 0x8f, 0xc0, 0xb9, 0xeb, 0x4b, 0xaa, 0x2d, 0x2b
+ },
+
+ "VC4_Engine_00",// DXGK_POWER_RUNTIME_COMPONENT.ComponentName
+ 2, // DXGK_POWER_RUNTIME_COMPONENT.StateCount
+
+ Package () // DXGK_POWER_RUNTIME_COMPONENT.States[] package
+ {
+ Package () // F0
+ {
+ 0, // DXGK_POWER_RUNTIME_STATE.TransitionLatency
+ 0, // DXGK_POWER_RUNTIME_STATE.ResidencyRequirement
+ 1210000, // DXGK_POWER_RUNTIME_STATE.NominalPower (microwatt)
+ },
+
+ Package () // F1 - Placeholder
+ {
+ 10000, // DXGK_POWER_RUNTIME_STATE.TransitionLatency
+ 10000, // DXGK_POWER_RUNTIME_STATE.ResidencyRequirement
+ 4, // DXGK_POWER_RUNTIME_STATE.NominalPower
+ },
+ }
+ }
+ }
+ })
+ Return (RBUF)
+ }
+}
+
+// PiQ Mailbox Driver
+Device (RPIQ)
+{
+ Name (_HID, "BCM2849")
+ Name (_CID, "BCM2849")
+ Name (_UID, 0)
+ Name (_CCA, 0x0)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_MBOX_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_MBOX_INTERRUPT }
+ })
+
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_MBOX_OFFSET)
+ Return (^RBUF)
+ }
+}
+
+// VCHIQ Driver
+Device (VCIQ)
+{
+ Name (_HID, "BCM2835")
+ Name (_CID, "BCM2835")
+ Name (_UID, 0)
+ Name (_CCA, 0x0)
+ Name (_DEP, Package() { \_SB.GDV0.RPIQ })
+ Method (_STA)
+ {
+ Return (0xf)
+ }
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_VCHIQ_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_VCHIQ_INTERRUPT }
+ })
+
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_VCHIQ_OFFSET)
+ Return (^RBUF)
+ }
+}
+
+// VC Shared Memory Driver
+Device (VCSM)
+{
+ Name (_HID, "BCM2856")
+ Name (_CID, "BCM2856")
+ Name (_UID, 0)
+ Name (_CCA, 0x0)
+ Name (_DEP, Package() { \_SB.GDV0.VCIQ })
+ Method (_STA)
+ {
+ Return (0xf)
+ }
+}
+
+// Description: GPIO
+Device (GPI0)
+{
+ Name (_HID, "BCM2845")
+ Name (_CID, "BCM2845")
+ Name (_UID, 0x0)
+ Name (_CCA, 0x0)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, GPIO_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Shared)
+ {
+ BCM2386_GPIO_INTERRUPT0, BCM2386_GPIO_INTERRUPT1,
+ BCM2386_GPIO_INTERRUPT2, BCM2386_GPIO_INTERRUPT3
+ }
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, GPIO_OFFSET)
+ Return (^RBUF)
+ }
+}
+
+// Description: I2C
+Device (I2C1)
+{
+ Name (_HID, "BCM2841")
+ Name (_CID, "BCM2841")
+ Name (_UID, 0x1)
+ Name (_CCA, 0x0)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_I2C1_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_I2C1_INTERRUPT }
+ PinFunction (Exclusive, PullUp, BCM_ALT0, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 2, 3 }
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_I2C1_OFFSET)
+ Return (^RBUF)
+ }
+}
+
+// I2C2 is the HDMI DDC connection
+Device (I2C2)
+{
+ Name (_HID, "BCM2841")
+ Name (_CID, "BCM2841")
+ Name (_UID, 0x2)
+ Name (_CCA, 0x0)
+
+ Name (RBUF, ResourceTemplate()
+ {
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_I2C2_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_I2C2_INTERRUPT }
+ })
+
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_I2C2_OFFSET)
+ Return (^RBUF)
+ }
+}
+
+// SPI
+Device (SPI0)
+{
+ Name (_HID, "BCM2838")
+ Name (_CID, "BCM2838")
+ Name (_UID, 0x0)
+ Name (_CCA, 0x0)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_SPI0_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_SPI0_INTERRUPT }
+ PinFunction (Exclusive, PullDown, BCM_ALT0, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 9, 10, 11 } // MISO, MOSI, SCLK
+ PinFunction (Exclusive, PullUp, BCM_ALT0, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 8 } // CE0
+ PinFunction (Exclusive, PullUp, BCM_ALT0, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 7 } // CE1
+ })
+
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_SPI0_OFFSET)
+ Return (^RBUF)
+ }
+}
+
+Device (SPI1)
+{
+ Name (_HID, "BCM2839")
+ Name (_CID, "BCM2839")
+ Name (_UID, 0x1)
+ Name (_CCA, 0x0)
+ Name (_DEP, Package() { \_SB.GDV0.RPIQ })
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_SPI1_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Shared,) { BCM2836_SPI1_INTERRUPT }
+ PinFunction (Exclusive, PullDown, BCM_ALT4, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 19, 20, 21 } // MISO, MOSI, SCLK
+ PinFunction (Exclusive, PullDown, BCM_ALT4, "\\_SB.GDV0.GPI0", 0, ResourceConsumer, , ) { 16 } // CE2
+ })
+
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_SPI1_OFFSET)
+ Return (^RBUF)
+ }
+}
+
+// SPI2 has no pins on GPIO header
+// Device (SPI2)
+// {
+// Name (_HID, "BCM2839")
+// Name (_CID, "BCM2839")
+// Name (_UID, 0x2)
+// Name (_CCA, 0x0)
+// Name (_DEP, Package() { \_SB.GDV0.RPIQ })
+// Method (_STA)
+// {
+// Return (0xf) // Disabled
+// }
+// Method (_CRS, 0x0, Serialized)
+// {
+// Name (RBUF, ResourceTemplate ()
+// {
+// MEMORY32FIXED (ReadWrite, BCM2836_SPI2_BASE_ADDRESS, BCM2836_SPI2_LENGTH, RMEM)
+// Interrupt (ResourceConsumer, Level, ActiveHigh, Shared,) { BCM2836_SPI2_INTERRUPT }
+// })
+// Return (RBUF)
+// }
+// }
+
+// PWM Driver
+Device (PWM0)
+{
+ Name (_HID, "BCM2844")
+ Name (_CID, "BCM2844")
+ Name (_UID, 0)
+ Name (_CCA, 0x0)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ // DMA channel 11 control
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_PWM_DMA_LENGTH, RM01)
+ // PWM control
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_PWM_CTRL_LENGTH, RM02)
+ // PWM control bus
+ MEMORY32FIXED (ReadWrite, BCM2836_PWM_BUS_BASE_ADDRESS, BCM2836_PWM_BUS_LENGTH, )
+ // PWM control uncached
+ MEMORY32FIXED (ReadWrite, BCM2836_PWM_CTRL_UNCACHED_BASE_ADDRESS, BCM2836_PWM_CTRL_UNCACHED_LENGTH, )
+ // PWM clock control
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_PWM_CLK_LENGTH, RM03)
+ // Interrupt DMA channel 11
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_DMA_INTERRUPT }
+ // DMA channel 11, DREQ 5 for PWM
+ FixedDMA (5, 11, Width32Bit, )
+ })
+
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RM01, RB01, BCM2836_PWM_DMA_OFFSET)
+ MEMORY32SETBASE (RBUF, RM02, RB02, BCM2836_PWM_CTRL_OFFSET)
+ MEMORY32SETBASE (RBUF, RM03, RB03, BCM2836_PWM_CLK_OFFSET)
+ Return (^RBUF)
+ }
+} \ No newline at end of file
diff --git a/board/raspberrypi/rpi/pci.asl b/board/raspberrypi/rpi/pci.asl
new file mode 100644
index 00000000000..a7a09df5cd9
--- /dev/null
+++ b/board/raspberrypi/rpi/pci.asl
@@ -0,0 +1,177 @@
+/** @file
+ *
+ * Copyright (c) 2019 Linaro, Limited. All rights reserved.
+ * Copyright (c) 2021 Arm
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ **/
+
+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(_CCA, 0) // Mark the PCI noncoherent
+
+ // PCIe can only DMA to first 3GB with early SOC's
+ // But we keep the restriction on the later ones
+ // To avoid DMA translation problems.
+ Name (_DMA, ResourceTemplate() {
+ QWordMemory (ResourceProducer,
+ ,
+ MinFixed,
+ MaxFixed,
+ NonCacheable,
+ ReadWrite,
+ 0x0,
+ 0x0, // MIN
+ 0xbfffffff, // MAX
+ 0x0, // TRA
+ 0xc0000000, // LEN
+ ,
+ ,
+ )
+ })
+
+ // PCI Routing Table
+ Name(_PRT, Package() {
+ Package (4) { 0x0000FFFF, 0, zero, 175 },
+ Package (4) { 0x0000FFFF, 1, zero, 176 },
+ Package (4) { 0x0000FFFF, 2, zero, 177 },
+ Package (4) { 0x0000FFFF, 3, zero, 178 }
+ })
+
+ Name (_DSD, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package () { "linux-ecam-quirk-id", "bcm2711" },
+ }
+ })
+
+ // Root complex resources
+ Method (_CRS, 0, Serialized) {
+ Name (RBUF, ResourceTemplate () {
+
+ // bus numbers assigned to this root
+ WordBusNumber (
+ ResourceProducer,
+ MinFixed, MaxFixed, PosDecode,
+ 0, // AddressGranularity
+ 0, // AddressMinimum - Minimum Bus Number
+ 255, // AddressMaximum - Maximum Bus Number
+ 0, // AddressTranslation - Set to 0
+ 256 // RangeLength - Number of Busses
+ )
+
+ // 32-bit mmio window in 64-bit addr
+ QWordMemory (
+ ResourceProducer, PosDecode,
+ MinFixed, MaxFixed,
+ NonCacheable, ReadWrite, // cacheable
+ 0x00000000, // Granularity
+ 0, // PCIE_PCI_MMIO_BEGIN
+ 1, // PCIE_MMIO_LEN + PCIE_PCI_MMIO_BEGIN
+ PCIE_CPU_MMIO_WINDOW, // PCIE_PCI_MMIO_BEGIN - PCIE_CPU_MMIO_WINDOW
+ 2 // PCIE_MMIO_LEN + 1
+ ,,,MMI1
+ )
+
+ // root port registers, not to be used if SMCCC is utilized
+ QWordMemory (
+ ResourceConsumer, ,
+ MinFixed, MaxFixed,
+ NonCacheable, ReadWrite, // cacheable
+ 0x00000000, // Granularity
+ 0xFD500000, // Root port begin
+ 0xFD509FFF, // Root port end
+ 0x00000000, // no translation
+ 0x0000A000, // size
+ ,,
+ )
+ }) // end Name(RBUF)
+
+ // Work around ASL's inability to add in a resource definition
+ // or for that matter compute the min,max,len properly
+ CreateQwordField (RBUF, MMI1._MIN, MMIB)
+ CreateQwordField (RBUF, MMI1._MAX, MMIE)
+ CreateQwordField (RBUF, MMI1._TRA, MMIT)
+ CreateQwordField (RBUF, MMI1._LEN, MMIL)
+ Add (MMIB, PCIE_TOP_OF_MEM_WIN, MMIB)
+ Add (PCIE_BRIDGE_MMIO_LEN, PCIE_TOP_OF_MEM_WIN, MMIE)
+ Subtract (MMIT, PCIE_TOP_OF_MEM_WIN, MMIT)
+ Add (PCIE_BRIDGE_MMIO_LEN, 1 , MMIL)
+
+ Return (RBUF)
+ } // end Method(_CRS)
+
+ // 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) {
+ // Note, This code is very similar to the code in the PCIe firmware
+ // specification which can be used as a reference
+ // Check for proper UUID
+ If(LEqual(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)
+ // Mask out Native HotPlug
+ And(CTRL,0x1E,CTRL)
+ // Always allow native PME, AER (no dependencies)
+ // Never allow SHPC (no SHPC controller in this system)
+ And(CTRL,0x1D,CTRL)
+
+ If(LNotEqual(Arg1,One)) { // Unknown revision
+ Or(CDW1,0x08,CDW1)
+ }
+
+ If(LNotEqual(CDW3,CTRL)) { // Capabilities bits were masked
+ Or(CDW1,0x10,CDW1)
+ }
+ // Update DWORD3 in the buffer
+ Store(CTRL,CDW3)
+ Return(Arg3)
+ } Else {
+ Or(CDW1,4,CDW1) // Unrecognized UUID
+ Return(Arg3)
+ }
+ } // End _OSC
+
+ Device (XHC0)
+ {
+ Name (_ADR, 0x00010000)
+ Name (_CID, "PNP0D10")
+ Name (_UID, 0x0) // _UID: Unique ID
+ Name (_CCA, 0x0) // _CCA: Cache Coherency Attribute
+
+ /*
+ * Microsoft's USB Device-Specific Methods. See:
+ * https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/usb-device-specific-method---dsm-
+ */
+ Name (DSMU, ToUUID ("ce2ee385-00e6-48cb-9f05-2edb927c4899"))
+
+ Method (_DSM, 4, Serialized) {
+ If (LEqual (Arg0, DSMU)) { // USB capabilities UUID
+ Switch (ToInteger (Arg2)) {
+ Case (0) { // Function 0: List of supported functions
+ Return (Buffer () { 0x41 }) // 0x41 - Functions 0 and 6 supported
+ }
+ Case (6) { // Function 6: RegisterAccessType
+ Return (Buffer () { 0x01 }) // 0x01 - Must use 32bit register access
+ }
+ Default { } // Unsupported
+ }
+ }
+ return (Buffer () { 0x00 }) // Return 0x00 for anything unsupported
+ }
+ } // end XHC0
+
+} // PCI0 \ No newline at end of file
diff --git a/board/raspberrypi/rpi/pep.asl b/board/raspberrypi/rpi/pep.asl
new file mode 100644
index 00000000000..87469e2e5a9
--- /dev/null
+++ b/board/raspberrypi/rpi/pep.asl
@@ -0,0 +1,90 @@
+/** @file
+ *
+ * Platform Extension Plugin (PEP).
+ *
+ * Copyright (c) 2019, ARM Ltd. All rights reserved.
+ * Copyright (c) 2018, Andrey Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ **/
+
+Device(PEPD)
+{
+ //
+ // PEP virtual device.
+ //
+ Name (_HID, "BCM2854") // Note: Since PEP on RPi is a virtual device,
+ Name (_CID, "BCM2854") // its device id needs to be generated by Microsoft
+ Name (_UID, 0x0)
+ Name (_CRS, ResourceTemplate ()
+ {
+ // No hardware resources for PEP driver are needed.
+ })
+
+ //
+ // Processor info. PEP proprietary method to return
+ // PEP_PROCESSOR_TABLE_PLAT structure.
+ //
+ // See Pep.h and Pep.c.
+ //
+ Name (_GPI, Buffer()
+ {
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x5F, 0x00, 0x53,
+ 0x00, 0x42, 0x00, 0x2E, 0x00, 0x43, 0x00, 0x50, 0x00, 0x55, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ })
+
+ //
+ // Coordinated state info. PEP proprietary method to return
+ // PEP_COORDINATED_STATE_TABLE_PLAT structure.
+ //
+ // See Pep.h and Pep.c.
+ //
+ Name (_GCI, Buffer()
+ {
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+ })
+
+ //
+ // Device info. PEP proprietary method to return
+ // PEP_DEVICE_TABLE_PLAT structure.
+ //
+ // See Pep.h and Pep.c.
+ //
+ Name (_GDI, Buffer()
+ {
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x5F, 0x00, 0x53,
+ 0x00, 0x42, 0x00, 0x2E, 0x00, 0x49, 0x00, 0x32, 0x00, 0x43, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ })
+}
diff --git a/board/raspberrypi/rpi/rhpx.asl b/board/raspberrypi/rpi/rhpx.asl
new file mode 100644
index 00000000000..214b55c6564
--- /dev/null
+++ b/board/raspberrypi/rpi/rhpx.asl
@@ -0,0 +1,195 @@
+/** @file
+ *
+ * [DSDT] RHProxy device to enable WinRT API (RHPX)
+ *
+ * Copyright (c) 2018, Andrey Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ **/
+
+Device (RHPX)
+{
+ Name (_HID, "MSFT8000")
+ Name (_CID, "MSFT8000")
+ Name (_UID, 1)
+
+ Name(_CRS, ResourceTemplate ()
+ {
+ // Index 0
+ SPISerialBus ( // SCKL - GPIO 11 - Pin 23
+ // MOSI - GPIO 10 - Pin 19
+ // MISO - GPIO 9 - Pin 21
+ // CE0 - GPIO 8 - Pin 24
+ 0, // Device selection (CE0)
+ PolarityLow, // Device selection polarity
+ FourWireMode, // WireMode
+ 8, // DataBit len
+ ControllerInitiated, // Slave mode
+ 4000000, // Connection speed
+ ClockPolarityLow, // Clock polarity
+ ClockPhaseFirst, // Clock phase
+ "\\_SB.GDV0.SPI0", // ResourceSource: SPI bus controller name
+ 0, // ResourceSourceIndex
+ // Resource usage
+ // DescriptorName: creates name for offset of resource descriptor
+ ) // Vendor Data
+
+ // Index 1
+ SPISerialBus ( // SCKL - GPIO 11 - Pin 23
+ // MOSI - GPIO 10 - Pin 19
+ // MISO - GPIO 9 - Pin 21
+ // CE1 - GPIO 7 - Pin 26
+ 1, // Device selection (CE1)
+ PolarityLow, // Device selection polarity
+ FourWireMode, // WireMode
+ 8, // DataBit len
+ ControllerInitiated, // Slave mode
+ 4000000, // Connection speed
+ ClockPolarityLow, // Clock polarity
+ ClockPhaseFirst, // Clock phase
+ "\\_SB.GDV0.SPI0", // ResourceSource: SPI bus controller name
+ 0, // ResourceSourceIndex
+ // Resource usage
+ // DescriptorName: creates name for offset of resource descriptor
+ ) // Vendor Data
+
+ // Index 2
+ I2CSerialBus ( // Pin 3 (GPIO2, SDA1), 5 (GPIO3, SCL1)
+ 0xFFFF, // SlaveAddress: placeholder
+ , // SlaveMode: default to ControllerInitiated
+ 0, // ConnectionSpeed: placeholder
+ , // Addressing Mode: default to 7 bit
+ "\\_SB.GDV0.I2C1", // ResourceSource: I2C bus controller name
+ ,
+ ,
+ , // Descriptor Name: creates name for offset of resource descriptor
+ ) // Vendor Data
+
+ // Index 3
+ SPISerialBus ( // SPI1_SCLK - GPIO21
+ // SPI1_MOSI - GPIO20
+ // SPI1_MISO - GPIO19
+ // SPI1_CE2_N - GPIO16
+ 2, // Device selection (CE2)
+ PolarityLow, // Device selection polarity
+ FourWireMode, // WireMode
+ 8, // DataBit len
+ ControllerInitiated, // Slave mode
+ 4000000, // Connection speed
+ ClockPolarityLow, // Clock polarity
+ ClockPhaseFirst, // Clock phase
+ "\\_SB.GDV0.SPI1", // ResourceSource: SPI bus controller name
+ 0, // ResourceSourceIndex
+ // Resource usage
+ // DescriptorName: creates name for offset of resource descriptor
+ ) // Vendor Data
+
+ // GPIO 2
+ GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 2 }
+ GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 2 }
+ // GPIO 3
+ GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 3 }
+ GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 3 }
+ // GPIO 4
+ GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 4 }
+ GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 4 }
+ // GPIO 5
+ GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 5 }
+ GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 5 }
+ // GPIO 6
+ GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 6 }
+ GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 6 }
+ // GPIO 7
+ GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 7 }
+ GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 7 }
+ // GPIO 8
+ GpioIO (Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 8 }
+ GpioInt (Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GDV0.GPI0",) { 8 }
+ // GPIO 9
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 9 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 9 }
+ // GPIO 10
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 10 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 10 }
+ // GPIO 11
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 11 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 11 }
+ // GPIO 12
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 12 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 12 }
+ // GPIO 13
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 13 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 13 }
+ // NTRAID#MSFT-7141401-2016/04/7-jordanrh - disable UART muxing
+ // until a proper solution can be created for the dmap conflict
+ // GPIO 14 - UART TX
+ // GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 14 }
+ // GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 14 }
+ // GPIO 15 - UART RX
+ // GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 15 }
+ // GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 15 }
+ // GPIO 16
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 16 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 16 }
+ // GPIO 17
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 17 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 17 }
+ // GPIO 18
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 18 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 18 }
+ // GPIO 19
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 19 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 19 }
+ // GPIO 20
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 20 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 20 }
+ // GPIO 21
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 21 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 21 }
+ // GPIO 22
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 22 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 22 }
+ // GPIO 23
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 23 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 23 }
+ // GPIO 24
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 24 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 24 }
+ // GPIO 25
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 25 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 25 }
+ // GPIO 26
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 26 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 26 }
+ // GPIO 27
+ GpioIO (Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GDV0.GPI0", 0, ResourceConsumer,,) { 27 }
+ GpioInt (Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GDV0.GPI0",) { 27 }
+ })
+
+ Name (_DSD, Package()
+ {
+ ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package ()
+ {
+ // Reference http://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md
+ // SPI 0
+ Package (2) { "bus-SPI-SPI0", Package() { 0, 1 } }, // Index 0 & 1
+ Package (2) { "SPI0-MinClockInHz", 7629 }, // 7629 Hz
+ Package (2) { "SPI0-MaxClockInHz", 125000000 }, // 125 MHz
+ Package (2) { "SPI0-SupportedDataBitLengths", Package() { 8 } }, // Data Bit Length
+ // I2C1
+ Package (2) { "bus-I2C-I2C1", Package() { 2 } },
+ // GPIO Pin Count and supported drive modes
+ Package (2) { "GPIO-PinCount", 54 },
+ Package (2) { "GPIO-UseDescriptorPinNumbers", 1 },
+ Package (2) { "GPIO-SupportedDriveModes", 0xf }, // InputHighImpedance, InputPullUp, InputPullDown, OutputCmos
+ // SPI 1
+ Package (2) { "bus-SPI-SPI1", Package() { 3 }}, // Index 3
+ Package (2) { "SPI1-MinClockInHz", 30511 }, // 30.5 kHz
+ Package (2) { "SPI1-MaxClockInHz", 20000000 }, // 20 MHz
+ Package (2) { "SPI1-SupportedDataBitLengths", Package() { 8 } }, // Data Bit Length
+ }
+ })
+}
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index ab5ea85cf9f..9122f33d88d 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -23,6 +23,11 @@
#endif
#include <watchdog.h>
#include <dm/pinctrl.h>
+#include <dm/ofnode.h>
+#include <acpi/acpi_table.h>
+#include <acpi/acpigen.h>
+#include <dm/lists.h>
+#include <tables_csum.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -583,3 +588,181 @@ int ft_board_setup(void *blob, struct bd_info *bd)
return 0;
}
+
+#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+static bool is_rpi4(void)
+{
+ return of_machine_is_compatible("brcm,bcm2711") ||
+ of_machine_is_compatible("brcm,bcm2712");
+}
+
+static bool is_rpi3(void)
+{
+ return of_machine_is_compatible("brcm,bcm2837");
+}
+
+static int acpi_rpi_board_fill_ssdt(struct acpi_ctx *ctx)
+{
+ int node, ret, uart_in_use, mini_clock_rate;
+ bool enabled;
+ struct udevice *dev;
+ struct {
+ const char *fdt_compatible;
+ const char *acpi_scope;
+ bool on_rpi4;
+ bool on_rpi3;
+ u32 mmio_address;
+ } map[] = {
+ {"brcm,bcm2711-pcie", "\\_SB.PCI0", true, false},
+ {"brcm,bcm2711-emmc2", "\\_SB.GDV1.SDC3", true, false},
+ {"brcm,bcm2835-pwm", "\\_SB.GDV0.PWM0", true, true},
+ {"brcm,bcm2711-genet-v5", "\\_SB.ETH0", true, false},
+ {"brcm,bcm2711-thermal", "\\_SB.EC00", true, true},
+ {"brcm,bcm2835-sdhci", "\\_SB.SDC1", true, true},
+ {"brcm,bcm2835-sdhost", "\\_SB.SDC2", false, true},
+ {"brcm,bcm2835-mbox", "\\_SB.GDV0.RPIQ", true, true},
+ {"brcm,bcm2835-i2c", "\\_SB.GDV0.I2C1", true, true, 0xfe205000},
+ {"brcm,bcm2835-i2c", "\\_SB.GDV0.I2C2", true, true, 0xfe804000},
+ {"brcm,bcm2835-spi", "\\_SB.GDV0.SPI0", true, true},
+ {"brcm,bcm2835-aux-spi", "\\_SB.GDV0.SPI1", true, true, 0xfe215080},
+ {"arm,pl011", "\\_SB.URT0", true, true},
+ {"brcm,bcm2835-aux-uart", "\\_SB.URTM", true, true},
+ { /* Sentinel */ }
+ };
+
+ /* Device enable */
+ for (int i = 0; map[i].fdt_compatible; i++) {
+ if ((is_rpi4() && !map[i].on_rpi4) ||
+ (is_rpi3() && !map[i].on_rpi3)) {
+ enabled = false;
+ } else {
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
+ map[i].fdt_compatible);
+ while (node != -FDT_ERR_NOTFOUND && map[i].mmio_address) {
+ struct fdt_resource r;
+
+ ret = fdt_get_resource(gd->fdt_blob, node, "reg", 0, &r);
+ if (ret) {
+ node = -FDT_ERR_NOTFOUND;
+ break;
+ }
+
+ if (r.start == map[i].mmio_address)
+ break;
+
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, node,
+ map[i].fdt_compatible);
+ }
+
+ enabled = (node > 0) ? fdtdec_get_is_enabled(gd->fdt_blob, node) : 0;
+ }
+ acpigen_write_scope(ctx, map[i].acpi_scope);
+ acpigen_write_name_integer(ctx, "_STA", enabled ? 0xf : 0);
+ acpigen_pop_len(ctx);
+ }
+
+ /* GPIO quirks */
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "brcm,bcm2835-gpio");
+ if (node <= 0)
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "brcm,bcm2711-gpio");
+
+ acpigen_write_scope(ctx, "\\_SB.GDV0.GPI0");
+ enabled = (node > 0) ? fdtdec_get_is_enabled(gd->fdt_blob, node) : 0;
+ acpigen_write_name_integer(ctx, "_STA", enabled ? 0xf : 0);
+ acpigen_pop_len(ctx);
+
+ if (is_rpi4()) {
+ /* eMMC quirks */
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "brcm,bcm2711-emmc2");
+ if (node) {
+ phys_addr_t cpu;
+ dma_addr_t bus;
+ u64 size;
+
+ ret = fdt_get_dma_range(gd->fdt_blob, node, &cpu, &bus, &size);
+
+ acpigen_write_scope(ctx, "\\_SB.GDV1");
+ acpigen_write_method_serialized(ctx, "_DMA", 0);
+ acpigen_emit_byte(ctx, RETURN_OP);
+
+ if (!ret && bus != cpu) /* Translated DMA range */
+ acpigen_emit_namestring(ctx, "\\_SB.GDV1.DMTR");
+ else if (!ret && bus == cpu) /* Non translated DMA */
+ acpigen_emit_namestring(ctx, "\\_SB.GDV1.DMNT");
+ else /* Silicon revisions older than C0: Translated DMA range */
+ acpigen_emit_namestring(ctx, "\\_SB.GDV1.DMTR");
+ acpigen_pop_len(ctx);
+ }
+ }
+
+ /* Serial */
+ uart_in_use = ~0;
+ mini_clock_rate = 0x1000000;
+
+ ret = uclass_get_device_by_driver(UCLASS_SERIAL,
+ DM_DRIVER_GET(bcm283x_pl011_uart),
+ &dev);
+ if (!ret)
+ uart_in_use = 0;
+
+ ret = uclass_get_device_by_driver(UCLASS_SERIAL,
+ DM_DRIVER_GET(serial_bcm283x_mu),
+ &dev);
+ if (!ret) {
+ if (uart_in_use == 0)
+ log_err("Invalid config: PL011 and MiniUART are both enabled.");
+ else
+ uart_in_use = 1;
+
+ mini_clock_rate = dev_read_u32_default(dev, "clock", 0x1000000);
+ }
+ if (uart_in_use > 1)
+ log_err("No working serial: PL011 and MiniUART are both disabled.");
+
+ acpigen_write_scope(ctx, "\\_SB.BTH0");
+ acpigen_write_name_integer(ctx, "URIU", uart_in_use);
+ acpigen_pop_len(ctx);
+
+ acpigen_write_scope(ctx, "\\_SB.URTM");
+ acpigen_write_name_integer(ctx, "MUCR", mini_clock_rate);
+ acpigen_pop_len(ctx);
+
+ return 0;
+}
+
+static int rpi_acpi_write_ssdt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_header *ssdt;
+ int ret;
+
+ ssdt = ctx->current;
+ memset(ssdt, '\0', sizeof(struct acpi_table_header));
+
+ acpi_fill_header(ssdt, "SSDT");
+ ssdt->revision = acpi_get_table_revision(ACPITAB_SSDT);
+ ssdt->creator_revision = 1;
+ ssdt->length = sizeof(struct acpi_table_header);
+
+ acpi_inc(ctx, sizeof(struct acpi_table_header));
+
+ ret = acpi_rpi_board_fill_ssdt(ctx);
+ if (ret) {
+ ctx->current = ssdt;
+ return log_msg_ret("fill", ret);
+ }
+
+ /* (Re)calculate length and checksum */
+ ssdt->length = ctx->current - (void *)ssdt;
+ ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
+ log_debug("SSDT at %p, length %x\n", ssdt, ssdt->length);
+
+ /* Drop the table if it is empty */
+ if (ssdt->length == sizeof(struct acpi_table_header))
+ return log_msg_ret("fill", -ENOENT);
+ acpi_add_table(ctx, ssdt);
+
+ return 0;
+}
+
+ACPI_WRITER(5ssdt, "SSDT", rpi_acpi_write_ssdt, 0);
+#endif
diff --git a/board/raspberrypi/rpi/sdhc.asl b/board/raspberrypi/rpi/sdhc.asl
new file mode 100644
index 00000000000..3feac14acf2
--- /dev/null
+++ b/board/raspberrypi/rpi/sdhc.asl
@@ -0,0 +1,111 @@
+/** @file
+ *
+ * [DSDT] SD controller/card definition (SDHC)
+ *
+ * Copyright (c) 2020, Pete Batard <pete@akeo.ie>
+ * Copyright (c) 2018, Andrey Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ **/
+
+#include <asm/arch/acpi/bcm2836_sdhost.h>
+#include <asm/arch/acpi/bcm2836_sdio.h>
+
+#include "acpitables.h"
+
+//
+// Note: UEFI can use either SDHost or Arasan. We expose both to the OS.
+//
+
+// ArasanSD 3.0 SD Host Controller. (brcm,bcm2835-sdhci)
+Device (SDC1)
+{
+ Name (_HID, "BCM2847")
+ Name (_CID, "BCM2847")
+ Name (_UID, 0x0)
+ Name (_CCA, 0x0)
+ Name (_S1D, 0x1)
+ Name (_S2D, 0x1)
+ Name (_S3D, 0x1)
+ Name (_S4D, 0x1)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, MMCHS1_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_MMCHS1_INTERRUPT }
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, MMCHS1_OFFSET)
+ Return (^RBUF)
+ }
+
+ // The standard CAPs registers on this controller
+ // appear to be 0, lets set some minimal defaults
+ // Since this cap doesn't indicate DMA capability
+ // we don't need a _DMA()
+ Name (_DSD, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package () { "sdhci-caps", 0x0120fa81 },
+ }
+ })
+
+ //
+ // A child device that represents the
+ // sd card, which is marked as non-removable.
+ //
+ Device (SDMM)
+ {
+ Method (_ADR)
+ {
+ Return (0)
+ }
+ Method (_RMV) // Is removable
+ {
+ Return (0) // 0 - fixed
+ }
+ }
+}
+
+// Broadcom SDHost 2.0 SD Host Controller
+Device (SDC2)
+{
+ Name (_HID, "BCM2855")
+ Name (_CID, "BCM2855")
+ Name (_UID, 0x0)
+ Name (_CCA, 0x0)
+ Name (_S1D, 0x1)
+ Name (_S2D, 0x1)
+ Name (_S3D, 0x1)
+ Name (_S4D, 0x1)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, SDHOST_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_SDHOST_INTERRUPT }
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, SDHOST_OFFSET)
+ Return (^RBUF)
+ }
+
+ //
+ // A child device that represents the
+ // sd card, which is marked as non-removable.
+ //
+ Device (SDMM)
+ {
+ Method (_ADR)
+ {
+ Return (0)
+ }
+ Method (_RMV) // Is removable
+ {
+ Return (0) // 0 - fixed
+ }
+ }
+} \ No newline at end of file
diff --git a/board/raspberrypi/rpi/uart.asl b/board/raspberrypi/rpi/uart.asl
new file mode 100644
index 00000000000..78dc9a74dfc
--- /dev/null
+++ b/board/raspberrypi/rpi/uart.asl
@@ -0,0 +1,208 @@
+/** @file
+ *
+ * [DSDT] Serial devices (UART).
+ *
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ * Copyright (c) 2020, Pete Batard <pete@akeo.ie>
+ * Copyright (c) 2018, Andrey Warkentin <andrey.warkentin@gmail.com>
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ *
+ **/
+
+#include <asm/arch/acpi/bcm2836.h>
+
+#include "acpitables.h"
+
+// PL011 based UART.
+Device (URT0)
+{
+ Name (_HID, "BCM2837")
+ Name (_CID, "ARMH0011")
+ Name (_UID, 0x4)
+ Name (_CCA, 0x0)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_PL011_UART_LENGTH, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { BCM2836_PL011_UART_INTERRUPT }
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_PL011_UART_OFFSET)
+ Return (^RBUF)
+ }
+
+ Name (CLCK, 48000000)
+
+ Name (_DSD, Package ()
+ {
+ ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package ()
+ {
+ Package (2) { "clock-frequency", CLCK },
+ }
+ })
+}
+
+//
+// UART Mini.
+//
+// This device is referenced in the DBG2 table, which will cause the system to
+// not start the driver when the debugger is enabled and to mark the device
+// with problem code 53 (CM_PROB_USED_BY_DEBUGGER).
+//
+
+Device (URTM)
+{
+ Name (_HID, "BCM2836")
+ Name (_CID, "BCM2836")
+ Name (_UID, 0x0)
+ Name (_CCA, 0x0)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ MEMORY32FIXED (ReadWrite, 0, BCM2836_MINI_UART_LENGTH, RMEM)
+ Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) { BCM2836_MINI_UART_INTERRUPT }
+
+ })
+ Method (_CRS, 0x0, Serialized)
+ {
+ MEMORY32SETBASE (RBUF, RMEM, RBAS, BCM2836_MINI_UART_OFFSET)
+ Return (^RBUF)
+ }
+
+ //
+ // Mini Uart Clock Rate will be dynamically updated during boot
+ //
+ External (\_SB.URTM.MUCR, IntObj)
+
+ Name (_DSD, Package ()
+ {
+ ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package ()
+ {
+ Package (2) { "clock-frequency", MUCR },
+ }
+ })
+}
+
+//
+// Multifunction serial bus device to support Bluetooth function.
+//
+Device(BTH0)
+{
+ Name (_HID, "BCM2EA6")
+ Name (_CID, "BCM2EA6")
+
+ //
+ // UART In Use will be dynamically updated during boot
+ //
+ External (\_SB.BTH0.URIU, IntObj)
+
+ Method (_STA)
+ {
+ Return (0xf)
+ }
+
+ //
+ // Resource for URT0 (PL011)
+ //
+ Name (BTPL, ResourceTemplate ()
+ {
+ UARTSerialBus(
+ 115200, // InitialBaudRate: in BPS
+ , // BitsPerByte: default to 8 bits
+ , // StopBits: Defaults to one bit
+ 0x00, // LinesInUse: 8 1-bit flags to
+ // declare enabled control lines.
+ // Raspberry Pi does not exposed
+ // HW control signals -> not supported.
+ // Optional bits:
+ // - Bit 7 (0x80) Request To Send (RTS)
+ // - Bit 6 (0x40) Clear To Send (CTS)
+ // - Bit 5 (0x20) Data Terminal Ready (DTR)
+ // - Bit 4 (0x10) Data Set Ready (DSR)
+ // - Bit 3 (0x08) Ring Indicator (RI)
+ // - Bit 2 (0x04) Data Carrier Detect (DTD)
+ // - Bit 1 (0x02) Reserved. Must be 0.
+ // - Bit 0 (0x01) Reserved. Must be 0.
+ , // IsBigEndian:
+ // default to LittleEndian.
+ , // Parity: Defaults to no parity
+ , // FlowControl: Defaults to
+ // no flow control.
+ 16, // ReceiveBufferSize
+ 16, // TransmitBufferSize
+ "\\_SB.GDV0.URT0", // ResourceSource:
+ // UART bus controller name
+ , // ResourceSourceIndex: assumed to be 0
+ , // ResourceUsage: assumed to be
+ // ResourceConsumer
+ UAR0, // DescriptorName: creates name
+ // for offset of resource descriptor
+ ) // Vendor data
+ })
+
+ //
+ // Resource for URTM (miniUART)
+ //
+ Name (BTMN, ResourceTemplate ()
+ {
+ //
+ // BT UART: ResourceSource will be dynamically updated to
+ // either URT0 (PL011) or URTM (miniUART) during boot
+ //
+ UARTSerialBus(
+ 115200, // InitialBaudRate: in BPS
+ , // BitsPerByte: default to 8 bits
+ , // StopBits: Defaults to one bit
+ 0x00, // LinesInUse: 8 1-bit flags to
+ // declare enabled control lines.
+ // Raspberry Pi does not exposed
+ // HW control signals -> not supported.
+ // Optional bits:
+ // - Bit 7 (0x80) Request To Send (RTS)
+ // - Bit 6 (0x40) Clear To Send (CTS)
+ // - Bit 5 (0x20) Data Terminal Ready (DTR)
+ // - Bit 4 (0x10) Data Set Ready (DSR)
+ // - Bit 3 (0x08) Ring Indicator (RI)
+ // - Bit 2 (0x04) Data Carrier Detect (DTD)
+ // - Bit 1 (0x02) Reserved. Must be 0.
+ // - Bit 0 (0x01) Reserved. Must be 0.
+ , // IsBigEndian:
+ // default to LittleEndian.
+ , // Parity: Defaults to no parity
+ , // FlowControl: Defaults to
+ // no flow control.
+ 16, // ReceiveBufferSize
+ 16, // TransmitBufferSize
+ "\\_SB.GDV0.URTM", // ResourceSource:
+ // UART bus controller name
+ , // ResourceSourceIndex: assumed to be 0
+ , // ResourceUsage: assumed to be
+ // ResourceConsumer
+ UARM, // DescriptorName: creates name
+ // for offset of resource descriptor
+ ) // Vendor data
+ })
+
+ Method (_CRS, 0x0, Serialized)
+ {
+ if (URIU == 0)
+ {
+ //
+ // PL011 UART is configured for console output
+ // Return Mini UART for Bluetooth
+ //
+ return (^BTMN)
+ }
+ else
+ {
+ //
+ // Mini UART is configured for console output
+ // Return PL011 UART for Bluetooth
+ //
+ return (^BTPL)
+ }
+ }
+}
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 59d77d2385f..d8807eb109d 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -936,11 +936,15 @@ int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg)
return ret;
*buf = '\0';
- if (!strcmp("earlycon", arg)) {
+ if (!strcmp("earlycon", arg) && info.type == SERIAL_CHIP_16550_COMPATIBLE) {
snprintf(buf, sizeof(buf),
"uart8250,mmio32,%#lx,%dn8", info.addr,
info.baudrate);
- } else if (!strcmp("console", arg)) {
+ } else if (!strcmp("earlycon", arg) && info.type == SERIAL_CHIP_PL01X) {
+ snprintf(buf, sizeof(buf),
+ "pl011,mmio32,%#lx,%dn8", info.addr,
+ info.baudrate);
+ } else if (!strcmp("console", arg) && info.type == SERIAL_CHIP_16550_COMPATIBLE) {
snprintf(buf, sizeof(buf),
"ttyS0,%dn8", info.baudrate);
}
diff --git a/common/Kconfig b/common/Kconfig
index 14a6c44c804..e8d89bf6eb9 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1081,6 +1081,7 @@ config BLOBLIST_SIZE_RELOC
hex "Size of bloblist after relocation"
default BLOBLIST_SIZE if BLOBLIST_FIXED || BLOBLIST_ALLOC
default 0x0 if BLOBLIST_PASSAGE
+ default 0x20000 if (ARM && EFI_LOADER && GENERATE_ACPI_TABLE)
help
Sets the size of the bloblist in bytes after relocation. Since U-Boot
has a lot more memory available then, it is possible to use a larger
diff --git a/common/bloblist.c b/common/bloblist.c
index 6640ad1fd69..ec6ff7a5a93 100644
--- a/common/bloblist.c
+++ b/common/bloblist.c
@@ -499,7 +499,7 @@ int bloblist_init(void)
{
bool fixed = IS_ENABLED(CONFIG_BLOBLIST_FIXED);
int ret = -ENOENT;
- ulong addr, size;
+ ulong addr = 0, size;
/*
* If U-Boot is not in the first phase, an existing bloblist must be
* at a fixed address.
diff --git a/configs/clearfog_defconfig b/configs/clearfog_defconfig
index f251d69253a..bba25e09494 100644
--- a/configs/clearfog_defconfig
+++ b/configs/clearfog_defconfig
@@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_DM_PCA953X=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MVTWSI=y
diff --git a/configs/clearfog_gt_8k_defconfig b/configs/clearfog_gt_8k_defconfig
index cabd2226d78..eaa8a333049 100644
--- a/configs/clearfog_gt_8k_defconfig
+++ b/configs/clearfog_gt_8k_defconfig
@@ -46,7 +46,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_DM_I2C=y
diff --git a/configs/clearfog_sata_defconfig b/configs/clearfog_sata_defconfig
index 8d4b54cb12e..b82d604c237 100644
--- a/configs/clearfog_sata_defconfig
+++ b/configs/clearfog_sata_defconfig
@@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_DM_PCA953X=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MVTWSI=y
diff --git a/configs/clearfog_spi_defconfig b/configs/clearfog_spi_defconfig
index 2f58e94a62b..cef80d69a38 100644
--- a/configs/clearfog_spi_defconfig
+++ b/configs/clearfog_spi_defconfig
@@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_DM_PCA953X=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MVTWSI=y
diff --git a/configs/db-88f6820-gp_defconfig b/configs/db-88f6820-gp_defconfig
index b327149ad72..5b69a20ae5d 100644
--- a/configs/db-88f6820-gp_defconfig
+++ b/configs/db-88f6820-gp_defconfig
@@ -58,7 +58,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_SYS_I2C_LEGACY=y
CONFIG_SPL_SYS_I2C_LEGACY=y
CONFIG_SYS_I2C_MVTWSI=y
diff --git a/configs/ds116_defconfig b/configs/ds116_defconfig
index 0bb7e301a64..c321e6f484d 100644
--- a/configs/ds116_defconfig
+++ b/configs/ds116_defconfig
@@ -65,7 +65,7 @@ CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_NETCONSOLE=y
CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_DM_I2C=y
diff --git a/configs/helios4_defconfig b/configs/helios4_defconfig
index 61d110e6f4c..e45446c2d05 100644
--- a/configs/helios4_defconfig
+++ b/configs/helios4_defconfig
@@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_DM_PCA953X=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MVTWSI=y
diff --git a/configs/mvebu_crb_cn9130_defconfig b/configs/mvebu_crb_cn9130_defconfig
index 505f063605f..e8984b663b5 100644
--- a/configs/mvebu_crb_cn9130_defconfig
+++ b/configs/mvebu_crb_cn9130_defconfig
@@ -46,7 +46,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_DEV=1
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_DM_I2C=y
diff --git a/configs/mvebu_db-88f3720_defconfig b/configs/mvebu_db-88f3720_defconfig
index 962edb790b7..e5de34c85fc 100644
--- a/configs/mvebu_db-88f3720_defconfig
+++ b/configs/mvebu_db-88f3720_defconfig
@@ -43,7 +43,7 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_CLK=y
diff --git a/configs/mvebu_db_armada8k_defconfig b/configs/mvebu_db_armada8k_defconfig
index 7c6b53ed3a6..f9b03a7e77a 100644
--- a/configs/mvebu_db_armada8k_defconfig
+++ b/configs/mvebu_db_armada8k_defconfig
@@ -42,7 +42,7 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_DM_I2C=y
diff --git a/configs/mvebu_db_cn9130_defconfig b/configs/mvebu_db_cn9130_defconfig
index f80812c811a..6dd6be788d3 100644
--- a/configs/mvebu_db_cn9130_defconfig
+++ b/configs/mvebu_db_cn9130_defconfig
@@ -47,7 +47,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_DEV=1
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_DM_GPIO_LOOKUP_LABEL=y
diff --git a/configs/mvebu_espressobin-88f3720_defconfig b/configs/mvebu_espressobin-88f3720_defconfig
index 375705caa4b..e9ee88594e9 100644
--- a/configs/mvebu_espressobin-88f3720_defconfig
+++ b/configs/mvebu_espressobin-88f3720_defconfig
@@ -54,7 +54,7 @@ CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_AHCI_PCI=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_CLK=y
diff --git a/configs/mvebu_espressobin_ultra-88f3720_defconfig b/configs/mvebu_espressobin_ultra-88f3720_defconfig
index fe3def1fe6b..aa9026acc34 100644
--- a/configs/mvebu_espressobin_ultra-88f3720_defconfig
+++ b/configs/mvebu_espressobin_ultra-88f3720_defconfig
@@ -53,7 +53,7 @@ CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_AHCI_PCI=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_CLK=y
diff --git a/configs/mvebu_mcbin-88f8040_defconfig b/configs/mvebu_mcbin-88f8040_defconfig
index c1b470c9825..90d341e0a4c 100644
--- a/configs/mvebu_mcbin-88f8040_defconfig
+++ b/configs/mvebu_mcbin-88f8040_defconfig
@@ -46,7 +46,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_DM_I2C=y
diff --git a/configs/mvebu_puzzle-m801-88f8040_defconfig b/configs/mvebu_puzzle-m801-88f8040_defconfig
index 1d86e26833d..21ab2177058 100644
--- a/configs/mvebu_puzzle-m801-88f8040_defconfig
+++ b/configs/mvebu_puzzle-m801-88f8040_defconfig
@@ -50,7 +50,7 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_DM_PCA953X=y
diff --git a/configs/n2350_defconfig b/configs/n2350_defconfig
index 8d54882ee85..7851bc470c0 100644
--- a/configs/n2350_defconfig
+++ b/configs/n2350_defconfig
@@ -65,7 +65,7 @@ CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_NETCONSOLE=y
CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_DM_I2C=y
diff --git a/configs/octeon_nic23_defconfig b/configs/octeon_nic23_defconfig
index 0febe80bd96..76adbf201e3 100644
--- a/configs/octeon_nic23_defconfig
+++ b/configs/octeon_nic23_defconfig
@@ -46,7 +46,7 @@ CONFIG_EFI_PARTITION=y
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_TFTP_TSIZE=y
CONFIG_SATA=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_CLK=y
diff --git a/configs/qemu-arm-sbsa_defconfig b/configs/qemu-arm-sbsa_defconfig
new file mode 100644
index 00000000000..69195afeedf
--- /dev/null
+++ b/configs/qemu-arm-sbsa_defconfig
@@ -0,0 +1,12 @@
+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
+CONFIG_BLOBLIST_ALLOC=y
+CONFIG_BLOBLIST_SIZE_RELOC=0x20000
diff --git a/configs/rpi_4_acpi_defconfig b/configs/rpi_4_acpi_defconfig
new file mode 100644
index 00000000000..b32dfc16a19
--- /dev/null
+++ b/configs/rpi_4_acpi_defconfig
@@ -0,0 +1,10 @@
+#include <configs/rpi_4_defconfig>
+
+CONFIG_ARM=y
+CONFIG_ARCH_BCM283X=y
+CONFIG_TARGET_RPI_4=y
+CONFIG_BLOBLIST_ALLOC=y
+CONFIG_OF_BOARD=y
+CONFIG_ACPI=y
+CONFIG_GENERATE_ACPI_TABLE=y
+
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 3bb85591834..dd1a45bd258 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -90,7 +90,7 @@ CONFIG_NET_RETRY_COUNT=50
CONFIG_NETCONSOLE=y
CONFIG_SPL_OF_TRANSLATE=y
CONFIG_AHCI_PCI=y
-CONFIG_AHCI_MVEBU=y
+CONFIG_AHCI_GENERIC=y
CONFIG_DM_PCA953X=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_MV=y
diff --git a/doc/board/emulation/index.rst b/doc/board/emulation/index.rst
index 98a0b26ad24..0419d724150 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 00000000000..fe1dc3249e4
--- /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@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 ARMv7/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 8ac9c94cafe..31b94d04675 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/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 6cca561f974..4fbb63a148a 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -78,14 +78,16 @@ config MTK_AHCI
Enable this driver to support Sata devices through
Mediatek AHCI controller (e.g. MT7622).
-config AHCI_MVEBU
- bool "Marvell EBU AHCI SATA support"
- depends on ARCH_MVEBU || ARCH_OCTEON
+config AHCI_GENERIC
+ bool "Generic AHCI SATA support"
+ depends on OF_CONTROL
select SCSI_AHCI
select SCSI
help
- This option enables support for the Marvell EBU SoC's
- onboard AHCI SATA.
+ This option enables support for generic onboard AHCI SATA controller
+ that do not need platform specific quirks, like emulated devices,
+ Marvell EBU SoC's onboard AHCI SATA controllers or Cavium's Octeon
+ 7130 AHCI controllers.
If unsure, say N.
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index ee10c4445b0..69fa9b707e0 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -14,6 +14,6 @@ obj-$(CONFIG_SATA) += sata.o sata_bootdev.o
obj-$(CONFIG_SATA_CEVA) += sata_ceva.o
obj-$(CONFIG_SATA_MV) += sata_mv.o
obj-$(CONFIG_SATA_SIL) += sata_sil.o
-obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o
+obj-$(CONFIG_AHCI_GENERIC) += ahci_generic.o
obj-$(CONFIG_SUNXI_AHCI) += ahci_sunxi.o
obj-$(CONFIG_MTK_AHCI) += mtk_ahci.o
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_generic.c
index f6e2d6bee45..6e5a6cbafd8 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_generic.c
@@ -16,7 +16,7 @@ __weak int board_ahci_enable(void)
return 0;
}
-static int mvebu_ahci_bind(struct udevice *dev)
+static int generic_ahci_bind(struct udevice *dev)
{
struct udevice *scsi_dev;
int ret;
@@ -30,7 +30,7 @@ static int mvebu_ahci_bind(struct udevice *dev)
return 0;
}
-static int mvebu_ahci_probe(struct udevice *dev)
+static int generic_ahci_probe(struct udevice *dev)
{
/*
* Board specific SATA / AHCI enable code, e.g. enable the
@@ -43,18 +43,19 @@ static int mvebu_ahci_probe(struct udevice *dev)
return 0;
}
-static const struct udevice_id mvebu_ahci_ids[] = {
+static const struct udevice_id generic_ahci_ids[] = {
{ .compatible = "marvell,armada-380-ahci" },
{ .compatible = "marvell,armada-3700-ahci" },
{ .compatible = "marvell,armada-8k-ahci" },
{ .compatible = "cavium,octeon-7130-ahci" },
+ { .compatible = "generic-ahci" },
{ }
};
-U_BOOT_DRIVER(ahci_mvebu_drv) = {
- .name = "ahci_mvebu",
+U_BOOT_DRIVER(ahci_generic_drv) = {
+ .name = "ahci_generic",
.id = UCLASS_AHCI,
- .of_match = mvebu_ahci_ids,
- .bind = mvebu_ahci_bind,
- .probe = mvebu_ahci_probe,
+ .of_match = generic_ahci_ids,
+ .bind = generic_ahci_bind,
+ .probe = generic_ahci_probe,
};
diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c
index 9f784228921..4763963914b 100644
--- a/drivers/core/acpi.c
+++ b/drivers/core/acpi.c
@@ -48,6 +48,7 @@ enum method_t {
METHOD_FILL_SSDT,
METHOD_INJECT_DSDT,
METHOD_SETUP_NHLT,
+ METHOD_FILL_MADT,
};
/* Prototype for all methods */
@@ -282,6 +283,8 @@ acpi_method acpi_get_method(struct udevice *dev, enum method_t method)
switch (method) {
case METHOD_WRITE_TABLES:
return aops->write_tables;
+ case METHOD_FILL_MADT:
+ return aops->fill_madt;
case METHOD_FILL_SSDT:
return aops->fill_ssdt;
case METHOD_INJECT_DSDT:
@@ -328,6 +331,19 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent,
return 0;
}
+int acpi_fill_madt_subtbl(struct acpi_ctx *ctx)
+{
+ int ret;
+
+ log_debug("Writing MADT table\n");
+ ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_MADT, TYPE_NONE);
+ log_debug("Writing MADT finished, err=%d\n", ret);
+ if (ret)
+ return log_msg_ret("build", ret);
+
+ return ret;
+}
+
int acpi_fill_ssdt(struct acpi_ctx *ctx)
{
void *start = ctx->current;
diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig
index 5c06cd9f60e..4cc3679c009 100644
--- a/drivers/cpu/Kconfig
+++ b/drivers/cpu/Kconfig
@@ -26,6 +26,13 @@ config CPU_RISCV
help
Support CPU cores for RISC-V architecture.
+config CPU_ARMV8
+ bool "Enable generic ARMv8 CPU driver"
+ depends on CPU && ARM64
+ select IRQ
+ help
+ Support CPU cores for armv8 architecture.
+
config CPU_MICROBLAZE
bool "Enable Microblaze CPU driver"
depends on CPU && MICROBLAZE
diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
index bc75d9b974e..eaf494706e2 100644
--- a/drivers/cpu/Makefile
+++ b/drivers/cpu/Makefile
@@ -6,10 +6,12 @@
obj-$(CONFIG_CPU) += cpu-uclass.o
+obj-$(CONFIG_ARCH_BCM283X) += bcm283x_cpu.o
obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o
obj-$(CONFIG_ARCH_AT91) += at91_cpu.o
obj-$(CONFIG_ARCH_MEDIATEK) += mtk_cpu.o
+obj-$(CONFIG_CPU_ARMV8) += armv8_cpu.o
obj-$(CONFIG_CPU_IMX) += imx8_cpu.o
obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
diff --git a/drivers/cpu/armv8_cpu.c b/drivers/cpu/armv8_cpu.c
new file mode 100644
index 00000000000..4eedfe5e2c5
--- /dev/null
+++ b/drivers/cpu/armv8_cpu.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 9elements GmbH
+ */
+#include <cpu.h>
+#include <dm.h>
+#include <irq.h>
+#include <acpi/acpigen.h>
+#include <asm/armv8/cpu.h>
+#include <asm/io.h>
+#include <dm/acpi.h>
+#include <linux/bitops.h>
+#include <linux/printk.h>
+#include <linux/sizes.h>
+
+static int armv8_cpu_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ int cpuid;
+
+ cpuid = (read_midr() & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT;
+
+ snprintf(buf, size, "CPU MIDR %04x", cpuid);
+
+ return 0;
+}
+
+static int armv8_cpu_get_info(const struct udevice *dev,
+ struct cpu_info *info)
+{
+ info->cpu_freq = 0;
+ info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
+
+ return 0;
+}
+
+static int armv8_cpu_get_count(const struct udevice *dev)
+{
+ return uclass_id_count(UCLASS_CPU);
+}
+
+#ifdef CONFIG_ACPIGEN
+int armv8_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ uint core_id = dev_seq(dev);
+
+ acpigen_write_processor_device(ctx, core_id);
+
+ return 0;
+}
+
+int armv8_cpu_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ struct acpi_madt_gicc *gicc;
+ struct cpu_plat *cpu_plat;
+ struct udevice *gic;
+ u64 gicc_gicv = 0;
+ u64 gicc_gich = 0;
+ u64 gicc_gicr_base = 0;
+ u64 gicc_phys_base = 0;
+ u32 gicc_perf_gsiv = 0;
+ u64 gicc_mpidr;
+ u32 gicc_vgic_maint_irq = 0;
+ int addr_index;
+ fdt_addr_t addr;
+ int ret;
+ struct irq req_irq;
+
+ cpu_plat = dev_get_parent_plat(dev);
+ if (!cpu_plat)
+ return 0;
+
+ ret = irq_get_interrupt_parent(dev, &gic);
+ if (ret) {
+ log_err("%s: Failed to find interrupt parent for %s\n",
+ __func__, dev->name);
+ return -ENODEV;
+ }
+
+ addr_index = 1;
+
+ if (device_is_compatible(gic, "arm,gic-v3")) {
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_gicr_base = addr;
+ }
+
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_phys_base = addr;
+
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_gich = addr;
+
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_gicv = addr;
+
+ ret = irq_get_by_index(gic, 0, &req_irq);
+ if (!ret)
+ gicc_vgic_maint_irq = req_irq.id;
+
+ gicc_mpidr = dev_read_u64_default(dev, "reg", 0);
+ if (!gicc_mpidr)
+ gicc_mpidr = dev_read_u32_default(dev, "reg", 0);
+
+ /*
+ * gicc_vgic_maint_irq and gicc_gicv are the same for every CPU
+ */
+ gicc = ctx->current;
+ acpi_write_madt_gicc(gicc,
+ dev_seq(dev),
+ gicc_perf_gsiv, /* FIXME: needs a PMU driver */
+ gicc_phys_base,
+ gicc_gicv,
+ gicc_gich,
+ gicc_vgic_maint_irq,
+ gicc_gicr_base,
+ gicc_mpidr,
+ 0); /* FIXME: Not defined in DT */
+
+ acpi_inc(ctx, gicc->length);
+
+ return 0;
+}
+
+struct acpi_ops armv8_cpu_acpi_ops = {
+ .fill_ssdt = armv8_cpu_fill_ssdt,
+ .fill_madt = armv8_cpu_fill_madt,
+};
+#endif
+
+static const struct cpu_ops cpu_ops = {
+ .get_count = armv8_cpu_get_count,
+ .get_desc = armv8_cpu_get_desc,
+ .get_info = armv8_cpu_get_info,
+};
+
+static const struct udevice_id cpu_ids[] = {
+ { .compatible = "arm,armv8" },
+ {}
+};
+
+U_BOOT_DRIVER(arm_cpu) = {
+ .name = "arm-cpu",
+ .id = UCLASS_CPU,
+ .of_match = cpu_ids,
+ .ops = &cpu_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+ ACPI_OPS_PTR(&armv8_cpu_acpi_ops)
+};
diff --git a/drivers/cpu/armv8_cpu.h b/drivers/cpu/armv8_cpu.h
new file mode 100644
index 00000000000..48c705e98de
--- /dev/null
+++ b/drivers/cpu/armv8_cpu.h
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 9elements GmbH
+ */
+#include <dm/acpi.h>
+#include <dm/device.h>
+
+#ifndef _ARMV8_CPU_H_
+#define _ARMV8_CPU_H_
+
+/**
+ * armv8_cpu_fill_ssdt() - Fill the SSDT
+ * Parses the FDT and writes the SSDT nodes.
+ *
+ * @dev: cpu device to generate ACPI tables for
+ * @ctx: ACPI context pointer
+ * @return: 0 if OK, or a negative error code.
+ */
+int armv8_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx);
+
+/**
+ * armv8_cpu_fill_madt() - Fill the MADT
+ * Parses the FDT and writes the MADT subtables.
+ *
+ * @dev: cpu device to generate ACPI tables for
+ * @ctx: ACPI context pointer
+ * @return: 0 if OK, or a negative error code.
+ */
+int armv8_cpu_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx);
+
+#endif \ No newline at end of file
diff --git a/drivers/cpu/bcm283x_cpu.c b/drivers/cpu/bcm283x_cpu.c
new file mode 100644
index 00000000000..59a7b142c95
--- /dev/null
+++ b/drivers/cpu/bcm283x_cpu.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 9elements GmbH
+ */
+
+#include <cpu.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <fdt_support.h>
+#include <acpi/acpigen.h>
+#include <asm/armv8/cpu.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/global_data.h>
+#include <asm/system.h>
+#include <asm-generic/sections.h>
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include "armv8_cpu.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct bcm_plat {
+ u64 release_addr;
+};
+
+static int cpu_bcm_get_desc(const struct udevice *dev, char *buf, int size)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+ const char *name;
+
+ if (size < 32)
+ return -ENOSPC;
+
+ if (device_is_compatible(dev, "arm,cortex-a53"))
+ name = "A53";
+ else if (device_is_compatible(dev, "arm,cortex-a72"))
+ name = "A72";
+ else
+ name = "?";
+
+ snprintf(buf, size, "Broadcom Cortex-%s at %u MHz\n",
+ name, plat->timebase_freq);
+
+ return 0;
+}
+
+static int cpu_bcm_get_info(const struct udevice *dev, struct cpu_info *info)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+
+ info->cpu_freq = plat->timebase_freq * 1000;
+ info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
+
+ return 0;
+}
+
+static int cpu_bcm_get_count(const struct udevice *dev)
+{
+ return uclass_id_count(UCLASS_CPU);
+}
+
+static int cpu_bcm_get_vendor(const struct udevice *dev, char *buf, int size)
+{
+ snprintf(buf, size, "Broadcom");
+
+ return 0;
+}
+
+static int cpu_bcm_is_current(struct udevice *dev)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+
+ if (plat->cpu_id == (read_mpidr() & 0xffff))
+ return 1;
+
+ return 0;
+}
+
+/**
+ * bcm_cpu_on - Releases the secondary CPU from it's spintable
+ *
+ * Write the CPU's spintable mailbox and let the CPU enter U-Boot.
+ *
+ * @dev: Device to start
+ * @return: zero on success or error code on failure.
+ */
+static int bcm_cpu_on(struct udevice *dev)
+{
+ struct bcm_plat *plat = dev_get_plat(dev);
+ ulong *start_address;
+
+ if (plat->release_addr == ~0ULL)
+ return -ENODATA;
+
+ start_address = map_physmem(plat->release_addr, sizeof(uintptr_t), MAP_NOCACHE);
+
+ /* Point secondary CPU to U-Boot entry */
+ *start_address = (uintptr_t)_start;
+
+ /* Make sure the other CPUs see the written start address */
+ if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+ flush_dcache_all();
+
+ /* Send an event to wake up the secondary CPU. */
+ asm("dsb ishst\n"
+ "sev");
+
+ unmap_physmem(start_address, MAP_NOCACHE);
+
+ return 0;
+}
+
+static const struct cpu_ops cpu_bcm_ops = {
+ .get_desc = cpu_bcm_get_desc,
+ .get_info = cpu_bcm_get_info,
+ .get_count = cpu_bcm_get_count,
+ .get_vendor = cpu_bcm_get_vendor,
+ .is_current = cpu_bcm_is_current,
+};
+
+static const struct udevice_id cpu_bcm_ids[] = {
+ { .compatible = "arm,cortex-a53" }, /* RPi 3 */
+ { .compatible = "arm,cortex-a72" }, /* RPi 4 */
+ { }
+};
+
+static int bcm_cpu_bind(struct udevice *dev)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+
+ plat->cpu_id = dev_read_addr(dev);
+
+ return 0;
+}
+
+/**
+ * bcm_cpu_of_to_plat - Gather spin-table release address
+ *
+ * Read the spin-table release address to allow all seconary CPUs to enter
+ * U-Boot when necessary.
+ *
+ * @dev: Device to start
+ */
+static int bcm_cpu_of_to_plat(struct udevice *dev)
+{
+ struct bcm_plat *plat = dev_get_plat(dev);
+ const char *prop;
+
+ if (CONFIG_IS_ENABLED(ARMV8_MULTIENTRY)) {
+ plat->release_addr = ~0ULL;
+
+ prop = dev_read_string(dev, "enable-method");
+ if (!prop || strcmp(prop, "spin-table"))
+ return -ENODEV;
+
+ plat->release_addr = dev_read_u64_default(dev, "cpu-release-addr", ~0ULL);
+
+ if (plat->release_addr == ~0ULL)
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int bcm_cpu_probe(struct udevice *dev)
+{
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+ struct clk clk;
+ int ret;
+
+ /* Get a clock if it exists */
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (!ret) {
+ ret = clk_enable(&clk);
+ if (ret && (ret != -ENOSYS || ret != -EOPNOTSUPP))
+ return ret;
+ ret = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+ plat->timebase_freq = ret;
+ }
+
+ /*
+ * The armstub holds the secondary CPUs in a spinloop. When
+ * ARMV8_MULTIENTRY is enabled release the secondary CPUs and
+ * let them enter U-Boot as well.
+ */
+ if (CONFIG_IS_ENABLED(ARMV8_MULTIENTRY)) {
+ ret = bcm_cpu_on(dev);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+struct acpi_ops bcm283x_cpu_acpi_ops = {
+ .fill_ssdt = armv8_cpu_fill_ssdt,
+ .fill_madt = armv8_cpu_fill_madt,
+};
+
+U_BOOT_DRIVER(cpu_bcm_drv) = {
+ .name = "bcm283x_cpu",
+ .id = UCLASS_CPU,
+ .of_match = cpu_bcm_ids,
+ .ops = &cpu_bcm_ops,
+ .probe = bcm_cpu_probe,
+ .bind = bcm_cpu_bind,
+ .of_to_plat = bcm_cpu_of_to_plat,
+ .plat_auto = sizeof(struct bcm_plat),
+ ACPI_OPS_PTR(&bcm283x_cpu_acpi_ops)
+};
diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c
index 79eb7c200dc..ac778593c96 100644
--- a/drivers/misc/irq-uclass.c
+++ b/drivers/misc/irq-uclass.c
@@ -62,6 +62,40 @@ int irq_read_and_clear(struct irq *irq)
return ops->read_and_clear(irq);
}
+int irq_get_interrupt_parent(const struct udevice *dev,
+ struct udevice **interrupt_parent)
+{
+ struct ofnode_phandle_args phandle_args;
+ struct udevice *irq = NULL;
+ ofnode node;
+ int ret;
+
+ if (!dev || !interrupt_parent)
+ return -EINVAL;
+
+ *interrupt_parent = NULL;
+
+ node = dev_ofnode(dev);
+ if (!ofnode_valid(node))
+ return -EINVAL;
+
+ while (ofnode_valid(node)) {
+ ret = ofnode_parse_phandle_with_args(node, "interrupt-parent",
+ NULL, 0, 0, &phandle_args);
+ if (!ret && !device_get_global_by_ofnode(phandle_args.node, &irq))
+ break;
+ node = ofnode_get_parent(node);
+ }
+
+ if (!irq) {
+ log_err("Cannot find an interrupt parent for device %s\n", dev->name);
+ return -ENODEV;
+ }
+ *interrupt_parent = irq;
+
+ return 0;
+}
+
#if CONFIG_IS_ENABLED(OF_PLATDATA)
int irq_get_by_phandle(struct udevice *dev, const struct phandle_2_arg *cells,
struct irq *irq)
@@ -142,10 +176,40 @@ err:
int irq_get_by_index(struct udevice *dev, int index, struct irq *irq)
{
struct ofnode_phandle_args args;
- int ret;
+ struct udevice *interrupt_parent;
+ int ret, size, i;
+ const __be32 *list;
+ u32 count;
ret = dev_read_phandle_with_args(dev, "interrupts-extended",
"#interrupt-cells", 0, index, &args);
+ if (ret) {
+ list = dev_read_prop(dev, "interrupts", &size);
+ if (!list)
+ return -ENOENT;
+
+ ret = irq_get_interrupt_parent(dev, &interrupt_parent);
+ if (ret)
+ return -ENODEV;
+ args.node = dev_ofnode(interrupt_parent);
+
+ if (dev_read_u32(interrupt_parent, "#interrupt-cells", &count)) {
+ log_err("%s: could not get #interrupt-cells for %s\n",
+ __func__, dev->name);
+ return -ENOENT;
+ }
+
+ if (index * count >= size / sizeof(*list))
+ return -ENOENT;
+ if (count > OF_MAX_PHANDLE_ARGS)
+ count = OF_MAX_PHANDLE_ARGS;
+ args.args_count = count;
+ for (i = 0; i < count; i++)
+ args.args[i] = be32_to_cpup(&list[index * count + i]);
+
+ return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
+ "interrupts", index, irq);
+ }
return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
"interrupts-extended", index > 0, irq);
diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index f978c64365c..f089c48f028 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -12,6 +12,7 @@
* Copyright (C) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
*/
+#include <asm/arch/acpi/bcm2711.h>
#include <errno.h>
#include <dm.h>
#include <dm/ofnode.h>
@@ -21,88 +22,6 @@
#include <linux/log2.h>
#include <linux/iopoll.h>
-/* Offset of the mandatory PCIe capability config registers */
-#define BRCM_PCIE_CAP_REGS 0x00ac
-
-/* The PCIe controller register offsets */
-#define PCIE_RC_CFG_VENDOR_SPECIFIC_REG1 0x0188
-#define VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
-#define VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN 0x0
-
-#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
-#define CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
-
-#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc
-#define PCIE_RC_CFG_PRIV1_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_MEM_WIN0_LO(win) \
- PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + ((win) * 4)
-
-#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
-#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_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_MSI_INTR2_CLR 0x4508
-#define PCIE_MSI_INTR2_MASK_SET 0x4510
-
-#define PCIE_EXT_CFG_DATA 0x8000
-
-#define PCIE_EXT_CFG_INDEX 0x9000
-
-#define PCIE_RGR1_SW_INIT_1 0x9210
-#define RGR1_SW_INIT_1_PERST_MASK 0x1
-#define RGR1_SW_INIT_1_INIT_MASK 0x2
-
/* PCIe parameters */
#define BRCM_NUM_PCIE_OUT_WINS 4
@@ -447,7 +366,7 @@ static int brcm_pcie_probe(struct udevice *dev)
* This will need to be changed when support for other SoCs is added.
*/
setbits_le32(base + PCIE_RGR1_SW_INIT_1,
- RGR1_SW_INIT_1_INIT_MASK | RGR1_SW_INIT_1_PERST_MASK);
+ PCIE_RGR1_SW_INIT_1_INIT_MASK | PCIE_RGR1_SW_INIT_1_PERST_MASK);
/*
* The delay is a safety precaution to preclude the reset signal
* from looking like a glitch.
@@ -455,7 +374,7 @@ static int brcm_pcie_probe(struct udevice *dev)
udelay(100);
/* Take the bridge out of reset */
- clrbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
+ clrbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
clrbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
@@ -508,7 +427,7 @@ static int brcm_pcie_probe(struct udevice *dev)
/* Unassert the fundamental reset */
clrbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1,
- RGR1_SW_INIT_1_PERST_MASK);
+ PCIE_RGR1_SW_INIT_1_PERST_MASK);
/*
* Wait for 100ms after PERST# deassertion; see PCIe CEM specification
@@ -552,7 +471,7 @@ static int brcm_pcie_probe(struct udevice *dev)
* a PCIe-PCIe bridge (the default setting is to be EP mode).
*/
clrsetbits_le32(base + PCIE_RC_CFG_PRIV1_ID_VAL3,
- CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK, 0x060400);
+ PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK, 0x060400);
if (pcie->ssc) {
ret = brcm_pcie_set_ssc(pcie->base);
@@ -570,8 +489,8 @@ static int brcm_pcie_probe(struct udevice *dev)
nlw, ssc_good ? "(SSC)" : "(!SSC)");
/* PCIe->SCB endian mode for BAR */
- clrsetbits_le32(base + PCIE_RC_CFG_VENDOR_SPECIFIC_REG1,
- VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK,
+ clrsetbits_le32(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1,
+ PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK,
VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN);
/*
@@ -584,7 +503,7 @@ static int brcm_pcie_probe(struct udevice *dev)
* let's instead just unadvertise ASPM support.
*/
clrbits_le32(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY,
- PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
+ LINK_CAPABILITY_ASPM_SUPPORT_MASK);
return 0;
}
@@ -595,14 +514,14 @@ static int brcm_pcie_remove(struct udevice *dev)
void __iomem *base = pcie->base;
/* Assert fundamental reset */
- setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_PERST_MASK);
+ setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_PERST_MASK);
/* Turn off SerDes */
setbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
/* Shutdown bridge */
- setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
+ setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
return 0;
}
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 80c35963b8f..e6bf0c2935b 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -19,6 +19,7 @@
#include <watchdog.h>
#include <asm/io.h>
#include <serial.h>
+#include <spl.h>
#include <dm/device_compat.h>
#include <dm/platform_data/serial_pl01x.h>
#include <linux/compiler.h>
@@ -272,6 +273,28 @@ __weak struct serial_device *default_serial_console(void)
return &pl01x_serial_drv;
}
#else
+
+static int pl01x_serial_getinfo(struct udevice *dev,
+ struct serial_device_info *info)
+{
+ struct pl01x_serial_plat *plat = dev_get_plat(dev);
+
+ /* save code size */
+ if (!not_xpl())
+ return -ENOSYS;
+
+ info->type = SERIAL_CHIP_PL01X;
+ info->addr_space = SERIAL_ADDRESS_SPACE_MEMORY;
+ info->addr = plat->base;
+ info->size = 0x1000;
+ info->reg_width = 4;
+ info->reg_shift = 2;
+ info->reg_offset = 0;
+ info->clock = plat->clock;
+
+ return 0;
+}
+
int pl01x_serial_setbrg(struct udevice *dev, int baudrate)
{
struct pl01x_serial_plat *plat = dev_get_plat(dev);
@@ -341,6 +364,7 @@ static const struct dm_serial_ops pl01x_serial_ops = {
.pending = pl01x_serial_pending,
.getc = pl01x_serial_getc,
.setbrg = pl01x_serial_setbrg,
+ .getinfo = pl01x_serial_getinfo,
};
#if CONFIG_IS_ENABLED(OF_REAL)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 6e10b629a3c..bb5893d56db 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -68,6 +68,14 @@ config USB_XHCI_MVEBU
SoCs, which includes Armada8K, Armada3700 and other Armada
family SoCs.
+config USB_XHCI_GENERIC
+ bool "Generic SoC USB 3.0 support"
+ depends on OF_CONTROL
+ default n
+ help
+ Choose this option to add support for USB 3.0 driver for SoCs
+ that do not need platform specific code, like on emulated targets.
+
config USB_XHCI_OCTEON
bool "Support for Marvell Octeon family on-chip xHCI USB controller"
depends on ARCH_OCTEON
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 792956e647a..301bb9fdee1 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o
obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk.o
obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
+obj-$(CONFIG_USB_XHCI_GENERIC) += xhci-generic.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
obj-$(CONFIG_USB_XHCI_RCAR) += xhci-rcar.o
diff --git a/drivers/usb/host/xhci-generic.c b/drivers/usb/host/xhci-generic.c
new file mode 100644
index 00000000000..355d4883176
--- /dev/null
+++ b/drivers/usb/host/xhci-generic.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 9elements GmbH
+ *
+ * GENERIC USB HOST xHCI Controller
+ */
+#include <dm.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <usb.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <usb/xhci.h>
+
+struct generic_xhci_plat {
+ fdt_addr_t hcd_base;
+};
+
+/**
+ * Contains pointers to register base addresses
+ * for the usb controller.
+ */
+struct generic_xhci {
+ struct xhci_ctrl ctrl; /* Needs to come first in this struct! */
+ struct usb_plat usb_plat;
+ struct xhci_hccr *hcd;
+};
+
+static int xhci_usb_probe(struct udevice *dev)
+{
+ struct generic_xhci_plat *plat = dev_get_plat(dev);
+ struct generic_xhci *ctx = dev_get_priv(dev);
+ struct xhci_hcor *hcor;
+ int len;
+
+ ctx->hcd = (struct xhci_hccr *)phys_to_virt(plat->hcd_base);
+ len = HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase));
+ hcor = (struct xhci_hcor *)((uintptr_t)ctx->hcd + len);
+
+ return xhci_register(dev, ctx->hcd, hcor);
+}
+
+static int xhci_usb_of_to_plat(struct udevice *dev)
+{
+ struct generic_xhci_plat *plat = dev_get_plat(dev);
+
+ /*
+ * Get the base address for XHCI controller from the device node
+ */
+ plat->hcd_base = dev_read_addr(dev);
+ if (plat->hcd_base == FDT_ADDR_T_NONE) {
+ dev_dbg(dev, "Can't get the XHCI register base address\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id xhci_usb_ids[] = {
+ { .compatible = "generic-xhci" },
+ { }
+};
+
+U_BOOT_DRIVER(usb_xhci) = {
+ .name = "xhci_generic",
+ .id = UCLASS_USB,
+ .of_match = xhci_usb_ids,
+ .of_to_plat = xhci_usb_of_to_plat,
+ .probe = xhci_usb_probe,
+ .remove = xhci_deregister,
+ .ops = &xhci_usb_ops,
+ .plat_auto = sizeof(struct generic_xhci_plat),
+ .priv_auto = sizeof(struct generic_xhci),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h
index 15fd61a51d7..b8b1f1338c6 100644
--- a/include/acpi/acpi_table.h
+++ b/include/acpi/acpi_table.h
@@ -290,7 +290,8 @@ struct __packed acpi_fadt {
#define ACPI_MADT_REV_ACPI_3_0 2
#define ACPI_MADT_REV_ACPI_4_0 3
#define ACPI_MADT_REV_ACPI_5_0 3
-#define ACPI_MADT_REV_ACPI_6_0 5
+#define ACPI_MADT_REV_ACPI_6_2 4
+#define ACPI_MADT_REV_ACPI_6_3 5
#define ACPI_MCFG_REV_ACPI_3_0 1
@@ -342,7 +343,10 @@ enum acpi_apic_types {
ACPI_APIC_LX2APIC, /* Processor local x2APIC */
ACPI_APIC_LX2APIC_NMI, /* Local x2APIC NMI */
ACPI_APIC_GICC, /* Generic Interrupt Ctlr CPU i/f */
- ACPI_APIC_GICD /* Generic Interrupt Ctlr Distributor */
+ ACPI_APIC_GICD, /* Generic Interrupt Ctlr Distributor */
+ ACPI_APIC_MSI_FRAME, /* Generic Interrupt MSI Frame */
+ ACPI_APIC_GICR, /* Generic Interrupt Ctlr Redistributor */
+ ACPI_APIC_ITS, /* Interrupt Translation Service */
};
/* MADT: Processor Local APIC Structure */
@@ -386,20 +390,20 @@ struct __packed acpi_madt_lapic_nmi {
u8 lint; /* Local APIC LINT# */
};
-/* flags for acpi_madr_gicc flags word */
+/* flags for acpi_madt_gicc flags word */
enum {
- ACPI_MADRF_ENABLED = BIT(0),
- ACPI_MADRF_PERF = BIT(1),
- ACPI_MADRF_VGIC = BIT(2),
+ ACPI_MADTF_ENABLED = BIT(0),
+ ACPI_MADTF_PERF = BIT(1),
+ ACPI_MADTF_VGIC = BIT(2),
};
/**
- * struct __packed acpi_madr_gicc - GIC CPU interface (type 0xb)
+ * struct __packed acpi_madt_gicc - GIC CPU interface (type 0xb)
*
* This holds information about the Generic Interrupt Controller (GIC) CPU
* interface. See ACPI Spec v6.3 section 5.2.12.14
*/
-struct acpi_madr_gicc {
+struct acpi_madt_gicc {
u8 type;
u8 length;
u16 reserved;
@@ -421,12 +425,12 @@ struct acpi_madr_gicc {
} __packed;
/**
- * struct __packed acpi_madr_gicc - GIC distributor (type 0xc)
+ * struct __packed acpi_madt_gicc - GIC distributor (type 0xc)
*
* This holds information about the Generic Interrupt Controller (GIC)
* Distributor interface. See ACPI Spec v6.3 section 5.2.12.15
*/
-struct acpi_madr_gicd {
+struct acpi_madt_gicd {
u8 type;
u8 length;
u16 reserved;
@@ -437,6 +441,35 @@ struct acpi_madr_gicd {
u8 reserved3[3];
} __packed;
+/**
+ * struct __packed acpi_madt_gicr - GIC Redistributor (type 0xe)
+ *
+ * This holds information about the Generic Interrupt Controller (GIC)
+ * Redistributor interface. See ACPI Spec v6.3 section 5.2.12.17
+ */
+struct acpi_madt_gicr {
+ u8 type;
+ u8 length;
+ u16 reserved;
+ u64 discovery_range_base_address;
+ u32 discovery_range_length;
+} __packed;
+
+/**
+ * struct __packed acpi_madt_its - GIC Interrupt Translation Service (type 0xf)
+ *
+ * This holds information about the Interrupt Translation Service (ITS)
+ * Structure. See ACPI Spec v6.3 section 5.2.12.18
+ */
+struct acpi_madt_its {
+ u8 type;
+ u8 length;
+ u16 reserved;
+ u32 gic_its_id;
+ u64 physical_base_address;
+ u32 reserved2;
+} __packed;
+
/* MCFG (PCI Express MMIO config space BAR description table) */
struct acpi_mcfg {
struct acpi_table_header header;
@@ -707,6 +740,8 @@ struct acpi_gtdt {
u32 virt_el2_flags;
} __packed;
+#define GTDT_FLAG_INT_ACTIVE_LOW BIT(1)
+
/**
* struct acpi_bgrt - Boot Graphics Resource Table (BGRT)
*
@@ -797,6 +832,117 @@ struct acpi_pptt_cache {
u16 line_size;
} __packed;
+/** IORT - IO Remapping Table revision 6
+ * Document number: ARM DEN 0049E.e, Sep 2022
+ */
+struct acpi_table_iort {
+ struct acpi_table_header header;
+ u32 node_count;
+ u32 node_offset;
+ u32 reserved;
+} __packed;
+
+/*
+ * IORT subtables
+ */
+struct acpi_iort_node {
+ u8 type;
+ u16 length;
+ u8 revision;
+ u32 identifier;
+ u32 mapping_count;
+ u32 mapping_offset;
+ char node_data[];
+} __packed;
+
+/* Values for subtable Type above */
+enum acpi_iort_node_type {
+ ACPI_IORT_NODE_ITS_GROUP = 0x00,
+ ACPI_IORT_NODE_NAMED_COMPONENT = 0x01,
+ ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02,
+ ACPI_IORT_NODE_SMMU = 0x03,
+ ACPI_IORT_NODE_SMMU_V3 = 0x04,
+ ACPI_IORT_NODE_PMCG = 0x05,
+ ACPI_IORT_NODE_RMR = 0x06,
+};
+
+/* ITS Group revision 1 */
+struct acpi_iort_its_group {
+ u32 its_count;
+ u32 identifiers[]; /* GIC ITS identifier array */
+} __packed;
+
+/* PCI root complex node revision 2 */
+struct acpi_iort_rc {
+ u64 mem_access_properties;
+ u32 ats_attributes;
+ u32 pci_segment_number;
+ u8 memory_address_size_limit;
+ u8 reserved[3];
+} __packed;
+
+/* SMMUv3 revision 5 */
+struct acpi_iort_smmu_v3 {
+ u64 base_address; /* SMMUv3 base address */
+ u32 flags;
+ u32 reserved;
+ u64 vatos_address;
+ u32 model;
+ u32 event_gsiv;
+ u32 pri_gsiv;
+ u32 gerr_gsiv;
+ u32 sync_gsiv;
+ u32 pxm;
+ u32 id_mapping_index;
+} __packed;
+
+/* Masks for Flags field above */
+#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE (1)
+#define ACPI_IORT_SMMU_V3_HTTU_OVERRIDE (3 << 1)
+#define ACPI_IORT_SMMU_V3_PXM_VALID (1 << 3)
+#define ACPI_IORT_SMMU_V3_DEVICEID_VALID (1 << 4)
+
+struct acpi_iort_id_mapping {
+ u32 input_base; /* Lowest value in input range */
+ u32 id_count; /* Number of IDs */
+ u32 output_base; /* Lowest value in output range */
+ u32 output_reference; /* A reference to the output node */
+ u32 flags;
+} __packed;
+
+/* Masks for Flags field above for IORT subtable */
+#define ACPI_IORT_ID_SINGLE_MAPPING (1)
+
+/* Named Component revision 4 */
+struct acpi_iort_named_component {
+ u32 node_flags;
+ u64 memory_properties; /* Memory access properties */
+ u8 memory_address_limit; /* Memory address size limit */
+ char device_name[]; /* Path of namespace object */
+} __packed;
+
+/* Masks for Flags field above */
+#define ACPI_IORT_NC_STALL_SUPPORTED (1)
+#define ACPI_IORT_NC_PASID_BITS (31 << 1)
+
+struct acpi_iort_root_complex {
+ u64 memory_properties; /* Memory access properties */
+ u32 ats_attribute;
+ u32 pci_segment_number;
+ u8 memory_address_limit;/* Memory address size limit */
+ u16 pasid_capabilities; /* PASID Capabilities */
+ u8 reserved; /* Reserved, must be zero */
+ u32 flags; /* Flags */
+} __packed;
+
+/* Masks for ats_attribute field above */
+#define ACPI_IORT_ATS_SUPPORTED (1) /* The root complex ATS support */
+#define ACPI_IORT_PRI_SUPPORTED (1 << 1) /* The root complex PRI support */
+#define ACPI_IORT_PASID_FWD_SUPPORTED (1 << 2) /* The root complex PASID forward support */
+
+/* Masks for pasid_capabilities field above */
+#define ACPI_IORT_PASID_MAX_WIDTH (0x1F) /* Bits 0-4 */
+
/* Tables defined/reserved by ACPI and generated by U-Boot */
enum acpi_tables {
ACPITAB_BERT,
@@ -806,12 +952,14 @@ enum acpi_tables {
ACPITAB_ECDT,
ACPITAB_FACS,
ACPITAB_FADT,
+ ACPITAB_GTDT,
ACPITAB_HEST,
ACPITAB_HPET,
ACPITAB_IVRS,
ACPITAB_MADT,
ACPITAB_MCFG,
ACPITAB_NHLT,
+ ACPITAB_PPTT,
ACPITAB_RSDP,
ACPITAB_RSDT,
ACPITAB_SLIT,
@@ -847,6 +995,19 @@ int acpi_get_table_revision(enum acpi_tables table);
int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags);
/**
+ * acpi_create_mcfg_mmconfig() - Create a MCFG table entry
+ *
+ * @mmconfig: Place to put the table
+ * @base: Base address of the ECAM space
+ * @seg_nr: PCI segment number
+ * @start: PCI bus start number
+ * @end: PCI bus end number
+ * Return: size of data written in bytes
+ */
+int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
+ u16 seg_nr, u8 start, u8 end);
+
+/**
* acpi_create_dbg2() - Create a DBG2 table
*
* This table describes how to access the debug UART
@@ -914,6 +1075,17 @@ static inline int acpi_add_fadt(struct acpi_ctx *ctx, struct acpi_fadt *fadt)
}
/**
+ * acpi_write_dbg2_pci_uart() - Write out a DBG2 table
+ *
+ * @ctx: Current ACPI context
+ * @dev: Debug UART device to describe
+ * @access_size: Access size for UART (e.g. ACPI_ACCESS_SIZE_DWORD_ACCESS)
+ * Return: 0 if OK, -ve on error
+ */
+int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
+ uint access_size);
+
+/**
* acpi_write_rsdp() - Write out an RSDP indicating where the ACPI tables are
*
* @rsdp: Address to write RSDP
@@ -944,6 +1116,138 @@ void acpi_fill_header(struct acpi_table_header *header, char *signature);
int acpi_fill_csrt(struct acpi_ctx *ctx);
/**
+ * acpi_fill_fadt() - Fill out the body of the FADT
+ *
+ * Must be implemented in SoC specific code or in mainboard code.
+ *
+ * @fadt: Pointer to FADT to update
+ */
+void acpi_fill_fadt(struct acpi_fadt *fadt);
+
+/**
+ * acpi_fill_iort() - Fill out the body of the IORT table
+ *
+ * Should be implemented in SoC specific code.
+ *
+ * @ctx: ACPI context to write to
+ * @offset: Offset from the start of the IORT
+ */
+int acpi_fill_iort(struct acpi_ctx *ctx);
+
+/**
+ * acpi_iort_add_its_group() - Add ITS group node to IORT table
+ *
+ * Called by SoC specific code within acpi_fill_iort().
+ *
+ * @ctx: ACPI context to write to
+ * @its_count: Elements in identifiers
+ * @identifiers: The array of ITS identifiers. These IDs must match the value
+ * used in the Multiple APIC Description Table (MADT) GIC ITS
+ * structure for each relevant ITS unit.
+ * @return Offset of table within parent
+ */
+int acpi_iort_add_its_group(struct acpi_ctx *ctx,
+ const u32 its_count,
+ const u32 *identifiers);
+
+/**
+ * acpi_iort_add_named_component() - Add named component to IORT table
+ *
+ * Called by SoC specific code within acpi_fill_iort().
+ *
+ * @ctx: ACPI context to write to
+ * @node_flags: Node flags
+ * @memory_properties: Memory properties
+ * @memory_address_limit: Memory address limit
+ * @device_name: ACPI device path
+ * @return Offset of table within parent
+ */
+int acpi_iort_add_named_component(struct acpi_ctx *ctx,
+ const u32 node_flags,
+ const u64 memory_properties,
+ const u8 memory_address_limit,
+ const char *device_name);
+
+/**
+ * acpi_iort_add_rc() - Add PCI root complex node to IORT table
+ *
+ * Called by SoC specific code within acpi_fill_iort().
+ *
+ * @ctx: ACPI context to write to
+ * @mem_access_properties: Memory access properties
+ * @ats_attributes: Support for ATS and its ancillary feature
+ * @pci_segment_number: The PCI segment number, as in MCFG
+ * @memory_address_size_limit: The number of address bits, starting from LSB
+ * @num_mappings: Number of elements in map
+ * @map: ID mappings for this node
+ * @return Offset of table within parent
+ */
+int acpi_iort_add_rc(struct acpi_ctx *ctx,
+ const u64 mem_access_properties,
+ const u32 ats_attributes,
+ const u32 pci_segment_number,
+ const u8 memory_address_size_limit,
+ const int num_mappings,
+ const struct acpi_iort_id_mapping *map);
+
+/**
+ * acpi_iort_add_smmu_v3() - Add PCI root complex node to IORT table
+ *
+ * Called by SoC specific code within acpi_fill_iort().
+ *
+ * @ctx: ACPI context to write to
+ * @base_address: Base address of SMMU
+ * @flags: SMMUv3 flags
+ * @vatos_address: Optional, set to zero if not supported
+ * @model: Model ID
+ * @event_gsiv: GSIV of the Event interrupt if SPI based
+ * @pri_gsiv: GSIV of the PRI interrupt if SPI based
+ * @gerr_gsiv: GSIV of the GERR interrupt if GSIV based
+ * @sync_gsiv: TGSIV of the Sync interrupt if GSIV based
+ * @pxm: Proximity Domain
+ * @id_mapping_index: If all the SMMU control interrupts are GSIV based,
+ * this field is ignored. Index into the array of ID
+ * mapping otherwise.
+ * @num_mappings: Number of elements in map
+ * @map: ID mappings for this node
+ * @return Offset of table within parent
+ */
+int acpi_iort_add_smmu_v3(struct acpi_ctx *ctx,
+ const u64 base_address,
+ const u32 flags,
+ const u64 vatos_address,
+ const u32 model,
+ const u32 event_gsiv,
+ const u32 pri_gsiv,
+ const u32 gerr_gsiv,
+ const u32 sync_gsiv,
+ const u32 pxm,
+ const u32 id_mapping_index,
+ const int num_mappings,
+ const struct acpi_iort_id_mapping *map);
+
+/**
+ * acpi_fill_madt() - Fill out the body of the MADT
+ *
+ * Must be implemented in SoC specific code.
+ *
+ * @madt: The MADT to update
+ * @ctx: ACPI context to write MADT sub-tables to
+ * @return Pointer to the end of tables, where the next tables can be written
+ */
+void *acpi_fill_madt(struct acpi_madt *madt, struct acpi_ctx *ctx);
+
+/**
+ * acpi_write_park() - Installs the ACPI parking protocol.
+ *
+ * Sets up the ACPI parking protocol and installs the spinning code for
+ * secondary CPUs.
+ *
+ * @madt: The MADT to update
+ */
+void acpi_write_park(struct acpi_madt *madt);
+
+/**
* acpi_get_rsdp_addr() - get ACPI RSDP table address
*
* This routine returns the ACPI RSDP table address in the system memory.
diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h
index 3aa94d70b9c..16df85b9c1b 100644
--- a/include/acpi/acpigen.h
+++ b/include/acpi/acpigen.h
@@ -833,6 +833,7 @@ void acpigen_write_dsm_end(struct acpi_ctx *ctx);
*
* This emits a Processor package header with the required information. The
* caller must complete the information and call acpigen_pop_len() at the end
+ * Deprecated since ACPI 6.0.
*
* @ctx: ACPI context pointer
* @cpuindex: CPU number
@@ -843,6 +844,17 @@ void acpigen_write_processor(struct acpi_ctx *ctx, uint cpuindex,
u32 pblock_addr, uint pblock_len);
/**
+ * acpigen_write_processor_device() - Write a Processor device
+ *
+ * Write a device with _HID ACPI0007 identifying a processor.
+ * Replacement for the Processor OpCode.
+ *
+ * @ctx: ACPI context pointer
+ * @cpuindex: CPU number
+ */
+void acpigen_write_processor_device(struct acpi_ctx *ctx, uint cpuindex);
+
+/**
* acpigen_write_processor_package() - Write a package containing the processors
*
* The package containins the name of each processor in the SoC
diff --git a/include/bloblist.h b/include/bloblist.h
index b0706b5637d..ff32d3fecfd 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -110,6 +110,7 @@ enum bloblist_tag_t {
BLOBLISTT_ACPI_TABLES = 4,
BLOBLISTT_TPM_EVLOG = 5,
BLOBLISTT_TPM_CRB_BASE = 6,
+ BLOBLISTT_ACPI_PP = 7,
/* Standard area to allocate blobs used across firmware components */
BLOBLISTT_AREA_FIRMWARE = 0x10,
diff --git a/include/configs/qemu-sbsa.h b/include/configs/qemu-sbsa.h
new file mode 100644
index 00000000000..aff78160e12
--- /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 */
diff --git a/include/dm/acpi.h b/include/dm/acpi.h
index 3adfe217678..d6bc0c099ad 100644
--- a/include/dm/acpi.h
+++ b/include/dm/acpi.h
@@ -147,6 +147,22 @@ struct acpi_ops {
int (*write_tables)(const struct udevice *dev, struct acpi_ctx *ctx);
/**
+ * fill_madt() - Generate MADT sub-tables for a device
+ *
+ * This is called to create the MADT table. The method should write out
+ * whatever sub-table is needed by this device. It will end up in the
+ * MADT table.
+ *
+ * Note that this is called 'fill' because the entire contents of the
+ * MADT is build by calling this method on all devices.
+ *
+ * @dev: Device to write
+ * @ctx: ACPI context to use
+ * @return 0 if OK, -ve on error
+ */
+ int (*fill_madt)(const struct udevice *dev, struct acpi_ctx *ctx);
+
+ /**
* fill_ssdt() - Generate SSDT code for a device
*
* This is called to create the SSDT code. The method should write out
@@ -232,6 +248,16 @@ int acpi_copy_name(char *out_name, const char *name);
int acpi_write_dev_tables(struct acpi_ctx *ctx);
/**
+ * acpi_fill_madt_subtbl() - Generate ACPI tables for MADT
+ *
+ * This is called to create the MADT sub-tables for all devices.
+ *
+ * @ctx: ACPI context to use
+ * Return: 0 if OK, -ve on error
+ */
+int acpi_fill_madt_subtbl(struct acpi_ctx *ctx);
+
+/**
* acpi_fill_ssdt() - Generate ACPI tables for SSDT
*
* This is called to create the SSDT code for all devices.
diff --git a/include/irq.h b/include/irq.h
index 5638c10128e..0fbc1a5f485 100644
--- a/include/irq.h
+++ b/include/irq.h
@@ -200,6 +200,20 @@ int irq_restore_polarities(struct udevice *dev);
*/
int irq_read_and_clear(struct irq *irq);
+/**
+ * irq_get_interrupt_parent() - returns the interrupt parent
+ *
+ * Walks the devicetree and returns the interrupt parent's ofnode
+ * for the specified device.
+ *
+ * @dev: device
+ * @interrupt_parent: The interrupt parent's ofnode'
+ * Return: 0 success, or error value
+ *
+ */
+int irq_get_interrupt_parent(const struct udevice *dev,
+ struct udevice **interrupt_parent);
+
struct phandle_2_arg;
/**
* irq_get_by_phandle() - Get an irq by its phandle information (of-platadata)
diff --git a/include/serial.h b/include/serial.h
index eabc49f820f..e5f6d984d28 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -124,6 +124,7 @@ enum serial_stop {
enum serial_chip_type {
SERIAL_CHIP_UNKNOWN = -1,
SERIAL_CHIP_16550_COMPATIBLE,
+ SERIAL_CHIP_PL01X,
};
enum adr_space_type {
diff --git a/lib/Kconfig b/lib/Kconfig
index fc2db747dcc..56ffdfa1839 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -315,6 +315,22 @@ config GENERATE_ACPI_TABLE
by the operating system. It defines platform-independent interfaces
for configuration and power management monitoring.
+config ACPI_PARKING_PROTOCOL
+ bool "Support ACPI parking protocol method"
+ depends on GENERATE_ACPI_TABLE
+ depends on ARMV8_MULTIENTRY
+ depends on BLOBLIST_TABLES
+ default y if !SEC_FIRMWARE_ARMV8_PSCI && !ARMV8_PSCI
+ help
+ Say Y here to support "ACPI parking protocol" enable method
+ for booting Linux.
+
+ To use this feature, you must do:
+ - Bring secondary CPUs into U-Boot proper in a board-specific
+ manner. This must be done *after* relocation. Otherwise, the
+ secondary CPUs will spin in unprotected memory-area because the
+ master CPU protects the relocated spin code.
+
config SPL_TINY_MEMSET
bool "Use a very small memset() in SPL"
depends on SPL
@@ -988,12 +1004,15 @@ menu "System tables"
config BLOBLIST_TABLES
bool "Put tables in a bloblist"
- depends on X86 && BLOBLIST
- help
- Normally tables are placed at address 0xf0000 and can be up to 64KB
- long. With this option, tables are instead placed in the bloblist
- with a pointer from 0xf0000. The size can then be larger and the
- tables can be placed high in memory.
+ depends on BLOBLIST
+ default y if (ARM && EFI_LOADER && GENERATE_ACPI_TABLE)
+ default n
+ help
+ On x86 normally tables are placed at address 0xf0000 and can be up
+ to 64KB long. With this option, tables are instead placed in the
+ bloblist with a pointer from 0xf0000. The size can then be larger
+ and the tables can be placed high in memory.
+ On other architectures the tables are always placed in high memory.
config GENERATE_SMBIOS_TABLE
bool "Generate an SMBIOS (System Management BIOS) table"
diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c
index 6dbfdb22dec..6473d95c102 100644
--- a/lib/acpi/acpi_table.c
+++ b/lib/acpi/acpi_table.c
@@ -5,15 +5,28 @@
* Copyright 2019 Google LLC
*/
-#include <dm.h>
+#include <bloblist.h>
#include <cpu.h>
+#include <dm.h>
+#include <efi_api.h>
+#include <efi_loader.h>
#include <log.h>
#include <mapmem.h>
#include <tables_csum.h>
+#include <serial.h>
#include <version_string.h>
#include <acpi/acpi_table.h>
+#include <acpi/acpi_device.h>
#include <asm/global_data.h>
#include <dm/acpi.h>
+#include <linux/sizes.h>
+#include <linux/log2.h>
+
+enum {
+ TABLE_SIZE = SZ_64K,
+};
+
+DECLARE_GLOBAL_DATA_PTR;
/*
* OEM_REVISION is 32-bit unsigned number. It should be increased only when
@@ -61,9 +74,9 @@ int acpi_get_table_revision(enum acpi_tables table)
{
switch (table) {
case ACPITAB_FADT:
- return ACPI_FADT_REV_ACPI_3_0;
+ return ACPI_FADT_REV_ACPI_6_0;
case ACPITAB_MADT:
- return ACPI_MADT_REV_ACPI_3_0;
+ return ACPI_MADT_REV_ACPI_6_2;
case ACPITAB_MCFG:
return ACPI_MCFG_REV_ACPI_3_0;
case ACPITAB_TCPA:
@@ -105,6 +118,10 @@ int acpi_get_table_revision(enum acpi_tables table)
return 1;
case ACPITAB_SPCR:
return 2;
+ case ACPITAB_PPTT: /* ACPI 6.2: 1 */
+ return 1;
+ case ACPITAB_GTDT: /* ACPI 6.2: 2, ACPI 6.3: 3 */
+ return 2;
default:
return -EINVAL;
}
@@ -151,55 +168,148 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table)
struct acpi_rsdt *rsdt;
struct acpi_xsdt *xsdt;
- /* The RSDT is mandatory while the XSDT is not */
- rsdt = ctx->rsdt;
+ /* On legacy x86 platforms the RSDT is mandatory while the XSDT is not.
+ * On other platforms there might be no memory below 4GiB, thus RSDT is NULL.
+ */
+ if (ctx->rsdt) {
+ rsdt = ctx->rsdt;
+
+ /* This should always be MAX_ACPI_TABLES */
+ entries_num = ARRAY_SIZE(rsdt->entry);
+
+ for (i = 0; i < entries_num; i++) {
+ if (rsdt->entry[i] == 0)
+ break;
+ }
+
+ if (i >= entries_num) {
+ log_err("ACPI: Error: too many tables\n");
+ return -E2BIG;
+ }
+
+ /* Add table to the RSDT */
+ rsdt->entry[i] = nomap_to_sysmem(table);
- /* This should always be MAX_ACPI_TABLES */
- entries_num = ARRAY_SIZE(rsdt->entry);
+ /* Fix RSDT length or the kernel will assume invalid entries */
+ rsdt->header.length = sizeof(struct acpi_table_header) +
+ (sizeof(u32) * (i + 1));
- for (i = 0; i < entries_num; i++) {
- if (rsdt->entry[i] == 0)
- break;
+ /* Re-calculate checksum */
+ rsdt->header.checksum = 0;
+ rsdt->header.checksum = table_compute_checksum((u8 *)rsdt,
+ rsdt->header.length);
}
- if (i >= entries_num) {
- log_err("ACPI: Error: too many tables\n");
- return -E2BIG;
+ if (ctx->xsdt) {
+ /*
+ * And now the same thing for the XSDT. We use the same index as for
+ * now we want the XSDT and RSDT to always be in sync in U-Boot
+ */
+ xsdt = ctx->xsdt;
+
+ /* This should always be MAX_ACPI_TABLES */
+ entries_num = ARRAY_SIZE(xsdt->entry);
+
+ for (i = 0; i < entries_num; i++) {
+ if (xsdt->entry[i] == 0)
+ break;
+ }
+
+ if (i >= entries_num) {
+ log_err("ACPI: Error: too many tables\n");
+ return -E2BIG;
+ }
+
+ /* Add table to the XSDT */
+ xsdt->entry[i] = nomap_to_sysmem(table);
+
+ /* Fix XSDT length */
+ xsdt->header.length = sizeof(struct acpi_table_header) +
+ (sizeof(u64) * (i + 1));
+
+ /* Re-calculate checksum */
+ xsdt->header.checksum = 0;
+ xsdt->header.checksum = table_compute_checksum((u8 *)xsdt,
+ xsdt->header.length);
}
- /* Add table to the RSDT */
- rsdt->entry[i] = nomap_to_sysmem(table);
+ return 0;
+}
- /* Fix RSDT length or the kernel will assume invalid entries */
- rsdt->header.length = sizeof(struct acpi_table_header) +
- (sizeof(u32) * (i + 1));
+int acpi_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_header *header;
+ struct acpi_fadt *fadt;
- /* Re-calculate checksum */
- rsdt->header.checksum = 0;
- rsdt->header.checksum = table_compute_checksum((u8 *)rsdt,
- rsdt->header.length);
+ fadt = ctx->current;
+ header = &fadt->header;
- /*
- * And now the same thing for the XSDT. We use the same index as for
- * now we want the XSDT and RSDT to always be in sync in U-Boot
- */
- xsdt = ctx->xsdt;
+ memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
+
+ acpi_fill_header(header, "FACP");
+ header->length = sizeof(struct acpi_fadt);
+ header->revision = acpi_get_table_revision(ACPITAB_FADT);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
+ memcpy(header->creator_id, ASLC_ID, 4);
+ header->creator_revision = 1;
+ fadt->minor_revision = 2;
- /* Add table to the XSDT */
- xsdt->entry[i] = nomap_to_sysmem(table);
+ fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
+ fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
- /* Fix XSDT length */
- xsdt->header.length = sizeof(struct acpi_table_header) +
- (sizeof(u64) * (i + 1));
+ if (fadt->x_firmware_ctrl < 0x100000000ULL)
+ fadt->firmware_ctrl = fadt->x_firmware_ctrl;
- /* Re-calculate checksum */
- xsdt->header.checksum = 0;
- xsdt->header.checksum = table_compute_checksum((u8 *)xsdt,
- xsdt->header.length);
+ if (fadt->x_dsdt < 0x100000000ULL)
+ fadt->dsdt = fadt->x_dsdt;
+
+ fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
+
+ acpi_fill_fadt(fadt);
+
+ header->checksum = table_compute_checksum(fadt, header->length);
+
+ return acpi_add_fadt(ctx, fadt);
+}
+
+ACPI_WRITER(5fadt, "FADT", acpi_write_fadt, 0);
+
+int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_header *header;
+ struct acpi_madt *madt;
+ void *current;
+
+ madt = ctx->current;
+
+ memset(madt, '\0', sizeof(struct acpi_madt));
+ header = &madt->header;
+
+ /* Fill out header fields */
+ acpi_fill_header(header, "APIC");
+ header->length = sizeof(struct acpi_madt);
+ header->revision = acpi_get_table_revision(ACPITAB_MADT);
+
+ acpi_inc(ctx, sizeof(struct acpi_madt));
+ /* TODO: Get rid of acpi_fill_madt and use driver model */
+ current = acpi_fill_madt(madt, ctx);
+
+ /* (Re)calculate length and checksum */
+ header->length = (uintptr_t)current - (uintptr_t)madt;
+
+ if (IS_ENABLED(CONFIG_ACPI_PARKING_PROTOCOL))
+ acpi_write_park(madt);
+
+ header->checksum = table_compute_checksum((void *)madt, header->length);
+ acpi_add_table(ctx, madt);
+ ctx->current = (void *)madt + madt->header.length;
return 0;
}
+ACPI_WRITER(5madt, "MADT", acpi_write_madt, 0);
+
void acpi_create_dbg2(struct acpi_dbg2_header *dbg2,
int port_type, int port_subtype,
struct acpi_gen_regaddr *address, u32 address_size,
@@ -262,3 +372,451 @@ void acpi_create_dbg2(struct acpi_dbg2_header *dbg2,
header->length = current - (uintptr_t)dbg2;
header->checksum = table_compute_checksum(dbg2, header->length);
}
+
+int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
+ uint access_size)
+{
+ struct acpi_dbg2_header *dbg2 = ctx->current;
+ char path[ACPI_PATH_MAX];
+ struct acpi_gen_regaddr address;
+ u64 addr;
+ int ret;
+
+ if (!device_active(dev)) {
+ log_info("Device not enabled\n");
+ return -EACCES;
+ }
+ /*
+ * PCI devices don't remember their resource allocation information in
+ * U-Boot at present. We assume that MMIO is used for the UART and that
+ * the address space is 32 bytes: ns16550 uses 8 registers of up to
+ * 32-bits each. This is only for debugging so it is not a big deal.
+ */
+ addr = dm_pci_read_bar32(dev, 0);
+ log_debug("UART addr %lx\n", (ulong)addr);
+
+ ret = acpi_device_path(dev, path, sizeof(path));
+ if (ret)
+ return log_msg_ret("path", ret);
+
+ memset(&address, '\0', sizeof(address));
+ address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
+ address.addrl = (uint32_t)addr;
+ address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
+ address.access_size = access_size;
+
+ ret = acpi_device_path(dev, path, sizeof(path));
+ if (ret)
+ return log_msg_ret("path", ret);
+ acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
+ ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
+
+ acpi_inc_align(ctx, dbg2->header.length);
+ acpi_add_table(ctx, dbg2);
+
+ return 0;
+}
+
+static int acpi_write_spcr(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct serial_device_info serial_info = {0};
+ ulong serial_address, serial_offset;
+ struct acpi_table_header *header;
+ struct acpi_spcr *spcr;
+ struct udevice *dev;
+ uint serial_config;
+ uint serial_width;
+ int access_size;
+ int space_id;
+ int ret = -ENODEV;
+
+ spcr = ctx->current;
+ header = &spcr->header;
+
+ memset(spcr, '\0', sizeof(struct acpi_spcr));
+
+ /* Fill out header fields */
+ acpi_fill_header(header, "SPCR");
+ header->length = sizeof(struct acpi_spcr);
+ header->revision = 2;
+
+ /* Read the device once, here. It is reused below */
+ dev = gd->cur_serial_dev;
+ if (dev)
+ ret = serial_getinfo(dev, &serial_info);
+ if (ret)
+ serial_info.type = SERIAL_CHIP_UNKNOWN;
+
+ /* Encode chip type */
+ switch (serial_info.type) {
+ case SERIAL_CHIP_16550_COMPATIBLE:
+ spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
+ break;
+ case SERIAL_CHIP_PL01X:
+ spcr->interface_type = ACPI_DBG2_ARM_PL011;
+ break;
+ case SERIAL_CHIP_UNKNOWN:
+ default:
+ spcr->interface_type = ACPI_DBG2_UNKNOWN;
+ break;
+ }
+
+ /* Encode address space */
+ switch (serial_info.addr_space) {
+ case SERIAL_ADDRESS_SPACE_MEMORY:
+ space_id = ACPI_ADDRESS_SPACE_MEMORY;
+ break;
+ case SERIAL_ADDRESS_SPACE_IO:
+ default:
+ space_id = ACPI_ADDRESS_SPACE_IO;
+ break;
+ }
+
+ serial_width = serial_info.reg_width * 8;
+ serial_offset = serial_info.reg_offset << serial_info.reg_shift;
+ serial_address = serial_info.addr + serial_offset;
+
+ /* Encode register access size */
+ switch (serial_info.reg_shift) {
+ case 0:
+ access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ break;
+ case 1:
+ access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
+ break;
+ case 2:
+ access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ break;
+ case 3:
+ access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
+ break;
+ default:
+ access_size = ACPI_ACCESS_SIZE_UNDEFINED;
+ break;
+ }
+
+ debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
+
+ /* Fill GAS */
+ spcr->serial_port.space_id = space_id;
+ spcr->serial_port.bit_width = serial_width;
+ spcr->serial_port.bit_offset = 0;
+ spcr->serial_port.access_size = access_size;
+ spcr->serial_port.addrl = lower_32_bits(serial_address);
+ spcr->serial_port.addrh = upper_32_bits(serial_address);
+
+ /* Encode baud rate */
+ switch (serial_info.baudrate) {
+ case 9600:
+ spcr->baud_rate = 3;
+ break;
+ case 19200:
+ spcr->baud_rate = 4;
+ break;
+ case 57600:
+ spcr->baud_rate = 6;
+ break;
+ case 115200:
+ spcr->baud_rate = 7;
+ break;
+ default:
+ spcr->baud_rate = 0;
+ break;
+ }
+
+ serial_config = SERIAL_DEFAULT_CONFIG;
+ if (dev)
+ ret = serial_getconfig(dev, &serial_config);
+
+ spcr->parity = SERIAL_GET_PARITY(serial_config);
+ spcr->stop_bits = SERIAL_GET_STOP(serial_config);
+
+ /* No PCI devices for now */
+ spcr->pci_device_id = 0xffff;
+ spcr->pci_vendor_id = 0xffff;
+
+ /*
+ * SPCR has no clue if the UART base clock speed is different
+ * to the default one. However, the SPCR 1.04 defines baud rate
+ * 0 as a preconfigured state of UART and OS is supposed not
+ * to touch the configuration of the serial device.
+ */
+ if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
+ spcr->baud_rate = 0;
+
+ /* Fix checksum */
+ header->checksum = table_compute_checksum((void *)spcr, header->length);
+
+ acpi_add_table(ctx, spcr);
+ acpi_inc(ctx, spcr->header.length);
+
+ return 0;
+}
+
+ACPI_WRITER(5spcr, "SPCR", acpi_write_spcr, 0);
+
+__weak int acpi_fill_iort(struct acpi_ctx *ctx)
+{
+ return 0;
+}
+
+int acpi_iort_add_its_group(struct acpi_ctx *ctx,
+ const u32 its_count,
+ const u32 *identifiers)
+{
+ struct acpi_iort_node *node;
+ struct acpi_iort_its_group *group;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+
+ node = ctx->current;
+ memset(node, '\0', sizeof(struct acpi_iort_node));
+
+ node->type = ACPI_IORT_NODE_ITS_GROUP;
+ node->revision = 1;
+
+ node->length = sizeof(struct acpi_iort_node);
+ node->length += sizeof(struct acpi_iort_its_group);
+ node->length += sizeof(u32) * its_count;
+
+ group = (struct acpi_iort_its_group *)node->node_data;
+ group->its_count = its_count;
+ memcpy(&group->identifiers, identifiers, sizeof(u32) * its_count);
+
+ ctx->current += node->length;
+
+ return offset;
+}
+
+int acpi_iort_add_named_component(struct acpi_ctx *ctx,
+ const u32 node_flags,
+ const u64 memory_properties,
+ const u8 memory_address_limit,
+ const char *device_name)
+{
+ struct acpi_iort_node *node;
+ struct acpi_iort_named_component *comp;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+
+ node = ctx->current;
+ memset(node, '\0', sizeof(struct acpi_iort_node));
+
+ node->type = ACPI_IORT_NODE_NAMED_COMPONENT;
+ node->revision = 4;
+ node->length = sizeof(struct acpi_iort_node);
+ node->length += sizeof(struct acpi_iort_named_component);
+ node->length += strlen(device_name) + 1;
+
+ comp = (struct acpi_iort_named_component *)node->node_data;
+
+ comp->node_flags = node_flags;
+ comp->memory_properties = memory_properties;
+ comp->memory_address_limit = memory_address_limit;
+ memcpy(comp->device_name, device_name, strlen(device_name) + 1);
+
+ ctx->current += node->length;
+
+ return offset;
+}
+
+int acpi_iort_add_rc(struct acpi_ctx *ctx,
+ const u64 mem_access_properties,
+ const u32 ats_attributes,
+ const u32 pci_segment_number,
+ const u8 memory_address_size_limit,
+ const int num_mappings,
+ const struct acpi_iort_id_mapping *map)
+{
+ struct acpi_iort_id_mapping *mapping;
+ struct acpi_iort_node *node;
+ struct acpi_iort_rc *rc;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+
+ node = ctx->current;
+ memset(node, '\0', sizeof(struct acpi_iort_node));
+
+ node->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
+ node->revision = 2;
+
+ node->length = sizeof(struct acpi_iort_node);
+ node->length += sizeof(struct acpi_iort_rc);
+ node->length += sizeof(struct acpi_iort_id_mapping) * num_mappings;
+
+ rc = (struct acpi_iort_rc *)node->node_data;
+ rc->mem_access_properties = mem_access_properties;
+ rc->ats_attributes = ats_attributes;
+ rc->pci_segment_number = pci_segment_number;
+ rc->memory_address_size_limit = memory_address_size_limit;
+
+ mapping = (struct acpi_iort_id_mapping *)(rc + 1);
+ for (int i = 0; i < num_mappings; i++) {
+ memcpy(mapping, &map[i], sizeof(struct acpi_iort_id_mapping));
+ mapping++;
+ }
+
+ ctx->current += node->length;
+
+ return offset;
+}
+
+int acpi_iort_add_smmu_v3(struct acpi_ctx *ctx,
+ const u64 base_address,
+ const u32 flags,
+ const u64 vatos_address,
+ const u32 model,
+ const u32 event_gsiv,
+ const u32 pri_gsiv,
+ const u32 gerr_gsiv,
+ const u32 sync_gsiv,
+ const u32 pxm,
+ const u32 id_mapping_index,
+ const int num_mappings,
+ const struct acpi_iort_id_mapping *map)
+{
+ struct acpi_iort_node *node;
+ struct acpi_iort_smmu_v3 *smmu;
+ struct acpi_iort_id_mapping *mapping;
+ int offset;
+
+ offset = ctx->current - ctx->tab_start;
+
+ node = ctx->current;
+ memset(node, '\0', sizeof(struct acpi_iort_node));
+
+ node->type = ACPI_IORT_NODE_SMMU_V3;
+ node->revision = 5;
+ node->mapping_count = num_mappings;
+ node->mapping_offset = sizeof(struct acpi_iort_node) + sizeof(struct acpi_iort_smmu_v3);
+
+ node->length = sizeof(struct acpi_iort_node);
+ node->length += sizeof(struct acpi_iort_smmu_v3);
+ node->length += sizeof(struct acpi_iort_id_mapping) * num_mappings;
+
+ smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+ smmu->base_address = base_address;
+ smmu->flags = flags;
+ smmu->vatos_address = vatos_address;
+ smmu->model = model;
+ smmu->event_gsiv = event_gsiv;
+ smmu->pri_gsiv = pri_gsiv;
+ smmu->gerr_gsiv = gerr_gsiv;
+ smmu->sync_gsiv = sync_gsiv;
+ smmu->pxm = pxm;
+ smmu->id_mapping_index = id_mapping_index;
+
+ mapping = (struct acpi_iort_id_mapping *)(smmu + 1);
+ for (int i = 0; i < num_mappings; i++) {
+ memcpy(mapping, &map[i], sizeof(struct acpi_iort_id_mapping));
+ mapping++;
+ }
+
+ ctx->current += node->length;
+
+ return offset;
+}
+
+static int acpi_write_iort(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_iort *iort;
+ struct acpi_iort_node *node;
+ u32 offset;
+ int ret;
+
+ iort = ctx->current;
+ ctx->tab_start = ctx->current;
+ memset(iort, '\0', sizeof(struct acpi_table_iort));
+
+ acpi_fill_header(&iort->header, "IORT");
+ iort->header.revision = 1;
+ iort->header.creator_revision = 1;
+ iort->header.length = sizeof(struct acpi_table_iort);
+ iort->node_offset = sizeof(struct acpi_table_iort);
+
+ acpi_inc(ctx, sizeof(struct acpi_table_iort));
+
+ offset = sizeof(struct acpi_table_iort);
+ ret = acpi_fill_iort(ctx);
+ if (ret) {
+ ctx->current = iort;
+ return log_msg_ret("fill", ret);
+ }
+
+ /* Count nodes filled in */
+ for (node = (void *)iort + iort->node_offset;
+ node->length > 0 && (void *)node < ctx->current;
+ node = (void *)node + node->length)
+ iort->node_count++;
+
+ /* (Re)calculate length and checksum */
+ iort->header.length = ctx->current - (void *)iort;
+ iort->header.checksum = table_compute_checksum((void *)iort, iort->header.length);
+ log_debug("IORT at %p, length %x\n", iort, iort->header.length);
+
+ /* Drop the table if it is empty */
+ if (iort->header.length == sizeof(struct acpi_table_iort))
+ return log_msg_ret("fill", -ENOENT);
+ acpi_add_table(ctx, iort);
+
+ return 0;
+}
+
+ACPI_WRITER(5iort, "IORT", acpi_write_iort, 0);
+
+/*
+ * Allocate memory for ACPI tables and write ACPI tables to the
+ * allocated buffer.
+ *
+ * Return: status code
+ */
+static int alloc_write_acpi_tables(void)
+{
+ u64 table_end;
+ void *addr;
+
+ if (IS_ENABLED(CONFIG_X86) ||
+ IS_ENABLED(CONFIG_QFW_ACPI) ||
+ IS_ENABLED(CONFIG_SANDBOX)) {
+ log_debug("Skipping writing ACPI tables as already done\n");
+ return 0;
+ }
+
+ if (!IS_ENABLED(CONFIG_BLOBLIST_TABLES)) {
+ log_debug("Skipping writing ACPI tables as BLOBLIST_TABLES is not selected\n");
+ return 0;
+ }
+
+ /* Align the table to a 4KB boundary to keep EFI happy */
+ addr = bloblist_add(BLOBLISTT_ACPI_TABLES, TABLE_SIZE,
+ ilog2(SZ_4K));
+
+ if (!addr)
+ return log_msg_ret("mem", -ENOMEM);
+
+ gd->arch.table_start_high = virt_to_phys(addr);
+ gd->arch.table_end_high = gd->arch.table_start_high + TABLE_SIZE;
+
+ table_end = write_acpi_tables(gd->arch.table_start_high);
+ if (!table_end) {
+ log_err("Can't create ACPI configuration table\n");
+ return -EINTR;
+ }
+
+ log_debug("- wrote 'acpi' to %lx, end %llx\n", gd->arch.table_start_high, table_end);
+ if (table_end > gd->arch.table_end_high) {
+ log_err("Out of space for configuration tables: need %llx, have %x\n",
+ table_end - gd->arch.table_start_high, TABLE_SIZE);
+ return log_msg_ret("acpi", -ENOSPC);
+ }
+
+ log_debug("- done writing tables\n");
+
+ return 0;
+}
+
+EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, alloc_write_acpi_tables);
diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c
index ecff5a50d50..fa9dad32a3f 100644
--- a/lib/acpi/acpigen.c
+++ b/lib/acpi/acpigen.c
@@ -361,6 +361,17 @@ void acpigen_write_processor(struct acpi_ctx *ctx, uint cpuindex,
acpigen_emit_byte(ctx, pblock_len);
}
+void acpigen_write_processor_device(struct acpi_ctx *ctx, uint cpuindex)
+{
+ char pscope[16];
+
+ snprintf(pscope, sizeof(pscope), ACPI_CPU_STRING, cpuindex);
+ acpigen_write_device(ctx, pscope);
+ acpigen_write_name_string(ctx, "_HID", "ACPI0007");
+ acpigen_write_name_integer(ctx, "_UID", cpuindex);
+ acpigen_pop_len(ctx); /* Device */
+}
+
void acpigen_write_processor_package(struct acpi_ctx *ctx,
const char *const name,
const uint first_core,
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index 7ccd7f8d20a..39a26bbb492 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -95,6 +95,21 @@ static int testacpi_get_name(const struct udevice *dev, char *out_name)
return acpi_copy_name(out_name, ACPI_TEST_DEV_NAME);
}
+static int testacpi_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ u64 *data = ctx->current;
+
+ /* Only fill madt once */
+ if (device_get_uclass_id(dev->parent) != UCLASS_TEST_ACPI)
+ return 0;
+
+ *data = 0xdeadbeef;
+
+ acpi_inc(ctx, sizeof(u64));
+
+ return 0;
+}
+
static int testacpi_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
{
const char *data;
@@ -124,6 +139,7 @@ static int testacpi_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx)
struct acpi_ops testacpi_ops = {
.get_name = testacpi_get_name,
.write_tables = testacpi_write_tables,
+ .fill_madt = testacpi_fill_madt,
.fill_ssdt = testacpi_fill_ssdt,
.inject_dsdt = testacpi_inject_dsdt,
};
@@ -527,6 +543,33 @@ static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts)
}
DM_TEST(dm_test_acpi_fill_ssdt, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+/* Test acpi_fill_madt() */
+static int dm_test_acpi_fill_madt(struct unit_test_state *uts)
+{
+ struct acpi_ctx ctx;
+ u64 *buf;
+
+ buf = malloc(BUF_SIZE);
+ ut_assertnonnull(buf);
+
+ acpi_reset_items();
+ ctx.current = buf;
+ buf[1] = 'z'; /* sentinel */
+ ut_assertok(acpi_fill_madt_subtbl(&ctx));
+
+ /*
+ * These values come from acpi-test2's acpi-ssdt-test-data property.
+ * This device comes first because of u-boot,acpi-ssdt-order
+ */
+ ut_asserteq(0xdeadbeef, buf[0]);
+
+ ut_asserteq('z', buf[1]);
+
+ return 0;
+}
+
+DM_TEST(dm_test_acpi_fill_madt, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+
/* Test acpi_inject_dsdt() */
static int dm_test_acpi_inject_dsdt(struct unit_test_state *uts)
{
diff --git a/test/dm/irq.c b/test/dm/irq.c
index 836f2d82e71..ca3e1880656 100644
--- a/test/dm/irq.c
+++ b/test/dm/irq.c
@@ -76,6 +76,21 @@ static int dm_test_request(struct unit_test_state *uts)
}
DM_TEST(dm_test_request, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+/* Test of irq_get_by_index() */
+static int dm_test_irq_get_by_index(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct irq irq;
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "f-test",
+ &dev));
+ ut_assertok(irq_get_by_index(dev, 0, &irq));
+ ut_asserteq(4, irq.id);
+
+ return 0;
+}
+DM_TEST(dm_test_irq_get_by_index, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+
/* Test of irq_get_acpi() */
static int dm_test_irq_get_acpi(struct unit_test_state *uts)
{
diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py
index e282c67335c..45143c1c7d9 100644
--- a/test/py/tests/test_event_dump.py
+++ b/test/py/tests/test_event_dump.py
@@ -18,6 +18,7 @@ def test_event_dump(u_boot_console):
-------------------- ------------------------------ ------------------------------
EVT_FT_FIXUP bootmeth_vbe_ft_fixup .*boot/vbe_request.c:.*
EVT_FT_FIXUP bootmeth_vbe_simple_ft_fixup .*boot/vbe_simple_os.c:.*
+EVT_LAST_STAGE_INIT alloc_write_acpi_tables .*lib/acpi/acpi_table.c:.*
EVT_LAST_STAGE_INIT install_smbios_table .*lib/efi_loader/efi_smbios.c:.*
EVT_MISC_INIT_F sandbox_early_getopt_check .*arch/sandbox/cpu/start.c:.*
EVT_TEST h_adder_simple .*test/common/event.c:'''