diff mbox series

[40/40] RFC: rpi: Enable booting with ACPI tables

Message ID 20211201160315.2203099-41-sjg@chromium.org
State RFC
Delegated to: Tom Rini
Headers show
Series RFC: rpi: Enable ACPI booting on ARM with Raspberry Pi 4 | expand

Commit Message

Simon Glass Dec. 1, 2021, 4:03 p.m. UTC
This is only partially implemented and includes RFC patches.

So far it boots into grub but is unable to read the OS from the USB stick,
presumably because the XHCI SSDT is missing.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/arm/include/asm/acpi_table.h |  15 +
 board/raspberrypi/rpi/Makefile    |   2 +
 board/raspberrypi/rpi/rpi.c       | 460 +++++++++++++++++++++++++++++-
 configs/rpi_4_defconfig           |   2 +
 4 files changed, 478 insertions(+), 1 deletion(-)

Comments

Andy Shevchenko Dec. 1, 2021, 4:24 p.m. UTC | #1
On Wed, Dec 1, 2021 at 6:15 PM Simon Glass <sjg@chromium.org> wrote:
>
> This is only partially implemented and includes RFC patches.
>
> So far it boots into grub but is unable to read the OS from the USB stick,
> presumably because the XHCI SSDT is missing.

I would recommend enabling SPCR and then pass `earlycon` to see if it
gives anything.

Nevertheless, I'm in favour of this series, thanks!
For patches 21 and 27 (are they the only ones that touch tangier?) take my
Reviewed-by: Andy  Shevchenko <andy.shevchenko@gmail.com>
Simon Glass Dec. 1, 2021, 7:30 p.m. UTC | #2
Hi Andy,

On Wed, 1 Dec 2021 at 09:25, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Wed, Dec 1, 2021 at 6:15 PM Simon Glass <sjg@chromium.org> wrote:
> >
> > This is only partially implemented and includes RFC patches.
> >
> > So far it boots into grub but is unable to read the OS from the USB stick,
> > presumably because the XHCI SSDT is missing.
>
> I would recommend enabling SPCR and then pass `earlycon` to see if it
> gives anything.

OK I will give that a try once I get to the kernel. For now it might
be stuck in grub?

https://drive.google.com/file/d/1k_4zik7UGyOS3czknKi2-WyGz-j1f6Q6/view?usp=sharing

Here is the console output:

$ int.sh rpi4
tbot starting ...
├─Calling interactive_board ...
│   ├─POWERON (rpi4)
│   ├─Entering interactive shell (CTRL+D to exit) ...


U-Boot 2022.01-rc3-00119-g7bc37ec5293 (Dec 01 2021 - 12:19:09 -0700)

DRAM:  3.9 GiB
RPI 4 Model B (0xc03111)
MMC:   mmcnr@7e300000: 1, mmc@7e340000: 0
Loading Environment from FAT... Unable to read "uboot.env" from
mmc0:1... In:    serial
Out:   vidconsole
Err:   vidconsole
Net:   eth0: ethernet@7d580000
ACPI: Writing ACPI tables at 10000
0base: writing table '<NULL>'
1facs: writing table 'FACS'
3dsdt: writing table 'DSDT'
5csrt: writing table 'CSRT'
5dbg2: writing table 'DBG2'
5facp: writing table 'FACP'
5gtdt: writing table 'GTDT'
5madt: writing table 'APIC'
5pptt: writing table 'PPTT'
6ssdt: writing table 'SSDT'
6ssdt: Omitted due to being empty
8dev: writing table '<NULL>'
ACPI current = 12eb0
PCIe BRCM: link up, 5.0 Gbps x1 (SSC)
starting USB...
Bus xhci_pci: Register 5000420 NbrPorts 5
Starting the controller
USB XHCI 1.00
scanning bus xhci_pci for devices... 3 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Card did not respond to voltage select! : -110
Scanning disk mmcnr@7e300000.blk...
Disk mmcnr@7e300000.blk not ready
Scanning disk mmc@7e340000.blk...
Scanning disk usb_mass_storage.lun0...
Found 5 disks
** Unable to read file ubootefi.var **
Failed to load EFI variables
ACPI: Writing ACPI tables at 39f17000
0base: writing table '<NULL>'
1facs: writing table 'FACS'
3dsdt: writing table 'DSDT'
5csrt: writing table 'CSRT'
5dbg2: writing table 'DBG2'
5facp: writing table 'FACP'
5gtdt: writing table 'GTDT'
5madt: writing table 'APIC'
5pptt: writing table 'PPTT'
6ssdt: writing table 'SSDT'
6ssdt: Omitted due to being empty
8dev: writing table '<NULL>'
ACPI current = 39f19eb0
BootOrder not defined
EFI boot manager: Cannot load any image
Card did not respond to voltage select! : -110

