[PATCH 12/17] arm: bcm283x: Write ACPI tables
Patrick Rudolph
patrick.rudolph at 9elements.com
Sat Jul 27 09:17:13 CEST 2024
Allocate a 64KiB buffer for ACPI tables and provide SoC specific tables
for BCM2711:
- MADT
- FADT
- PPTT
- GTDT
- SPCR
Board specific tables like DSDT and SSDT are added in a separate patch.
When ACPI is enabled for a different SoC compliation will fail by
design, indicating the required functions that needs to be implemented.
When ACPI is not enabled the added code does nothing, keeping existing
behaviour.
TEST: Booted on RPi4 with only ACPI enabled, providing no FDT to the OS.
Signed-off-by: Patrick Rudolph <patrick.rudolph at 9elements.com>
Cc: Simon Glass <sjg at chromium.org>
Cc: Matthias Brugger <mbrugger at suse.com>
Cc: Peter Robinson <pbrobinson at gmail.com>
Cc: Tom Rini <trini at konsulko.com>
---
arch/arm/mach-bcm283x/Makefile | 4 +
arch/arm/mach-bcm283x/bcm2711_acpi.c | 172 +++++++++++++++++++++++++++
arch/arm/mach-bcm283x/init.c | 30 +++++
3 files changed, 206 insertions(+)
create mode 100644 arch/arm/mach-bcm283x/bcm2711_acpi.c
diff --git a/arch/arm/mach-bcm283x/Makefile b/arch/arm/mach-bcm283x/Makefile
index 7cd068832f..38e320307d 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 0000000000..ab0f77c245
--- /dev/null
+++ b/arch/arm/mach-bcm283x/bcm2711_acpi.c
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2024 9elements GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ */
+
+#include <acpi/acpi_table.h>
+#include <asm/acpi_table.h>
+#include <asm/armv8/sec_firmware.h>
+#include <asm/arch/acpi/bcm2711.h>
+#include <tables_csum.h>
+#include <string.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;
+}
+
+void *acpi_fill_madt(struct acpi_madt *madt, void *current)
+{
+ struct acpi_madt_gicc *gicc;
+ struct acpi_madt_gicd *gicd;
+
+ madt->lapic_addr = 0;
+ madt->flags = 0;
+
+ gicc = current;
+ for (int i = 0; i < 4; i++) {
+ acpi_write_madt_gicc(gicc++, i, 0x30 + i, BCM2711_GIC400_BASE_ADDRESS + 0x2000,
+ BCM2711_GIC400_BASE_ADDRESS + 0x6000,
+ BCM2711_GIC400_BASE_ADDRESS + 0x4000,
+ 0x19, i, 1);
+ }
+
+ gicd = (struct acpi_madt_gicd *)gicc;
+ acpi_write_madt_gicd(gicd++, 0, BCM2711_GIC400_BASE_ADDRESS + 0x1000, 2);
+ return gicd;
+}
+
+static u32 *add_proc(struct acpi_ctx *ctx, int flags, int parent, int proc_id,
+ int num_resources)
+{
+ struct acpi_pptt_proc *proc = ctx->current;
+ u32 *resource_list;
+
+ 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;
+ resource_list = ctx->current + sizeof(struct acpi_pptt_proc);
+ acpi_inc(ctx, proc->hdr.length);
+
+ return resource_list;
+}
+
+static int add_cache(struct acpi_ctx *ctx, int flags, int size, int sets,
+ int assoc, int attributes, int line_size)
+{
+ struct acpi_pptt_cache *cache = ctx->current;
+ int ofs;
+
+ ofs = 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 = 0;
+ cache->size = size;
+ cache->sets = sets;
+ cache->assoc = assoc;
+ cache->attributes = attributes;
+ cache->line_size = line_size;
+ acpi_inc(ctx, cache->hdr.length);
+
+ return ofs;
+}
+
+static int acpi_write_pptt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+ struct acpi_table_header *header;
+ int proc_ofs;
+ u32 *proc_ptr;
+ int ofs, ofs0, ofs1, i;
+
+ 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));
+
+ proc_ofs = ctx->current - ctx->tab_start;
+ proc_ptr = add_proc(ctx, ACPI_PPTT_PHYSICAL_PACKAGE |
+ ACPI_PPTT_CHILDREN_IDENTICAL, 0, 0, 1);
+
+ ofs = add_cache(ctx, ACPI_PPTT_ALL_VALID, 0x100000, 0x400, 0x10,
+ ACPI_PPTT_WRITE_ALLOC |
+ (ACPI_PPTT_CACHE_TYPE_UNIFIED <<
+ ACPI_PPTT_CACHE_TYPE_SHIFT), 0x40);
+ *proc_ptr = ofs;
+
+ for (i = 0; i < 4; i++) {
+ proc_ptr = add_proc(ctx, ACPI_PPTT_CHILDREN_IDENTICAL |
+ ACPI_PPTT_NODE_IS_LEAF | ACPI_PPTT_PROC_ID_VALID,
+ proc_ofs, i, 2);
+
+ ofs0 = add_cache(ctx, ACPI_PPTT_ALL_VALID, 0x8000, 0x100, 2,
+ ACPI_PPTT_WRITE_ALLOC, 0x40);
+
+ ofs1 = add_cache(ctx, ACPI_PPTT_ALL_BUT_WRITE_POL, 0xc000, 0x100, 3,
+ ACPI_PPTT_CACHE_TYPE_INSTR <<
+ ACPI_PPTT_CACHE_TYPE_SHIFT, 0x40);
+ proc_ptr[0] = ofs0;
+ proc_ptr[1] = ofs1;
+ }
+
+ 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 = >dt->header;
+
+ memset(gtdt, '\0', sizeof(struct acpi_gtdt));
+
+ acpi_fill_header(header, "GTDT");
+ header->length = sizeof(struct acpi_gtdt);
+ header->revision = acpi_get_table_revision(ACPITAB_GTDT);
+
+ gtdt->cnt_ctrl_base = 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);
\ No newline at end of file
diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
index 7a1de22e0a..80a10f2212 100644
--- a/arch/arm/mach-bcm283x/init.c
+++ b/arch/arm/mach-bcm283x/init.c
@@ -6,11 +6,13 @@
* project.
*/
+#include <acpi/acpi_table.h>
#include <cpu_func.h>
#include <init.h>
#include <dm/device.h>
#include <fdt_support.h>
#include <asm/global_data.h>
+#include <malloc.h>
#define BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS 0x600000000UL
#define BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE 0x400000UL
@@ -240,3 +242,31 @@ void enable_caches(void)
dcache_enable();
}
#endif
+
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+static int last_stage_init(void)
+{
+ ulong end;
+ void *ptr;
+
+ /* Reserve 64K for ACPI tables, aligned to a 4K boundary */
+ ptr = memalign(SZ_4K, SZ_64K);
+
+ /* Generate ACPI tables */
+ end = write_acpi_tables((uintptr_t)ptr);
+ if (end < 0) {
+ log_err("Failed to write tables\n");
+ return log_msg_ret("table", end);
+ }
+ if (end > ((ulong)ptr + SZ_64K)) {
+ log_err("ACPI tables overflowed\n");
+ return 0;
+ }
+
+ gd->arch.table_start = (uintptr_t)ptr;
+ gd->arch.table_end = end;
+
+ return 0;
+}
+EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init);
+#endif
\ No newline at end of file
--
2.45.2
More information about the U-Boot
mailing list