/** @file
|
SSDT for FVP PCIe
|
|
Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
|
#include "ArmPlatform.h"
|
|
/*
|
See ACPI 6.1 Section 6.2.13
|
|
There are two ways that _PRT can be used.
|
|
In the first model, a PCI Link device is used to provide additional
|
configuration information such as whether the interrupt is Level or
|
Edge triggered, it is active High or Low, Shared or Exclusive, etc.
|
|
In the second model, the PCI interrupts are hardwired to specific
|
interrupt inputs on the interrupt controller and are not
|
configurable. In this case, the Source field in _PRT does not
|
reference a device, but instead contains the value zero, and the
|
Source Index field contains the global system interrupt to which the
|
PCI interrupt is hardwired.
|
|
We use the first model with link indirection to set the correct
|
interrupt type as PCI defaults (Level Triggered, Active Low) are not
|
compatible with GICv2.
|
*/
|
#define LNK_DEVICE(Unique_Id, Link_Name, irq) \
|
Device (Link_Name) { \
|
Name (_HID, EISAID("PNP0C0F")) \
|
Name (_UID, Unique_Id) \
|
Name (_PRS, ResourceTemplate() { \
|
Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { irq } \
|
}) \
|
Method (_CRS, 0) { Return (_PRS) } \
|
Method (_SRS, 1) { } \
|
Method (_DIS) { } \
|
}
|
|
#define PRT_ENTRY(Address, Pin, Link) \
|
Package (4) { \
|
Address, /* uses the same format as _ADR */ \
|
Pin, /* The PCI pin number of the device (0-INTA, 1-INTB, 2-INTC, 3-INTD) */ \
|
Link, /* Interrupt allocated via Link device */ \
|
Zero /* global system interrupt number (no used) */ \
|
}
|
|
/*
|
See Reference [1] 6.1.1
|
"High word Device #, Low word Function #. (for example, device 3,
|
function 2 is 0x00030002). To refer to all the functions on a device #,
|
use a function number of FFFF)."
|
*/
|
#define ROOT_PRT_ENTRY(Pin, Link) PRT_ENTRY (0x0000FFFF, Pin, Link) // Device 0 for Bridge.
|
|
DefinitionBlock ("SsdtPci.aml", "SSDT", 2, "ARMLTD", "FVP-REVC", 1) {
|
Scope(_SB) {
|
//
|
// PCI Root Complex
|
//
|
LNK_DEVICE (1, LNKA, 168)
|
LNK_DEVICE (2, LNKB, 169)
|
LNK_DEVICE (3, LNKC, 170)
|
LNK_DEVICE (4, LNKD, 171)
|
|
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, 1) // Initially mark the PCI coherent
|
|
// Root Complex 0
|
Device (RP0) {
|
Name (_ADR, 0xF0000000) // Dev 0, Func 0
|
}
|
|
// PCI Routing Table
|
Name (_PRT, Package () {
|
ROOT_PRT_ENTRY (0, LNKA), // INTA
|
ROOT_PRT_ENTRY (1, LNKB), // INTB
|
ROOT_PRT_ENTRY (2, LNKC), // INTC
|
ROOT_PRT_ENTRY (3, LNKD), // INTD
|
})
|
// Root complex resources
|
Method (_CRS, 0, Serialized) {
|
Name (RBUF, ResourceTemplate () {
|
WordBusNumber ( // Bus numbers assigned to this root
|
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
|
)
|
|
DWordMemory ( // 32-bit BAR Windows
|
ResourceProducer,
|
PosDecode,
|
MinFixed,
|
MaxFixed,
|
Cacheable,
|
ReadWrite,
|
0x00000000, // Granularity
|
0x50000000, // Min Base Address
|
0x57FFFFFF, // Max Base Address
|
0x00000000, // Translate
|
0x08000000 // Length
|
)
|
|
QWordMemory ( // 64-bit BAR Windows
|
ResourceProducer,
|
PosDecode,
|
MinFixed,
|
MaxFixed,
|
Cacheable,
|
ReadWrite,
|
0x00000000, // Granularity
|
0x4000000000, // Min Base Address
|
0x40FFFFFFFF, // Max Base Address
|
0x00000000, // Translate
|
0x100000000 // Length
|
)
|
|
DWordIo ( // IO window
|
ResourceProducer,
|
MinFixed,
|
MaxFixed,
|
PosDecode,
|
EntireRange,
|
0x00000000, // Granularity
|
0x00000000, // Min Base Address
|
0x007fffff, // Max Base Address
|
0x5f800000, // Translate
|
0x00800000, // Length
|
,
|
,
|
,
|
TypeTranslation
|
)
|
}) // Name (RBUF)
|
|
Return (RBUF)
|
} // 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) {
|
// 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)
|
|
// Only allow native hot plug control if OS supports:
|
// * ASPM
|
// * Clock PM
|
// * MSI/MSI-X
|
If(LNotEqual (And (SUPP, 0x16), 0x16)) {
|
And (CTRL, 0x1E, CTRL) // Mask bit 0 (and undefined bits)
|
}
|
|
// 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
|
} // PCI0
|
}
|
}
|