Device 0: Vendor: Lexar    Rev: PMAP Prod: USB Flash Drive
            Type: Removable Hard Disk
            Capacity: 30560.0 MB = 29.8 GB (62586880 x 512)
... is now current device
Scanning usb 0:2...
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
BootOrder not defined
EFI boot manager: Cannot load any image
Found EFI removable media binary efi/boot/bootaa64.efi
1865600 bytes read in 50 ms (35.6 MiB/s)
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Booting /efi\boot\bootaa64.efi
ethernet@7d580000 Waiting for PHY auto negotiation to
complete......... TIMEOUT !
bcmgenet: PHY startup failed: -110
EFI stub: ERROR: FIRMWARE BUG: kernel image not aligned on 64k boundary



>
> Nevertheless, I'm in favour of this series, thanks!
> For patches 21 and 27 (are they the only ones that touch tangier?) take my
> Reviewed-by: Andy  Shevchenko <andy.shevchenko@gmail.com>

Thanks!

I think tangier may be affected by anything with the x86 tag, since it
is moving the ACPI code around. Worth a test if you have time. So far
I tested it on coral but will do also on minnowmax which I have in my
lab.

Regards,
Simon
diff mbox series

Patch

diff --git a/arch/arm/include/asm/acpi_table.h b/arch/arm/include/asm/acpi_table.h
index e69de29bb2d..930e857edeb 100644
--- a/arch/arm/include/asm/acpi_table.h
+++ b/arch/arm/include/asm/acpi_table.h
@@ -0,0 +1,15 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef __ASM_ACPI_TABLE_H__
+#define __ASM_ACPI_TABLE_H__
+
+#ifndef __ACPI__
+
+ulong write_acpi_tables(ulong start);
+
+#endif
+
+#endif /* __ASM_ACPI_TABLE_H__ */
diff --git a/board/raspberrypi/rpi/Makefile b/board/raspberrypi/rpi/Makefile
index b1186cdf100..67f6b05e654 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.o
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 55afaa54d9f..3fe69c66da2 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -3,6 +3,8 @@ 
  * (C) Copyright 2012-2016 Stephen Warren
  */
 
+#define LOG_CATEGORY LOGC_BOARD
+
 #include <common.h>
 #include <config.h>
 #include <dm.h>
@@ -12,19 +14,29 @@ 
 #include <fdt_simplefb.h>
 #include <init.h>
 #include <lcd.h>
+#include <log.h>
 #include <memalign.h>
 #include <mmc.h>
+#include <signatures.h>
+#include <tables_csum.h>
+#include <acpi/acpi_table.h>
+#include <asm/acpi_table.h>
+#include <asm/global_data.h>
 #include <asm/gpio.h>
 #include <asm/arch/mbox.h>
 #include <asm/arch/msg.h>
 #include <asm/arch/sdhci.h>
-#include <asm/global_data.h>
+#include <asm/arch/acpi/bcm2836.h>
+#include <dm/acpi.h>
 #include <dm/platform_data/serial_bcm283x_mu.h>
 #ifdef CONFIG_ARM64
 #include <asm/armv8/mmu.h>
 #endif
 #include <watchdog.h>
 #include <dm/pinctrl.h>
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+#include "acpitables.h"
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -515,3 +527,449 @@  int ft_board_setup(void *blob, struct bd_info *bd)
 
 	return 0;
 }
