[PATCH 12/17] arm: bcm283x: Write ACPI tables
Simon Glass
sjg at chromium.org
Mon Jul 29 17:28:40 CEST 2024
Hi Patrick,
On Sat, 27 Jul 2024 at 01:20, Patrick Rudolph
<patrick.rudolph at 9elements.com> wrote:
>
> 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
This should be in arch/arm/lib or similar, i.e. generic code.
> 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);
We should really put tables in a bloblist on ARM. This is an option on
x86 but we should make it mandatory on ARM. We may have other tables,
such as SMBIOS.
> +
> + /* 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
But there should be :-)
> --
> 2.45.2
>
Regards,
Simon
More information about the U-Boot
mailing list