Skip to content

Commit

Permalink
Platform/RPi4: Add XHCI and MCFG ACPI tables
Browse files Browse the repository at this point in the history
Since the RPi4 PCIe host bridge is not ECAM compliant, we cannot
expose it as a host bridge to the OS via ACPI, so we add a dummy
MCFG table. However, given the hardwired nature of this platform,
we can expose the xHCI controller that is guaranteed to live at
the base of the MMIO32 BAR window as a platform device directly.

It should be noted that the xHCI table is not finalized at this
stage, as Windows xHCI support is still a major question mark.

Signed-off-by: Pete Batard <pete@akeo.ie>
  • Loading branch information
andreiw authored and pbatard committed Dec 17, 2019
1 parent 62956e3 commit 5779a50
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Platform/RaspberryPi/RPi4/AcpiTables/AcpiTables.inf
Expand Up @@ -29,6 +29,7 @@
Fadt.aslc
Dbg2.aslc
Gtdt.aslc
Mcfg.aslc
Dsdt.asl
Csrt.aslc
Spcr.aslc
Expand All @@ -39,6 +40,8 @@
EmbeddedPkg/EmbeddedPkg.dec
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
Silicon/Broadcom/Bcm27xx/Bcm27xx.dec
Silicon/Broadcom/Bcm283x/Bcm283x.dec

