Merge patch series "Implement ACPI on aarch64"

Patrick Rudolph <patrick.rudolph@9elements.com> says:

Based on the existing work done by Simon Glass this series adds
support for booting aarch64 devices using ACPI only.
As first target QEMU SBSA support is added, which relies on ACPI
only to boot an OS. As secondary target the Raspberry Pi4 was used,
which is broadly available and allows easy testing of the proposed
solution.

The series is split into ACPI cleanups and code movements, adding
Arm specific ACPI tables and finally SoC and mainboard related
changes to boot a Linux on the QEMU SBSA and RPi4. Currently only the
mandatory ACPI tables are supported, allowing to boot into Linux
without errors.

The QEMU SBSA support is feature complete and provides the same
functionality as the EDK2 implementation.

The changes were tested on real hardware as well on QEMU v9.0:

qemu-system-aarch64 -machine sbsa-ref -nographic -cpu cortex-a57 \
                    -pflash secure-world.rom \
                    -pflash unsecure-world.rom

qemu-system-aarch64 -machine raspi4b -kernel u-boot.bin -cpu cortex-a72 \
-smp 4 -m 2G -drive file=raspbian.img,format=raw,index=0 \
-dtb bcm2711-rpi-4-b.dtb -nographic

Tested against FWTS V24.03.00.

Known issues:
- The QEMU rpi4 support is currently limited as it doesn't emulate PCI,
  USB or ethernet devices!
- The SMP bringup doesn't work on RPi4, but works in QEMU (Possibly
  cache related).
- PCI on RPI4 isn't working on real hardware since the pcie_brcmstb
  Linux kernel module doesn't support ACPI yet.

Link: https://lore.kernel.org/r/20241023132116.970117-1-patrick.rudolph@9elements.com
This commit is contained in:
Tom Rini 2024-10-27 17:14:22 -06:00
commit 2800aecce0
113 changed files with 6528 additions and 551 deletions

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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:

View file

@ -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

138
arch/arm/dts/qemu-sbsa.dts Normal file
View file

@ -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";
};
};
};

View file

@ -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__ */

View file

@ -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:

View file

@ -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;

View file

@ -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)))

276
arch/arm/lib/acpi_table.c Normal file
View file

@ -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");
}

89
arch/arm/lib/gic-v2.c Normal file
View file

@ -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)
};

View file

@ -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_its_ids,
.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)
};

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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

View file

@ -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

View file

@ -527,6 +527,9 @@
};
f-test {
#interrupt-cells = <2>;
interrupt-parent = <&irq>;
interrupts = <4 0>;
compatible = "denx,u-boot-fdt-test";
};

View file

@ -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

View file

@ -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;
}

View file

@ -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,24 +145,10 @@ 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;
fadt->preferred_pm_profile = ACPI_PM_MOBILE;
}
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);
}
ACPI_WRITER(5fadt, "FADT", apl_write_fadt, 0);
int apl_acpi_fill_dmar(struct acpi_ctx *ctx)
{
struct udevice *dev, *sa_dev;

View file

@ -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)
{

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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,

View file

@ -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
@ -45,17 +42,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
*
@ -179,18 +165,6 @@ int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
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
*

View file

@ -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)
{

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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)
}

View file

@ -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

View file

@ -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();
}

View file

@ -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

View file

@ -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);

View file

@ -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;
}

3
board/raspberrypi/rpi/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
dsdt_generated.aml
dsdt_generated.asl.tmp
dsdt_generated.c

View file

@ -4,3 +4,5 @@
obj-y := rpi.o
obj-y += lowlevel_init.o
obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt_generated.o

View file

@ -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__

View file

@ -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"
}
}

View file

@ -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

View file

@ -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)
}
}

View file

@ -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

View file

@ -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
})
}

View file

@ -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
}
})
}

View file

@ -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

View file

@ -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
}
}
}

View file

@ -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)
}
}
}

View file

@ -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);
}

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -13,5 +13,6 @@ Emulation
qemu-mips
qemu-ppce500
qemu-riscv
qemu-sbsa
qemu-x86
qemu-xtensa

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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,
};

View file

@ -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;

View file

@ -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

View file

@ -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

151
drivers/cpu/armv8_cpu.c Normal file
View file

@ -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)
};

31
drivers/cpu/armv8_cpu.h Normal file
View file

@ -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

214
drivers/cpu/bcm283x_cpu.c Normal file
View file

@ -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)
};

View file

@ -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);

View file

@ -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;
}

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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,
};

Some files were not shown because too many files have changed in this diff Show more