+
+#ifdef CONFIG_GENERATE_ACPI_TABLE
+int last_stage_init(void)
+{
+	int ret;
+
+	ret = write_acpi_tables(0x10000);
+	if (ret < 0) {
+		log_err("Failed to write tables\n");
+		return log_msg_ret("table", ret);
+	}
+
+	return 0;
+}
+
+static int rpi_write_facp(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+	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 = ACPI_FADT_REV_ACPI_6_0;
+
+	fadt->firmware_ctrl = (ulong)ctx->facs;
+	fadt->dsdt = (ulong)ctx->dsdt;
+	fadt->preferred_pm_profile = ACPI_PM_APPLIANCE_PC;
+
+	fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_SLEEP_BUTTON |
+		ACPI_FADT_HW_REDUCED_ACPI;
+	fadt->arm_boot_arch = ACPI_ARM_PSCI_COMPLIANT;
+	fadt->minor_revision = 3;
+
+	fadt->x_firmware_ctl_l = (ulong)ctx->facs;
+	fadt->x_firmware_ctl_h = (ulong)ctx->facs >> 32;
+	fadt->x_dsdt_l = (ulong)ctx->dsdt;
+	fadt->x_dsdt_h = (ulong)ctx->dsdt >> 32;
+
+	header->checksum = table_compute_checksum(fadt, header->length);
+
+	acpi_add_table(ctx, fadt);
+
+	acpi_inc(ctx, sizeof(struct acpi_fadt));
+
+	return 0;
+}
+ACPI_WRITER(5facp, "FACP", rpi_write_facp, 0);
+
+#define GTDT_FLAG_INT_ACTIVE_LOW	BIT(1)
+#define RPI_GTDT_GTIMER_FLAGS		GTDT_FLAG_INT_ACTIVE_LOW
+
+/* ARM Architectural Timer Interrupt(GIC PPI) numbers */
+#define PcdArmArchTimerSecIntrNum	29
+#define PcdArmArchTimerIntrNum		30
+#define PcdArmArchTimerHypIntrNum	26
+#define PcdArmArchTimerVirtIntrNum	27
+
+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 = 3;
+
+	gtdt->cnt_ctrl_base = RPI_SYSTEM_TIMER_BASE_ADDRESS;
+	gtdt->sec_el1_gsiv = PcdArmArchTimerSecIntrNum;
+	gtdt->sec_el1_flags = RPI_GTDT_GTIMER_FLAGS;
+	gtdt->el1_gsiv = PcdArmArchTimerIntrNum;
+	gtdt->el1_flags = RPI_GTDT_GTIMER_FLAGS;
+	gtdt->virt_el1_gsiv = PcdArmArchTimerVirtIntrNum;
+	gtdt->virt_el1_flags = RPI_GTDT_GTIMER_FLAGS;
+	gtdt->el2_gsiv = PcdArmArchTimerHypIntrNum;
+	gtdt->el2_flags = RPI_GTDT_GTIMER_FLAGS;
+	gtdt->cnt_read_base = 0xffffffffffffffff;
+	acpi_add_table(ctx, gtdt);
+
+	acpi_inc(ctx, sizeof(struct acpi_gtdt));
+
+	return 0;
+};
+ACPI_WRITER(5gtdt, "GTDT", rpi_write_gtdt, 0);
+
+static int rpi_write_dbg2(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+	struct acpi_table_header *header;
+	struct acpi_dbg2_header *dbg2;
+	struct acpi_dbg2_device *ddev;
+	struct acpi_gen_regaddr *addr;
+	u32 *addr_size;
+	char *name;
+	void *end;
+
+	dbg2 = ctx->current;
+	header = &dbg2->header;
+
+	/* Note this doesn't zero everything */
+	memset(dbg2, '\0', sizeof(struct acpi_dbg2_header));
+
+	acpi_fill_header(header, "DBG2");
+	header->revision = 0;
+
+	dbg2->devices_offset = sizeof(*dbg2);
+	dbg2->devices_count = 1;
+
+	ddev = (void *)(dbg2 + 1);
+	ddev->revision = 0;
+	ddev->length = 0x35;
+	ddev->address_count = 1;
+	ddev->namespace_string_length = 0xf;
+	ddev->namespace_string_offset = 0x26;
+	ddev->oem_data_length = 0;
+	ddev->oem_data_offset = 0;
+	ddev->port_type = ACPI_DBG2_SERIAL_PORT;
+	ddev->port_subtype = ACPI_DBG2_ARM_PL011;
+
+	addr = (void *)(ddev + 1);
+	ddev->base_address_offset = sizeof(*ddev);
+	ddev->address_size_offset = sizeof(*ddev) + sizeof(*addr);
+
+	addr->space_id = ACPI_ADDRESS_SPACE_MEMORY;
+	addr->bit_width = 32;
+	addr->bit_offset = 0;
+	addr->access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+	addr->addrl = 0xfe201000;
+	addr->addrh = 0;
+
+	addr_size = (u32 *)(addr + 1);
+	*addr_size = 0x1000;
+
+	name = (char *)(addr_size + 1);
+	strcpy(name, "\\_SB.GDV0.URT0");
+	end = name + strlen(name) + 1;
+	header->length = end - ctx->current;
+	acpi_add_table(ctx, dbg2);
+
+	acpi_inc(ctx, header->length);
+
+	return 0;
+};
+ACPI_WRITER(5dbg2, "DBG2", rpi_write_dbg2, 0);
+
+#if 0
+/* Need to add a logo first */
+static int rpi_write_bgrt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+	struct acpi_table_header *header;
+	struct acpi_bgrt_header *bgrt;
+
+	bgrt = ctx->current;
+	header = &dbg2->header;
+
+	memset(bgrt, '\0', sizeof(struct acpi_bgrt));
+
+	acpi_fill_header(header, "BGRT");
+	header->revision = 0;
+
+	acpi_inc(ctx, header->length);
+
+	return 0;
+};
+ACPI_WRITER(5bgrt, "BGRT", rpi_write_bgrt, 0);
+#endif
+
+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 rpi_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 = 0;
+	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", rpi_write_pptt, 0);
+
+static void acpi_write_madt_gicc(struct acpi_ctx *ctx, uint cpu_num,
+				 uint perf_gsiv, ulong phys_base, ulong gicv,
+				 ulong gich, uint vgic_maint_irq, ulong mpidr,
+				 uint efficiency)
+{
+	struct acpi_madr_gicc *gicc = ctx->current;
+
+	memset(gicc, '\0', sizeof(struct acpi_madr_gicc));
+	gicc->type = ACPI_APIC_GICC;
+	gicc->length = sizeof(struct acpi_madr_gicc);
+	gicc->cpu_if_num = cpu_num;
+	gicc->processor_id = cpu_num;
+	gicc->flags = ACPI_MADRF_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->mpidr = mpidr;
+	gicc->efficiency = efficiency;
+	acpi_inc(ctx, gicc->length);
+}
+
+static void acpi_write_madt_gicd(struct acpi_ctx *ctx, uint gic_id,
+				 ulong phys_base, uint gic_version)
+{
+	struct acpi_madr_gicd *gicd = ctx->current;
+
+	memset(gicd, '\0', sizeof(struct acpi_madr_gicd));
+	gicd->type = ACPI_APIC_GICD;
+	gicd->length = sizeof(struct acpi_madr_gicd);
+	gicd->gic_id = gic_id;
+	gicd->phys_base = phys_base;
+	gicd->gic_version = gic_version;
+
+	acpi_inc(ctx, gicd->length);
+}
+
+static int rpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
+{
+	struct acpi_table_header *header;
+	struct acpi_madt *madt;
+	int i;
+
+	ctx->tab_start = ctx->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_6_0;
+
+	madt->lapic_addr = 0;
+	madt->flags = 0;
+	acpi_inc(ctx, sizeof(*madt));
+
+	for (i = 0; i < 4; i++) {
+		acpi_write_madt_gicc(ctx, i, 0x30 + i, 0xff842000, 0xff846000,
+				     0xff844000, 0x19, i, 1);
+	}
+	acpi_write_madt_gicd(ctx, 0, 0xff841000, 2);
+
+	/* (Re)calculate length and checksum */
+	header->length = (u32)(ctx->current - ctx->tab_start);
+
+	header->checksum = table_compute_checksum((void *)madt, header->length);
+	acpi_add_table(ctx, madt);
+	acpi_inc(ctx, madt->header.length);
+
+	return 0;
+}
+ACPI_WRITER(5madt, "APIC", rpi_write_madt, 0);
+
+/* DMA Controller Vendor Data */
+struct __packed dma_ctlr_vendor_data {
+	u32 length;
+	u32 type;
+	u64 chan_base;
+	u32 chan_size;
+	u64 ctlr_base;
+	u32 ctlr_size;
+	u32 chan_count;
+	u32 ctlr_irq;
+	u32 min_req_line;
+	u32 max_req_line;
+	u8 cache_coherent;
+};
+
+/* DMA Controller */
+struct __packed rd_dma_ctlr {
+	struct acpi_csrt_descriptor hdr;
+	struct dma_ctlr_vendor_data data;
+};
+
+/* dma chan vendor data */
+struct __packed dma_chan_vendor_data {
+	u32 chan;
+	u32 chan_irq;
+	u16 is_reserved;
+	u16 addr_incr;
+};
+
+/* dma chan */
+struct __packed rd_dma_chan {
+	struct acpi_csrt_descriptor hdr;
+	struct dma_chan_vendor_data data;
+};
+
+/* dma resource group */
+struct __packed rg_dma {
+	struct acpi_csrt_group hdr;
+	struct rd_dma_ctlr ctlr;
+	struct rd_dma_chan chan[];
+};
+
+#define RPI_DMA_MAX_REQ_LINES 32
+
+static void add_cmd_chan(struct rd_dma_chan *dmac, uint uid, uint chan,
+			 uint chan_irq, bool is_reserved, int addr_incr)
+{
+	memset(dmac, '\0', sizeof(*dmac));
+	dmac->hdr.length = sizeof(struct rd_dma_chan);
+	dmac->hdr.type = EFI_ACPI_CSRT_RESOURCE_TYPE_DMA;
+	dmac->hdr.subtype = EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL;
+	dmac->hdr.uid = uid;
+
+	dmac->data.chan = chan;
+	dmac->data.chan_irq = chan_irq;
+	dmac->data.is_reserved = is_reserved;
+	dmac->data.addr_incr = addr_incr;
+}
+
+int acpi_fill_csrt(struct acpi_ctx *ctx)
+{
+	struct dma_ctlr_vendor_data *data;
+	struct acpi_csrt_group *hdr;
+	struct rg_dma *dma;
+	int i;
+
+	dma = ctx->current;
+	hdr = &dma->hdr;
+	memset(hdr, '\0', sizeof(*hdr));
+	hdr->length = 0;
+	hdr->vendor_id = SIGNATURE_32('R', 'P', 'I', 'F');
+	hdr->device_id = EFI_ACPI_CSRT_DEVICE_ID_DMA;
+
+	dma->ctlr.hdr.length = sizeof(struct rd_dma_ctlr);
+	dma->ctlr.hdr.type = EFI_ACPI_CSRT_RESOURCE_TYPE_DMA;
+	dma->ctlr.hdr.subtype = EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CONTROLLER;
+	dma->ctlr.hdr.uid = EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP;
+
+	data = &dma->ctlr.data;
+	data->length = sizeof(struct dma_ctlr_vendor_data);
+	data->type = 1;
+	data->chan_base = BCM2836_DMA0_BASE_ADDRESS;
+	data->chan_size = RPI_DMA_CHANNEL_COUNT * BCM2836_DMA_CHANNEL_LENGTH;
+	data->ctlr_base = BCM2836_DMA_CTRL_BASE_ADDRESS;
+	data->ctlr_size = 8;
+	data->chan_count = RPI_DMA_USED_CHANNEL_COUNT;
+	data->max_req_line = RPI_DMA_MAX_REQ_LINES - 1;
+
+	acpi_inc(ctx, sizeof(struct rg_dma));
+
+	for (i = 0; i < 10; i++) {
+		add_cmd_chan(&dma->chan[i],
+			     EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP + 1 + i, i,
+			     0x30 + i,
+			     i == 1 || i == 2 || i == 3 || i == 6 || i == 7,
+			     i == 4);
+		acpi_inc(ctx, sizeof(struct rd_dma_chan));
+	}
+
+	hdr->length = (u32)(ctx->current - (void *)dma);
+
+	return 0;
+}
+#endif
diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
index 0720505c6a5..4a81f3e1f38 100644
--- a/configs/rpi_4_defconfig
+++ b/configs/rpi_4_defconfig
@@ -11,6 +11,7 @@  CONFIG_USE_PREBOOT=y
 CONFIG_PREBOOT="pci enum; usb start;"
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_LAST_STAGE_INIT=y
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_PROMPT="U-Boot> "
 CONFIG_CMD_DFU=y
@@ -60,4 +61,5 @@  CONFIG_DM_VIDEO=y
 CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_PHYS_TO_BUS=y
+CONFIG_GENERATE_ACPI_TABLE=y
 CONFIG_OF_LIBFDT_OVERLAY=y