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
113 changed files with 6528 additions and 551 deletions

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