diff options
| author | Tom Rini <[email protected]> | 2024-10-27 17:14:22 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2024-10-27 18:44:13 -0600 |
| commit | 2800aecce08b47b169d8e9824dd23b1297b2cedc (patch) | |
| tree | 2f8b61eaee1520b6fd5bd6cedb111aa3ee13f2f7 /board | |
| parent | 568407fab5336c00cf0265e9de6c507078988504 (diff) | |
| parent | 25081abf081880930365ff2bc6afc6c0273ca4bf (diff) | |
Merge patch series "Implement ACPI on aarch64"
Patrick Rudolph <[email protected]> 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/[email protected]
Diffstat (limited to 'board')
22 files changed, 2983 insertions, 0 deletions
diff --git a/board/emulation/qemu-arm/MAINTAINERS b/board/emulation/qemu-arm/MAINTAINERS index 5154262f29e..7bc0ee698c5 100644 --- a/board/emulation/qemu-arm/MAINTAINERS +++ b/board/emulation/qemu-arm/MAINTAINERS @@ -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 diff --git a/board/emulation/qemu-sbsa/Kconfig b/board/emulation/qemu-sbsa/Kconfig new file mode 100644 index 00000000000..72c76b351fa --- /dev/null +++ b/board/emulation/qemu-sbsa/Kconfig @@ -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 diff --git a/board/emulation/qemu-sbsa/Makefile b/board/emulation/qemu-sbsa/Makefile new file mode 100644 index 00000000000..bacae320e79 --- /dev/null +++ b/board/emulation/qemu-sbsa/Makefile @@ -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 diff --git a/board/emulation/qemu-sbsa/acpi.c b/board/emulation/qemu-sbsa/acpi.c new file mode 100644 index 00000000000..ba85e08fc7d --- /dev/null +++ b/board/emulation/qemu-sbsa/acpi.c @@ -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 = >dt->header; + + memset(gtdt, '\0', sizeof(struct acpi_gtdt)); + + acpi_fill_header(header, "GTDT"); + header->length = sizeof(struct acpi_gtdt); + header->revision = acpi_get_table_revision(ACPITAB_GTDT); + + gtdt->cnt_ctrl_base = 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); diff --git a/board/emulation/qemu-sbsa/dsdt.asl b/board/emulation/qemu-sbsa/dsdt.asl new file mode 100644 index 00000000000..f12cca04e2c --- /dev/null +++ b/board/emulation/qemu-sbsa/dsdt.asl @@ -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) +} diff --git a/board/emulation/qemu-sbsa/lowlevel_init.S b/board/emulation/qemu-sbsa/lowlevel_init.S new file mode 100644 index 00000000000..c997721af95 --- /dev/null +++ b/board/emulation/qemu-sbsa/lowlevel_init.S @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2016 + * Cédric Schieli <[email protected]> + */ + +#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 diff --git a/board/emulation/qemu-sbsa/qemu-sbsa.c b/board/emulation/qemu-sbsa/qemu-sbsa.c new file mode 100644 index 00000000000..3943c924320 --- /dev/null +++ b/board/emulation/qemu-sbsa/qemu-sbsa.c @@ -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(); +}
\ No newline at end of file diff --git a/board/emulation/qemu-sbsa/qemu-sbsa.env b/board/emulation/qemu-sbsa/qemu-sbsa.env new file mode 100644 index 00000000000..88fdb0ec1c5 --- /dev/null +++ b/board/emulation/qemu-sbsa/qemu-sbsa.env @@ -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 diff --git a/board/emulation/qemu-sbsa/qemu-sbsa.h b/board/emulation/qemu-sbsa/qemu-sbsa.h new file mode 100644 index 00000000000..391a70bdc40 --- /dev/null +++ b/board/emulation/qemu-sbsa/qemu-sbsa.h @@ -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); diff --git a/board/emulation/qemu-sbsa/smc.c b/board/emulation/qemu-sbsa/smc.c new file mode 100644 index 00000000000..9a2d091bea6 --- /dev/null +++ b/board/emulation/qemu-sbsa/smc.c @@ -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; +} diff --git a/board/raspberrypi/rpi/.gitignore b/board/raspberrypi/rpi/.gitignore new file mode 100644 index 00000000000..39e46ba0ae7 --- /dev/null +++ b/board/raspberrypi/rpi/.gitignore @@ -0,0 +1,3 @@ +dsdt_generated.aml +dsdt_generated.asl.tmp +dsdt_generated.c diff --git a/board/raspberrypi/rpi/Makefile b/board/raspberrypi/rpi/Makefile index b1186cdf100..bb1b7cc630f 100644 --- a/board/raspberrypi/rpi/Makefile +++ b/board/raspberrypi/rpi/Makefile @@ -4,3 +4,5 @@ obj-y := rpi.o obj-y += lowlevel_init.o + +obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt_generated.o diff --git a/board/raspberrypi/rpi/acpitables.h b/board/raspberrypi/rpi/acpitables.h new file mode 100644 index 00000000000..3ba8f19808c --- /dev/null +++ b/board/raspberrypi/rpi/acpitables.h @@ -0,0 +1,90 @@ +/** @file + * + * RPi defines for constructing ACPI tables + * + * Copyright (c) 2020, Pete Batard <[email protected]> + * Copyright (c) 2019, ARM Ltd. All rights reserved. + * Copyright (c) 2018, Andrei Warkentin <[email protected]> + * 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__ diff --git a/board/raspberrypi/rpi/dsdt.asl b/board/raspberrypi/rpi/dsdt.asl new file mode 100644 index 00000000000..c89b08d5ea1 --- /dev/null +++ b/board/raspberrypi/rpi/dsdt.asl @@ -0,0 +1,254 @@ +/** @file + * + * Differentiated System Definition Table (DSDT) + * + * Copyright (c) 2020, Pete Batard <[email protected]> + * Copyright (c) 2018-2020, Andrey Warkentin <[email protected]> + * 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" + } +} diff --git a/board/raspberrypi/rpi/emmc.asl b/board/raspberrypi/rpi/emmc.asl new file mode 100644 index 00000000000..63f01362c91 --- /dev/null +++ b/board/raspberrypi/rpi/emmc.asl @@ -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 diff --git a/board/raspberrypi/rpi/gpudevs.asl b/board/raspberrypi/rpi/gpudevs.asl new file mode 100644 index 00000000000..a3077a9c3bd --- /dev/null +++ b/board/raspberrypi/rpi/gpudevs.asl @@ -0,0 +1,372 @@ +/** @file + * + * [DSDT] Devices behind the GPU. + * + * Copyright (c) 2018-2020, Andrey Warkentin <[email protected]> + * 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) + } +}
\ No newline at end of file diff --git a/board/raspberrypi/rpi/pci.asl b/board/raspberrypi/rpi/pci.asl new file mode 100644 index 00000000000..a7a09df5cd9 --- /dev/null +++ b/board/raspberrypi/rpi/pci.asl @@ -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
\ No newline at end of file diff --git a/board/raspberrypi/rpi/pep.asl b/board/raspberrypi/rpi/pep.asl new file mode 100644 index 00000000000..87469e2e5a9 --- /dev/null +++ b/board/raspberrypi/rpi/pep.asl @@ -0,0 +1,90 @@ +/** @file + * + * Platform Extension Plugin (PEP). + * + * Copyright (c) 2019, ARM Ltd. All rights reserved. + * Copyright (c) 2018, Andrey Warkentin <[email protected]> + * 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 + }) +} diff --git a/board/raspberrypi/rpi/rhpx.asl b/board/raspberrypi/rpi/rhpx.asl new file mode 100644 index 00000000000..214b55c6564 --- /dev/null +++ b/board/raspberrypi/rpi/rhpx.asl @@ -0,0 +1,195 @@ +/** @file + * + * [DSDT] RHProxy device to enable WinRT API (RHPX) + * + * Copyright (c) 2018, Andrey Warkentin <[email protected]> + * 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 + } + }) +} diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index ab5ea85cf9f..9122f33d88d 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -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 diff --git a/board/raspberrypi/rpi/sdhc.asl b/board/raspberrypi/rpi/sdhc.asl new file mode 100644 index 00000000000..3feac14acf2 --- /dev/null +++ b/board/raspberrypi/rpi/sdhc.asl @@ -0,0 +1,111 @@ +/** @file + * + * [DSDT] SD controller/card definition (SDHC) + * + * Copyright (c) 2020, Pete Batard <[email protected]> + * Copyright (c) 2018, Andrey Warkentin <[email protected]> + * 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 + } + } +}
\ No newline at end of file diff --git a/board/raspberrypi/rpi/uart.asl b/board/raspberrypi/rpi/uart.asl new file mode 100644 index 00000000000..78dc9a74dfc --- /dev/null +++ b/board/raspberrypi/rpi/uart.asl @@ -0,0 +1,208 @@ +/** @file + * + * [DSDT] Serial devices (UART). + * + * Copyright (c) 2021, ARM Limited. All rights reserved. + * Copyright (c) 2020, Pete Batard <[email protected]> + * Copyright (c) 2018, Andrey Warkentin <[email protected]> + * 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) + } + } +} |