[FixedPcd]
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
Expand All @@ -47,6 +50,8 @@
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
gArmTokenSpaceGuid.PcdGicDistributorBase
gBcm27xxTokenSpaceGuid.PcdBcm27xxPciCpuMmioAdr
gBcm27xxTokenSpaceGuid.PcdBcm27xxPciRegBase
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress
1 change: 1 addition & 0 deletions Platform/RaspberryPi/RPi4/AcpiTables/Dsdt.asl
Expand Up @@ -22,6 +22,7 @@ DefinitionBlock ("Dsdt.aml", "DSDT", 5, "MSFT", "EDK2", 2)
{
include ("Sdhc.asl")
include ("Pep.asl")
include ("Xhci.asl")

Device (CPU0)
{
Expand Down
81 changes: 81 additions & 0 deletions Platform/RaspberryPi/RPi4/AcpiTables/Mcfg.aslc
@@ -0,0 +1,81 @@
/** @file
*
* Memory Mapped Configuration Address Space table (MCFG)
*
* Copyright (c) 2019, Pete Batard <pete@akeo.ie>
* Copyright (c) 2013-2015 Intel Corporation.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/

#include <IndustryStandard/Acpi.h>
#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>

#include "AcpiTables.h"

//
// Multiple APIC Description Table
//
#pragma pack (1)

#define RPI_ACPI_OEM_MCFG_REVISION 0x00000001
//
// The Pi 4 is not ECAM compliant so, ideally, we would just skip populating
// an allocation structure. However, GenFw throws 'MCFG length check failed'
// when the number of allocation structures is zero, so we need at least one.
//
#define RPI_ACPI_ALLOCATION_STRUCTURE_COUNT 1

typedef struct {
EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE AllocationStructure[RPI_ACPI_ALLOCATION_STRUCTURE_COUNT];
} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE;

STATIC EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE Mcfg =
{
{
//------------------------------------------------------------------------
// ACPI Table Header
//------------------------------------------------------------------------
{
EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_DESCRIPTION_TABLE),
EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
0x00, // Checksum calculated at runtime.
EFI_ACPI_OEM_ID, // OEMID is a 6 bytes long field "BC2836"
EFI_ACPI_OEM_TABLE_ID, // OEM table identification(8 bytes long) "RPI4EDK2"
EFI_ACPI_OEM_REVISION, // OEM revision number
EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID
EFI_ACPI_CREATOR_REVISION // ASL compiler revision number
},
//------------------------------------------------------------------------
// Reserved
//------------------------------------------------------------------------
0x0000000000000000, // Reserved
},

//------------------------------------------------------------------------
// MCFG specific fields
//------------------------------------------------------------------------
{
{
//
// Using (-1) as the base address tells the OS to ignore it.
//
0xFFFFFFFFFFFFFFFFULL, // BaseAddress
0x0000, // PciSegmentGroupNumber
0x00, // StartBusNumber
0x00, // EndBusNumber
0x00000000 // Reserved
}
}
};

#pragma pack()

//
// Reference the table being generated to prevent the optimizer from removing
// the data structure from the executable
//
VOID* CONST ReferenceAcpiTable = &Mcfg;
140 changes: 140 additions & 0 deletions Platform/RaspberryPi/RPi4/AcpiTables/Xhci.asl
@@ -0,0 +1,140 @@
/** @file
*
* Copyright (c) 2019 Linaro, Limited. All rights reserved.
* Copyright (c) 2019 Andrei Warkentin <andrey.warkentin@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/

#include <IndustryStandard/Bcm2711.h>

/*
* The following can be used to remove parenthesis from
* defined macros that the compiler complains about.
*/
#define _REMOVE_PAREN(...) __VA_ARGS__
#define REMOVE_PAREN(x) _REMOVE_PAREN x

/*
* According to UEFI boot log for the VLI device on Pi 4.
*/
#define XHCI_REG_LENGTH 0x1000

Device (SCB0) {
Name (_HID, "ACPI0004")

This comment has been minimized.

Copy link
@Googulator

Googulator Dec 18, 2019

PNP0A05 seems to be a better fit

This comment has been minimized.

Copy link
@andreiw

andreiw Dec 23, 2019

Author Member

Absolutely not. If you have _CRS describing resources consumed by children devices, it must be ACPI0004.

Here is what the spec says about PNP0A05 - . This ID should only be used for containers that
do not produce resources for consumption by child devices. Any system resources claimed
by a PNP0A05 device’s _CRS object must be consumed by the container itself.

Name (_UID, 0x0)
Name (_CCA, 0x0)

Method (_CRS, 0, Serialized) { // _CRS: Current Resource Settings
/*
* Container devices with _DMA must have _CRS, meaning SCB0
* to provide all resources that XHC0 consumes (except
* interrupts).
*/
Name (RBUF, ResourceTemplate () {
QWordMemory(ResourceProducer,
,
MinFixed,
MaxFixed,
NonCacheable,
ReadWrite,
0x0,
0xAAAA, // MIN

This comment has been minimized.

Copy link
@Googulator

Googulator Dec 18, 2019

These need to match the values in _DMA

This comment has been minimized.

Copy link
@pbatard

pbatard Dec 18, 2019

Member

This is being discussed on the edk2 mailing list.
Please see https://edk2.groups.io/g/devel/topic/68791816#52363 and feel free to participate there if you have comment, as this is the better place to review.

Bear in mind that the code you are seeing here is aimed at the integration process, which is carried out on the EDK2 mailing list.

This comment has been minimized.

Copy link
@andreiw

andreiw Dec 23, 2019

Author Member

That's not true either. The ACPI spec is pretty bad about legibility, but _CRS for ACPI0004 describes resources CONSUMED by the child, that is - the XHCI BAR space in this case. The DMA range (i.e. 3GB of RAM) cannot be described in _CRS, that would amount to a conflict and an NT PSOD - trust me, I tried before figuring out what the relationship was supposed to be.

0xBBBA, // MAX
0x0,
0x1111, // LEN
,
,
MMIO
)
})
CreateQwordField (RBUF, MMIO._MIN, MMBA)
CreateQwordField (RBUF, MMIO._MAX, MMBE)
CreateQwordField (RBUF, MMIO._LEN, MMLE)
Store (REMOVE_PAREN(PCIE_CPU_MMIO_WINDOW), MMBA)
Store (REMOVE_PAREN(PCIE_CPU_MMIO_WINDOW), MMBE)
Store (XHCI_REG_LENGTH, MMLE)
Add (MMBA, MMLE, MMBE)
Return (RBUF)
}

Name (_DMA, ResourceTemplate() {
/*
* XHC0 is limited to DMA to first 3GB. Note this
* only applies to PCIe, not GENET or other devices
* next to the A72.
*/
QWordMemory(ResourceConsumer,
,
MinFixed,
MaxFixed,
NonCacheable,
ReadWrite,
0x0,
0x0, // MIN
0xbfffffff, // MAX
0x0, // TRA

This comment has been minimized.

Copy link
@Googulator

Googulator Dec 18, 2019

I'm not sure if TRA == 0 is correct, the DTSI files seem to indicate a translation value of 0x600000000

This comment has been minimized.

Copy link
@andreiw

andreiw Dec 23, 2019

Author Member

Where do you see that? Xhci via USB works in UEFI and there is no DMA translation.

0xc0000000, // LEN
,
,
)
})

Device (XHC0)
{
Name (_HID, "11063483") // _HID: Hardware ID
Name (_CID, "PNP0D10") // _CID: Hardware ID
Name (_UID, 0x0) // _UID: Unique ID
Name (_CCA, 0x0) // _CCA: Cache Coherency Attribute

Method (_CRS, 0, Serialized) { // _CRS: Current Resource Settings
Name (RBUF, ResourceTemplate () {
QWordMemory(ResourceConsumer,
,
MinFixed,
MaxFixed,
NonCacheable,
ReadWrite,
0x0,
0xAAAA, // MIN
0xBBBA, // MAX
0x0,
0x1111, // LEN
,
,
MMIO
)
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, ) {
175
}
})
CreateQwordField (RBUF, MMIO._MIN, MMBA)
CreateQwordField (RBUF, MMIO._MAX, MMBE)
CreateQwordField (RBUF, MMIO._LEN, MMLE)
Store (REMOVE_PAREN(PCIE_CPU_MMIO_WINDOW), MMBA)
Store (REMOVE_PAREN(PCIE_CPU_MMIO_WINDOW), MMBE)
Store (XHCI_REG_LENGTH, MMLE)
Add (MMBA, MMLE, MMBE)
Return (RBUF)
}

Method (_INI, 0, Serialized) {
OperationRegion (PCFG, SystemMemory, REMOVE_PAREN(PCIE_REG_BASE) + PCIE_EXT_CFG_DATA, 0x1000)
Field (PCFG, AnyAcc, NoLock, Preserve) {
Offset (0),
VNID, 16, // Vendor ID
DVID, 16, // Device ID
CMND, 16, // Command register
STAT, 16, // Status register
}

// Set command register to:
// 1) decode MMIO (set bit 1)
// 2) enable DMA (set bit 2)
// 3) enable interrupts (clear bit 10)
Debug = "xHCI enable"
Store (0x6, CMND)
}
}
}

0 comments on commit 5779a50

Please sign in to comment.