summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Martin <olivier.martin@arm.com>2015-05-11 17:48:39 +0000
committeroliviermartin <oliviermartin@Edk2>2015-05-11 17:48:39 +0000
commit4595449b3e018b68ea0a8bb9abf32c2f36e9438e (patch)
tree78494778961f9e5cf04231b9a0e6a77e55e07bd4
parentf66eab9b9c9ef78e74658e087fe9f711a62fd401 (diff)
downloadedk2-platforms-4595449b3e018b68ea0a8bb9abf32c2f36e9438e.tar.xz
ArmPlatformPkg/ArmJunoPkg: Added PCI support
Added driver for the Juno R1 root complex. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> Reviewed-by: Ronald Cron <Ronald.Cron@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17412 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec8
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.c199
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.h324
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf76
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c642
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciRootBridge.c745
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.c167
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.h111
8 files changed, 2272 insertions, 0 deletions
diff --git a/ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec b/ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec
index 7a7466c67c..040a906ac1 100644
--- a/ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec
+++ b/ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec
@@ -31,7 +31,15 @@
[Guids.common]
gArmJunoTokenSpaceGuid = { 0xa1147a20, 0x3144, 0x4f8d, { 0x82, 0x95, 0xb4, 0x83, 0x11, 0xc8, 0xe4, 0xa4 } }
+[PcdsFeatureFlag.common]
+ gArmJunoTokenSpaceGuid.PcdPciMaxPayloadFixup|FALSE|BOOLEAN|0x00000013
+
[PcdsFixedAtBuild.common]
+ gArmJunoTokenSpaceGuid.PcdPcieControlBaseAddress|0x7FF20000|UINT64|0x0000000B
+ gArmJunoTokenSpaceGuid.PcdPcieRootPortBaseAddress|0x7FF30000|UINT64|0x0000000C
+ gArmJunoTokenSpaceGuid.PcdPciConfigurationSpaceBaseAddress|0x40000000|UINT64|0x00000011
+ gArmJunoTokenSpaceGuid.PcdPciConfigurationSpaceSize|0x10000000|UINT64|0x00000012
+
gArmJunoTokenSpaceGuid.PcdSynopsysUsbOhciBaseAddress|0x7FFB0000|UINT32|0x00000004
gArmJunoTokenSpaceGuid.PcdSynopsysUsbEhciBaseAddress|0x7FFC0000|UINT32|0x00000005
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.c
new file mode 100644
index 0000000000..e1a6b749e4
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.c
@@ -0,0 +1,199 @@
+/** @file
+* Pci Host Bridge support for the Xpress-RICH3 PCIe Root Complex
+*
+* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "PciHostBridge.h"
+
+#include <Guid/EventGroup.h>
+
+/**
+ * PCI Root Bridge Description
+ */
+typedef struct {
+ UINT32 AcpiUid;
+ UINT64 MemAllocAttributes;
+} PCI_ROOT_BRIDGE_DESC;
+
+PCI_ROOT_BRIDGE_DESC PciRbDescriptions = {
+ 0, // AcpiUid
+ PCI_MEMORY_ALLOCATION_ATTRIBUTES // MemAllocAttributes
+};
+
+/**
+ * Template for PCI Host Bridge Instance
+ **/
+STATIC CONST PCI_HOST_BRIDGE_INSTANCE
+gPciHostBridgeInstanceTemplate = {
+ PCI_HOST_BRIDGE_SIGNATURE, //Signature
+ NULL, // Handle
+ NULL, // ImageHandle
+ NULL, // RootBridge
+ TRUE, // CanRestarted
+ NULL, // CpuIo
+ NULL, // Metronome
+ { // ResAlloc
+ PciHbRaNotifyPhase, // ResAlloc.NotifyPhase
+ PciHbRaGetNextRootBridge, // ResAlloc.GetNextRootBridge
+ PciHbRaGetAllocAttributes, // ResAlloc.GetAllocAttributes
+ PciHbRaStartBusEnumeration, // ResAlloc.StartBusEnumeration
+ PciHbRaSetBusNumbers, // ResAlloc.SetBusNumbers
+ PciHbRaSubmitResources, // ResAlloc.SubmitResources
+ PciHbRaGetProposedResources, // ResAlloc.GetProposedResources
+ PciHbRaPreprocessController // ResAlloc.PreprocessController
+ }
+};
+PCI_HOST_BRIDGE_INSTANCE* gpPciHostBridgeInstance;
+
+EFI_STATUS
+HostBridgeConstructor (
+ IN OUT PCI_HOST_BRIDGE_INSTANCE** Instance,
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ PCI_HOST_BRIDGE_INSTANCE* HostBridge;
+
+ PCI_TRACE ("HostBridgeConstructor()");
+
+ if (Instance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridge = AllocateCopyPool (sizeof (PCI_HOST_BRIDGE_INSTANCE), &gPciHostBridgeInstanceTemplate);
+ if (HostBridge == NULL) {
+ PCI_TRACE ("HostBridgeConstructor(): FAIL to allocate resources");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // It will also create a device handle for the PCI Host Bridge (as HostBridge->Handle == NULL)
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &HostBridge->Handle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ PCI_TRACE ("HostBridgeConstructor(): FAIL to install resource allocator");
+ FreePool (HostBridge);
+ return EFI_DEVICE_ERROR;
+ } else {
+ PCI_TRACE ("HostBridgeConstructor(): SUCCEED to install resource allocator");
+ }
+
+ Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)(&(HostBridge->CpuIo)));
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)(&(HostBridge->Metronome)));
+ ASSERT_EFI_ERROR (Status);
+
+ HostBridge->ImageHandle = ImageHandle;
+
+ *Instance = HostBridge;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HostBridgeDestructor (
+ IN PCI_HOST_BRIDGE_INSTANCE* HostBridge
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ HostBridge->Handle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
+ NULL
+ );
+
+ if (HostBridge->RootBridge) {
+ PciRbDestructor (HostBridge->RootBridge);
+ }
+
+ FreePool (HostBridge);
+
+ return Status;
+}
+
+/**
+ Entry point of this driver
+
+ @param ImageHandle Handle of driver image
+ @param SystemTable Point to EFI_SYSTEM_TABLE
+
+ @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
+ @retval EFI_DEVICE_ERROR Can not install the protocol instance
+ @retval EFI_SUCCESS Success to initialize the Pci host bridge.
+**/
+EFI_STATUS
+EFIAPI
+PciHostBridgeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ PCI_TRACE ("PciHostBridgeEntryPoint()");
+
+ // Creation of the PCI Host Bridge Instance
+ Status = HostBridgeConstructor (&gpPciHostBridgeInstance, ImageHandle);
+ if (EFI_ERROR (Status)) {
+ PCI_TRACE ("PciHostBridgeEntryPoint(): ERROR: Fail to construct PCI Host Bridge.");
+ return Status;
+ }
+
+ // Creation of the PCIe Root Bridge
+ Status = PciRbConstructor (gpPciHostBridgeInstance, PciRbDescriptions.AcpiUid, PciRbDescriptions.MemAllocAttributes);
+ if (EFI_ERROR (Status)) {
+ PCI_TRACE ("PciHostBridgeEntryPoint(): ERROR: Fail to construct PCI Root Bridge.");
+ return Status;
+ }
+ ASSERT (gpPciHostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
+
+ // PCI 32bit Memory Space
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ PCI_MEM32_BASE,
+ PCI_MEM32_SIZE,
+ 0
+ );
+
+ // PCI 64bit Memory Space
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ PCI_MEM64_BASE,
+ PCI_MEM64_SIZE,
+ 0
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciHostBridgeUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ // Free Reserved memory space in GCD
+ gDS->RemoveMemorySpace (PCI_MEM32_BASE, PCI_MEM32_SIZE);
+ gDS->RemoveMemorySpace (PCI_MEM64_BASE, PCI_MEM64_SIZE);
+
+ // Free the allocated memory
+ Status = HostBridgeDestructor (gpPciHostBridgeInstance);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.h b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.h
new file mode 100644
index 0000000000..e53f4fa3a8
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.h
@@ -0,0 +1,324 @@
+/** @file
+* Header containing the structure specific to the Xpress-RICH3 PCIe Root Complex
+*
+* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __PCIHOSTBRIDGE_H
+#define __PCIHOSTBRIDGE_H
+
+#include <PiDxe.h>
+
+#include "XPressRich3.h"
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/CpuIo2.h>
+#include <Protocol/Metronome.h>
+
+#define PCI_TRACE(txt) DEBUG((EFI_D_VERBOSE, "ARM_PCI: " txt "\n"))
+
+#define PCIE_ROOTPORT_WRITE32(Add, Val) { UINT32 Value = (UINT32)(Val); CpuIo->Mem.Write (CpuIo,EfiCpuIoWidthUint32,(UINT64)(PcdGet64 (PcdPcieRootPortBaseAddress)+(Add)),1,&Value); }
+#define PCIE_ROOTPORT_READ32(Add, Val) { CpuIo->Mem.Read (CpuIo,EfiCpuIoWidthUint32,(UINT64)(PcdGet64 (PcdPcieRootPortBaseAddress)+(Add)),1,&Val); }
+
+#define PCIE_CONTROL_WRITE32(Add, Val) { UINT32 Value = (UINT32)(Val); CpuIo->Mem.Write (CpuIo,EfiCpuIoWidthUint32,(UINT64)(PcdGet64 (PcdPcieControlBaseAddress)+(Add)),1,&Value); }
+#define PCIE_CONTROL_READ32(Add, Val) { CpuIo->Mem.Read (CpuIo,EfiCpuIoWidthUint32,(UINT64)(PcdGet64 (PcdPcieControlBaseAddress)+(Add)),1,&Val); }
+
+/**
+ * PCI Root Bridge Device Path (ACPI Device Node + End Node)
+ */
+typedef struct {
+ ACPI_HID_DEVICE_PATH Acpi;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+typedef enum {
+ ResTypeIo = 0,
+ ResTypeMem32,
+ ResTypePMem32,
+ ResTypeMem64,
+ ResTypePMem64,
+ ResTypeMax
+} PCI_RESOURCE_TYPE;
+
+#define ACPI_SPECFLAG_PREFETCHABLE 0x06
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+
+typedef struct {
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Alignment;
+} PCI_RESOURCE_ALLOC;
+
+typedef struct _PCI_HOST_BRIDGE_INSTANCE PCI_HOST_BRIDGE_INSTANCE;
+
+/**
+ * PCI Root Bridge Instance structure
+ **/
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;
+ //
+ // Set Type of memory allocation (could be EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
+ // and EFI_PCI_HOST_BRIDGE_MEM64_DECODE).
+ //
+ UINT64 MemAllocAttributes;
+ PCI_RESOURCE_ALLOC ResAlloc[ResTypeMax];
+ UINTN BusStart;
+ UINTN BusLength;
+ UINT64 Supports;
+ UINT64 Attributes;
+ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+} PCI_ROOT_BRIDGE_INSTANCE;
+
+/**
+ * PCI Host Bridge Instance structure
+ **/
+struct _PCI_HOST_BRIDGE_INSTANCE {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_HANDLE ImageHandle;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
+ //
+ // The enumeration cannot be restarted after the process goes into the non initial
+ // enumeration phase.
+ //
+ BOOLEAN CanRestarted;
+ EFI_CPU_IO2_PROTOCOL *CpuIo;
+ EFI_METRONOME_ARCH_PROTOCOL *Metronome;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc;
+};
+
+#define PCI_HOST_BRIDGE_SIGNATURE SIGNATURE_32 ('e', 'h', 's', 't')
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('e', '2', 'p', 'b')
+#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) CR (a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
+#define INSTANCE_FROM_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+/**
+ * PCI Host Bridge Resource Allocator Functions
+ **/
+EFI_STATUS PciHbRaNotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ );
+
+EFI_STATUS PciHbRaGetNextRootBridge (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ );
+
+EFI_STATUS PciHbRaGetAllocAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ );
+
+EFI_STATUS PciHbRaStartBusEnumeration (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ );
+
+EFI_STATUS PciHbRaSetBusNumbers (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ );
+
+EFI_STATUS PciHbRaSubmitResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ );
+
+EFI_STATUS PciHbRaGetProposedResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ );
+
+EFI_STATUS PciHbRaPreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ );
+
+
+/**
+ * PCI Root Bridge
+ **/
+EFI_STATUS PciRbPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS PciRbPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS PciRbMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS PciRbMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS PciRbIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS PciRbIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS PciRbPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS PciRbPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS PciRbCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+EFI_STATUS PciRbMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+EFI_STATUS PciRbUnMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+EFI_STATUS PciRbAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS PciRbFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ );
+
+EFI_STATUS PciRbFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+EFI_STATUS PciRbSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+EFI_STATUS PciRbGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supports,
+ OUT UINT64 *Attributes
+ );
+
+EFI_STATUS PciRbConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+/**
+ * PCI Root Bridge Functions
+ **/
+EFI_STATUS
+PciRbConstructor (
+ IN PCI_HOST_BRIDGE_INSTANCE *HostBridge,
+ IN UINT32 PciAcpiUid,
+ IN UINT64 MemAllocAttributes
+ );
+
+EFI_STATUS
+PciRbDestructor (
+ IN PCI_ROOT_BRIDGE_INSTANCE* RootBridge
+ );
+
+EFI_STATUS
+HWPciRbInit (
+ IN EFI_CPU_IO2_PROTOCOL *CpuIo
+ );
+
+#endif
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf
new file mode 100644
index 0000000000..9f526910c4
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -0,0 +1,76 @@
+#/** @file
+# INF file for the Xpress-RICH3 PCIe Root Complex
+#
+# Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PciHostBridge
+ FILE_GUID = C62F4B20-681E-11DF-8F0D-0002A5D5C51B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PciHostBridgeEntryPoint
+ UNLOAD_IMAGE = PciHostBridgeUnload
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ DxeServicesTableLib
+ CacheMaintenanceLib
+ DmaLib
+
+[Sources]
+ PciHostBridge.c
+ PciHostBridgeResourceAllocation.c
+ PciRootBridge.c
+ XPressRich3.c
+
+[Protocols]
+ gEfiPciHostBridgeResourceAllocationProtocolGuid # Produced
+ gEfiPciRootBridgeIoProtocolGuid # Produced
+ gEfiDevicePathProtocolGuid # Produced
+ gEfiCpuIo2ProtocolGuid # Consumed
+ gEfiMetronomeArchProtocolGuid # Consumed
+
+[FeaturePcd]
+ gArmJunoTokenSpaceGuid.PcdPciMaxPayloadFixup
+
+[Pcd.common]
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+
+ gArmPlatformTokenSpaceGuid.PcdPciBusMin
+ gArmPlatformTokenSpaceGuid.PcdPciBusMax
+ gArmPlatformTokenSpaceGuid.PcdPciIoBase
+ gArmPlatformTokenSpaceGuid.PcdPciIoSize
+ gArmPlatformTokenSpaceGuid.PcdPciMmio32Base
+ gArmPlatformTokenSpaceGuid.PcdPciMmio32Size
+ gArmPlatformTokenSpaceGuid.PcdPciMmio64Base
+ gArmPlatformTokenSpaceGuid.PcdPciMmio64Size
+
+ gArmJunoTokenSpaceGuid.PcdPcieControlBaseAddress
+ gArmJunoTokenSpaceGuid.PcdPcieRootPortBaseAddress
+ gArmJunoTokenSpaceGuid.PcdPciConfigurationSpaceBaseAddress
+ gArmJunoTokenSpaceGuid.PcdPciConfigurationSpaceSize
+
+[Depex]
+ gEfiCpuIo2ProtocolGuid AND gEfiMetronomeArchProtocolGuid
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c
new file mode 100644
index 0000000000..de60db7184
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c
@@ -0,0 +1,642 @@
+/** @file
+* Implementation of the Pci Host Bridge Resource Allocation for the Xpress-RICH3 PCIe Root Complex
+*
+* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "PciHostBridge.h"
+
+EFI_STATUS
+PciHbRaNotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 AddrLen;
+ UINTN BitsOfAlignment;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ PCI_TRACE ("PciHbRaNotifyPhase()");
+
+ // Check RootBridge Signature
+ ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
+
+ // The enumeration cannot be restarted after the process has been further than the first phase
+ if (Phase == EfiPciHostBridgeBeginEnumeration) {
+ if (!HostBridgeInstance->CanRestarted) {
+ return EFI_NOT_READY;
+ }
+ } else {
+ HostBridgeInstance->CanRestarted = FALSE;
+ }
+
+ switch (Phase) {
+ case EfiPciHostBridgeBeginEnumeration:
+ PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginEnumeration)");
+ // Resets the host bridge PCI apertures and internal data structures
+ Status = HWPciRbInit (HostBridgeInstance->CpuIo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ break;
+
+ case EfiPciHostBridgeBeginBusAllocation:
+ PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginBusAllocation)");
+ // The bus allocation phase is about to begin
+ break;
+
+ case EfiPciHostBridgeEndBusAllocation:
+ PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndBusAllocation)");
+ // The bus allocation and bus programming phase is complete. All the PCI-to-PCI bridges have been given and written back
+ // a bus number range into their configuration
+ break;
+
+ case EfiPciHostBridgeBeginResourceAllocation:
+ PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginResourceAllocation)");
+ // The resource allocation phase is about to begin.
+ break;
+
+ case EfiPciHostBridgeAllocateResources:
+ PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeAllocateResources)");
+ // Allocates resources per previously submitted requests for all the PCI root bridges. The resources have been submitted to
+ // PciHbRaSubmitResources() before.
+
+ RootBridgeInstance = HostBridgeInstance->RootBridge;
+ if (RootBridgeInstance->ResAlloc[ResTypeIo].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeIo].Alignment) + 1; // Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypeIo].Length;
+
+ Status = gDS->AllocateIoSpace (
+ EfiGcdAllocateAnySearchBottomUp,
+ EfiGcdIoTypeIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+ // If error then ResAlloc[n].Base ==0
+ if (!EFI_ERROR (Status)) {
+ RootBridgeInstance->ResAlloc[ResTypeIo].Base = (UINTN)BaseAddress;
+ }
+ }
+
+ if (RootBridgeInstance->ResAlloc[ResTypeMem32].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem32].Alignment) + 1; // Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem32].Length;
+
+ // Top of the 32bit PCI Memory space
+ BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+
+ // Ensure the allocation is in the 32bit PCI memory space
+ if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
+ RootBridgeInstance->ResAlloc[ResTypeMem32].Base = (UINTN)BaseAddress;
+ }
+ }
+ if (RootBridgeInstance->ResAlloc[ResTypePMem32].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem32].Alignment) + 1; // Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem32].Length;
+
+ // Top of the 32bit PCI Memory space
+ BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+
+ // Ensure the allocation is in the 32bit PCI memory space
+ if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
+ RootBridgeInstance->ResAlloc[ResTypePMem32].Base = (UINTN)BaseAddress;
+ }
+ }
+ if (RootBridgeInstance->ResAlloc[ResTypeMem64].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem64].Alignment) + 1; // Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem64].Length;
+
+ // Top of the 64bit PCI Memory space
+ BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+
+ // Ensure the allocation is in the 64bit PCI memory space
+ if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
+ RootBridgeInstance->ResAlloc[ResTypeMem64].Base = (UINTN)BaseAddress;
+ }
+ }
+ if (RootBridgeInstance->ResAlloc[ResTypePMem64].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem64].Alignment) + 1; //Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem64].Length;
+
+ // Top of the 64bit PCI Memory space
+ BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+
+ // Ensure the allocation is in the 64bit PCI memory space
+ if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
+ RootBridgeInstance->ResAlloc[ResTypePMem64].Base = (UINTN)BaseAddress;
+ }
+ }
+
+ break;
+
+ case EfiPciHostBridgeSetResources:
+ PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeSetResources)");
+ // Programs the host bridge hardware to decode previously allocated resources (proposed resources)
+ // for all the PCI root bridges. The PCI bus driver will now program the resources
+ break;
+
+ case EfiPciHostBridgeFreeResources:
+ PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeFreeResources)");
+ // Deallocates resources that were previously allocated for all the PCI root bridges and resets the
+ // I/O and memory apertures to their initial state.*/
+ break;
+
+ case EfiPciHostBridgeEndResourceAllocation:
+ PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndResourceAllocation)");
+ break;
+
+ case EfiPciHostBridgeEndEnumeration:
+ PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndEnumeration)");
+ break;
+
+ default:
+ DEBUG ((EFI_D_INFO, "PciHbRaNotifyPhase(Phase:%d)\n", Phase));
+ ASSERT (0);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * PciHbRaGetNextRootBridge() returns the next root bridge attached to the 'This' PCI Host Bridge.
+ * As we have only got one PCI Root Bridge in this PCI interface, we return either this root bridge
+ * if it the first time we call this function (*RootBridgeHandle == NULL) or we return EFI_NOT_FOUND
+ **/
+EFI_STATUS
+PciHbRaGetNextRootBridge (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+
+ PCI_TRACE ("PciHbRaGetNextRootBridge()");
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ ASSERT (HostBridgeInstance->RootBridge != NULL);
+
+ //Check RootBridge Signature
+ ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
+
+ if (*RootBridgeHandle == NULL) {
+ *RootBridgeHandle = HostBridgeInstance->RootBridge->Handle;
+ return EFI_SUCCESS;
+ } else if (*RootBridgeHandle == HostBridgeInstance->RootBridge->Handle) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+/** PciHbRaGetAllocAttributes() returns the resource allocation attributes supported by this PCI Root Bridge.
+ * A PCI Root bridge could support these types :
+ * - EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM : does not support separate windows for nonprefetchable and prefetchable memory.
+ * - EFI_PCI_HOST_BRIDGE_MEM64_DECODE : supports 64-bit memory windows
+ **/
+EFI_STATUS
+PciHbRaGetAllocAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+
+ PCI_TRACE ("PciHbRaGetAllocAttributes()");
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ // Check if the RootBridgeHandle is the one managed by this PCI Host Bridge
+ ASSERT (HostBridgeInstance->RootBridge != NULL);
+ if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Attributes = HostBridgeInstance->RootBridge->MemAllocAttributes;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciHbRaStartBusEnumeration (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ VOID *Buffer;
+ UINT8 *Ptr;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+
+ // Fill an ACPI descriptor table with the Bus Number Range. This information will be used by the PCI Bus driver
+ // to set bus numbers to PCI-to-PCI bridge.
+ PCI_TRACE ("PciHbRaStartBusEnumeration()");
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ Buffer = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = (UINT8 *)Buffer;
+
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; // QWORD Address space Descriptor
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Len = 0x2B; // Length of this descriptor in bytes not including the first two fields
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS; // Resource Type Bus Number Range
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->GenFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->SpecificFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrSpaceGranularity = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin = HostBridgeInstance->RootBridge->BusStart; // Bus Start
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMax = 0; // Bus Max
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrTranslationOffset = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
+
+ Ptr = Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
+
+ *Configuration = Buffer;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciHbRaSetBusNumbers (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ UINT8 *Ptr;
+ UINTN BusStart;
+ UINTN BusEnd;
+ UINTN BusLen;
+
+ PCI_TRACE ("PciHbRaSetBusNumbers()");
+
+ Ptr = Configuration;
+ if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the passed ACPI descriptor table define a Bus Number Range
+ if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the Configuration only passed one ACPI Descriptor (+ End Descriptor)
+ if (*((UINT8*)(Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR))) != ACPI_END_TAG_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ ASSERT (HostBridgeInstance->RootBridge != NULL);
+ if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
+ BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
+ BusEnd = BusStart + BusLen - 1;
+
+ ASSERT (BusStart <= BusEnd); // We should at least have PCI_BUS_ROOT and PCI_SWITCH_BUS
+ ASSERT ((BusStart >= HostBridgeInstance->RootBridge->BusStart) && (BusLen <= HostBridgeInstance->RootBridge->BusLength));
+
+ HostBridgeInstance->RootBridge->BusStart = BusStart;
+ HostBridgeInstance->RootBridge->BusLength = BusLen;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * This function is used to submit all the I/O and memory resources that are required by the specified
+ * PCI root bridge.
+ **/
+EFI_STATUS
+PciHbRaSubmitResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Ptr;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+ PCI_RESOURCE_TYPE ResType;
+
+ PCI_TRACE ("PciHbRaSubmitResources()");
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the ACPI Descriptor tables is conformed
+ Ptr = (UINT8 *)Configuration;
+ while (*Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // QWORD Address Space descriptor
+ Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
+ }
+ if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { // End tag
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check the RootBridgeHandle
+ RootBridgeInstance = HostBridgeInstance->RootBridge;
+ ASSERT (RootBridgeInstance != NULL);
+ if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr = (UINT8 *)Configuration;
+ while ( *Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // While the entry is an ACPI Descriptor Table
+ Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
+
+ // Check if the description is valid
+ if (Desc->AddrLen > 0xffffffff) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Desc->AddrRangeMax >= 0xffffffff) || (Desc->AddrRangeMax != (GetPowerOfTwo64 (Desc->AddrRangeMax + 1) - 1))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (Desc->ResType) {
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:
+ // Check invalid Address Space Granularity
+ if ((Desc->AddrSpaceGranularity != 32) && (Desc->AddrSpaceGranularity != 64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // check the memory resource request is supported by PCI root bridge
+ if (RootBridgeInstance->MemAllocAttributes == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM && Desc->SpecificFlag == 0x06) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Desc->AddrSpaceGranularity == 32) {
+ if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
+ ResType = ResTypePMem32;
+ } else {
+ ResType = ResTypeMem32;
+ }
+ } else {
+ if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
+ ResType = ResTypePMem64;
+ } else {
+ ResType = ResTypeMem64;
+ }
+ }
+ RootBridgeInstance->ResAlloc[ResType].Length = Desc->AddrLen;
+ RootBridgeInstance->ResAlloc[ResType].Alignment = Desc->AddrRangeMax;
+ RootBridgeInstance->ResAlloc[ResType].Base = Desc->AddrRangeMin;
+ break;
+ case ACPI_ADDRESS_SPACE_TYPE_IO:
+ RootBridgeInstance->ResAlloc[ResTypeIo].Length = Desc->AddrLen;
+ RootBridgeInstance->ResAlloc[ResTypeIo].Alignment = Desc->AddrRangeMax;
+ RootBridgeInstance->ResAlloc[ResTypeIo].Base = 0;
+ break;
+ default:
+ ASSERT (0); // Could be the case Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS
+ break;
+ }
+ Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Returns the proposed resource settings for the specified PCI root bridge. The resources have been submitted by
+ * PciHbRaSubmitResources() before
+ **/
+EFI_STATUS
+PciHbRaGetProposedResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT32 i;
+ UINT32 ResAllocCount;
+ VOID *Buffer;
+ UINT8 *Ptr;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+
+ PCI_TRACE ("PciHbRaGetProposedResources()");
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ // Check the RootBridgeHandle
+ RootBridgeInstance = HostBridgeInstance->RootBridge;
+ ASSERT (RootBridgeInstance != NULL);
+ if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Count the number of Resource Allocated for this Root Bridge
+ ResAllocCount = 0;
+ for (i = 0; i < ResTypeMax; i++) {
+ if (RootBridgeInstance->ResAlloc[i].Length != 0) ResAllocCount++;
+ }
+
+ if (ResAllocCount == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = AllocateZeroPool (ResAllocCount * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = Buffer;
+ for (i = 0; i < ResTypeMax; i++) {
+ if (RootBridgeInstance->ResAlloc[i].Length != 0) { // Base != 0 if the resource has been allocated
+ Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
+
+ Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Desc->Len = 0x2B;
+ Desc->GenFlag = 0;
+ Desc->AddrRangeMax = 0;
+
+ switch (i) {
+ case ResTypeIo:
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+ Desc->SpecificFlag = 0;
+ Desc->AddrSpaceGranularity = 0;
+ break;
+ case ResTypeMem32:
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Desc->SpecificFlag = 0;
+ Desc->AddrSpaceGranularity = 32;
+ break;
+ case ResTypePMem32:
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
+ Desc->AddrSpaceGranularity = 32;
+ break;
+ case ResTypeMem64:
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Desc->SpecificFlag = 0;
+ Desc->AddrSpaceGranularity = 64;
+ break;
+ case ResTypePMem64:
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
+ Desc->AddrSpaceGranularity = 64;
+ break;
+ }
+ Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base;
+ Desc->AddrTranslationOffset = (RootBridgeInstance->ResAlloc[i].Base != 0) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length;
+ Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+ }
+
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
+
+ *Configuration = Buffer;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciHbRaPreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE* HostBridge;
+ PCI_ROOT_BRIDGE_INSTANCE* RootBridge;
+ UINT32 CapabilityPtr;
+ UINT32 CapabilityEntry;
+ UINT16 CapabilityID;
+ UINT32 DeviceCapability;
+
+ PCI_TRACE ("PciHbRaPreprocessController()");
+
+ if (FeaturePcdGet (PcdPciMaxPayloadFixup)) {
+ // Do Max payload fixup for every devices
+ if (Phase == EfiPciBeforeResourceCollection) {
+ // Get RootBridge Instance from Host Bridge Instance
+ HostBridge = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ RootBridge = HostBridge->RootBridge;
+
+ // Get the first PCI Capability
+ CapabilityPtr = PCI_CAPBILITY_POINTER_OFFSET;
+ RootBridge->Io.Pci.Read (
+ &RootBridge->Io,
+ EfiPciWidthUint8,
+ EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
+ 1,
+ &CapabilityPtr
+ );
+ CapabilityPtr &= 0x1FF;
+
+ // Get Pci Express Capability
+ while (CapabilityPtr != 0) {
+ RootBridge->Io.Pci.Read (
+ &RootBridge->Io,
+ EfiPciWidthUint16,
+ EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
+ 1,
+ &CapabilityEntry
+ );
+
+ CapabilityID = (UINT8)CapabilityEntry;
+
+ // Is PCIe capability ?
+ if (CapabilityID == EFI_PCI_CAPABILITY_ID_PCIEXP) {
+ // Get PCIe Device Capabilities
+ RootBridge->Io.Pci.Read (
+ &RootBridge->Io,
+ EfiPciWidthUint32,
+ EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
+ 1,
+ &DeviceCapability
+ );
+
+ // Force the Max Payload to 128 Bytes (128 Bytes Max Payload Size = 0)
+ DeviceCapability &= ~ ((UINT32)(0x7 << 5 ));
+ // Max Read Request Size to 128 Bytes (128 Bytes Max Read Request Size = 0)
+ DeviceCapability &= ~ ((UINT32)(0x7 << 12));
+ // Enable all error reporting
+ DeviceCapability |= 0xF;
+
+ RootBridge->Io.Pci.Write (
+ &RootBridge->Io,
+ EfiPciWidthUint32,
+ EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
+ 1,
+ &DeviceCapability
+ );
+
+ return EFI_SUCCESS;
+ }
+ CapabilityPtr = (CapabilityEntry >> 8) & 0xFF;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciRootBridge.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciRootBridge.c
new file mode 100644
index 0000000000..10a4575c16
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciRootBridge.c
@@ -0,0 +1,745 @@
+/** @file
+* Implementation of the PCI Root Bridge Protocol for XPress-RICH3 PCIe Root Complex
+*
+* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "PciHostBridge.h"
+
+#include <Library/DevicePathLib.h>
+#include <Library/DmaLib.h>
+
+#define CPUIO_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->CpuIo)
+#define METRONOME_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->Metronome)
+
+/**
+ * PCI Root Bridge Instance Templates
+ */
+STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH gDevicePathTemplate = {
+ {
+ { ACPI_DEVICE_PATH,
+ ACPI_DP,
+ { (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) }
+ },
+ EISA_PNP_ID (0x0A03),
+ 0
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { END_DEVICE_PATH_LENGTH, 0 }
+ }
+};
+
+STATIC CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL gIoTemplate = {
+ 0,
+ PciRbPollMem,
+ PciRbPollIo,
+ {
+ PciRbMemRead,
+ PciRbMemWrite
+ },
+ {
+ PciRbIoRead,
+ PciRbIoWrite
+ },
+ {
+ PciRbPciRead,
+ PciRbPciWrite
+ },
+ PciRbCopyMem,
+ PciRbMap,
+ PciRbUnMap,
+ PciRbAllocateBuffer,
+ PciRbFreeBuffer,
+ PciRbFlush,
+ PciRbGetAttributes,
+ PciRbSetAttributes,
+ PciRbConfiguration,
+ 0
+ };
+
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[ResTypeMax+1];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;
+} RESOURCE_CONFIGURATION;
+
+
+RESOURCE_CONFIGURATION Configuration = {
+ {{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_IO , 0, 0, 0, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 32, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 32, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 64, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 64, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_BUS, 0, 0, 0, 0, 255, 0, 255}},
+ {ACPI_END_TAG_DESCRIPTOR, 0}
+};
+
+
+EFI_STATUS
+PciRbPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ EFI_METRONOME_ARCH_PROTOCOL *Metronome;
+
+ PCI_TRACE ("PciRbPollMem()");
+
+ RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
+ Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // No matter what, always do a single poll.
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay == 0) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks) {
+ Metronome->WaitForTick (Metronome, 1);
+
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS
+PciRbPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ EFI_METRONOME_ARCH_PROTOCOL *Metronome;
+
+ PCI_TRACE ("PciRbPollIo()");
+
+ RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
+ Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // No matter what, always do a single poll.
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay == 0) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks) {
+ Metronome->WaitForTick (Metronome, 1);
+
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS
+PciRbMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ EFI_CPU_IO2_PROTOCOL *CpuIo;
+
+ PCI_TRACE ("PciRbMemRead()");
+
+ RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
+ CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&
+ ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+PciRbMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ EFI_CPU_IO2_PROTOCOL *CpuIo;
+
+ PCI_TRACE ("PciRbMemWrite()");
+
+ RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
+ CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&
+ ((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+PciRbIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_TRACE ("PciRbIoRead()");
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // IO currently unsupported
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+PciRbIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_TRACE ("PciRbIoWrite()");
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // IO currently unsupported
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+PciRbPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 EfiAddress,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ UINT32 Offset;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ EFI_CPU_IO2_PROTOCOL *CpuIo;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
+ UINT64 Address;
+
+ EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
+ RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
+ CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EfiPciAddress->ExtendedRegister) {
+ Offset = EfiPciAddress->ExtendedRegister;
+ } else {
+ Offset = EfiPciAddress->Register;
+ }
+
+ // The UEFI PCI enumerator scans for devices at all possible addresses,
+ // and ignores some PCI rules - this results in some hardware being
+ // detected multiple times. We work around this by faking absent
+ // devices
+ if ((EfiPciAddress->Bus == 0) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {
+ *((UINT32 *)Buffer) = 0xffffffff;
+ return EFI_SUCCESS;
+ }
+ if ((EfiPciAddress->Bus == 1) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {
+ *((UINT32 *)Buffer) = 0xffffffff;
+ return EFI_SUCCESS;
+ }
+
+ // Work around incorrect class ID in the root bridge
+ if ((EfiPciAddress->Bus == 0) && (EfiPciAddress->Device == 0) && (EfiPciAddress->Function == 0) && (Offset == 8)) {
+ *((UINT32 *)Buffer) = 0x06040001;
+ return EFI_SUCCESS;
+ }
+
+ Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |
+ (EfiPciAddress->Device << 15) |
+ (EfiPciAddress->Function << 12) | Offset);
+
+ if ((Address < PCI_ECAM_BASE) || (Address > PCI_ECAM_BASE + PCI_ECAM_SIZE)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+PciRbPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 EfiAddress,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ UINT32 Offset;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ EFI_CPU_IO2_PROTOCOL *CpuIo;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
+ UINT64 Address;
+
+ EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
+ RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
+ CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EfiPciAddress->ExtendedRegister)
+ Offset = EfiPciAddress->ExtendedRegister;
+ else
+ Offset = EfiPciAddress->Register;
+
+ Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |
+ (EfiPciAddress->Device << 15) |
+ (EfiPciAddress->Function << 12) | Offset);
+
+ if (Address < PCI_ECAM_BASE || Address > PCI_ECAM_BASE + PCI_ECAM_SIZE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+PciRbCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Direction;
+ UINTN Stride;
+ UINTN Index;
+ UINT64 Result;
+
+ PCI_TRACE ("PciRbCopyMem()");
+
+ if (Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestAddress == SrcAddress) {
+ return EFI_SUCCESS;
+ }
+
+ Stride = (UINTN)(1 << Width);
+
+ Direction = TRUE;
+ if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
+ Direction = FALSE;
+ SrcAddress = SrcAddress + (Count-1) * Stride;
+ DestAddress = DestAddress + (Count-1) * Stride;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ Status = PciRbMemRead (
+ This,
+ Width,
+ SrcAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = PciRbMemWrite (
+ This,
+ Width,
+ DestAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Direction) {
+ SrcAddress += Stride;
+ DestAddress += Stride;
+ } else {
+ SrcAddress -= Stride;
+ DestAddress -= Stride;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRbMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ DMA_MAP_OPERATION DmaOperation;
+
+ PCI_TRACE ("PciRbMap()");
+
+ if (Operation == EfiPciOperationBusMasterRead) {
+ DmaOperation = MapOperationBusMasterRead;
+ } else if (Operation == EfiPciOperationBusMasterWrite) {
+ DmaOperation = MapOperationBusMasterWrite;
+ } else if (Operation == EfiPciOperationBusMasterCommonBuffer) {
+ DmaOperation = MapOperationBusMasterCommonBuffer;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
+}
+
+EFI_STATUS
+PciRbUnMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ PCI_TRACE ("PciRbUnMap()");
+ return DmaUnmap (Mapping);
+}
+
+EFI_STATUS
+PciRbAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ PCI_TRACE ("PciRbAllocateBuffer()");
+
+ if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
+}
+
+EFI_STATUS
+PciRbFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+ PCI_TRACE ("PciRbFreeBuffer()");
+ return DmaFreeBuffer (Pages, HostAddress);
+}
+
+EFI_STATUS
+PciRbFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ )
+{
+ PCI_TRACE ("PciRbFlush()");
+
+ //TODO: Not supported yet
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRbSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ PCI_TRACE ("PciRbSetAttributes()");
+
+ RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
+
+ if (Attributes) {
+ if ((Attributes & (~(RootBridgeInstance->Supports))) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //TODO: Cannot allowed to change attributes
+ if (Attributes & ~RootBridgeInstance->Attributes) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRbGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ PCI_TRACE ("PciRbGetAttributes()");
+
+ RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
+
+ if (Attributes == NULL && Supported == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Set the return value for Supported and Attributes
+ if (Supported) {
+ *Supported = RootBridgeInstance->Supports;
+ }
+
+ if (Attributes) {
+ *Attributes = RootBridgeInstance->Attributes;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRbConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
+ UINTN Index;
+
+ PCI_TRACE ("PciRbConfiguration()");
+
+ RootBridge = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
+
+ for (Index = 0; Index < ResTypeMax; Index++) {
+ //if (ResAlloc[Index].Length != 0) => Resource allocated
+ if (RootBridge->ResAlloc[Index].Length != 0) {
+ Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->ResAlloc[Index].Base;
+ Configuration.SpaceDesp[Index].AddrRangeMax = RootBridge->ResAlloc[Index].Base + RootBridge->ResAlloc[Index].Length - 1;
+ Configuration.SpaceDesp[Index].AddrLen = RootBridge->ResAlloc[Index].Length;
+ }
+ }
+
+ // Set up Configuration for the bus
+ Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->BusStart;
+ Configuration.SpaceDesp[Index].AddrLen = RootBridge->BusLength;
+
+ *Resources = &Configuration;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRbConstructor (
+ IN PCI_HOST_BRIDGE_INSTANCE *HostBridge,
+ IN UINT32 PciAcpiUid,
+ IN UINT64 MemAllocAttributes
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE* RootBridge;
+ EFI_STATUS Status;
+
+ PCI_TRACE ("PciRbConstructor()");
+
+ // Allocate Memory for the Instance from a Template
+ RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));
+ if (RootBridge == NULL) {
+ PCI_TRACE ("PciRbConstructor(): ERROR: Out of Resources");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
+ CopyMem (&(RootBridge->DevicePath), &gDevicePathTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH));
+ CopyMem (&(RootBridge->Io), &gIoTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL));
+
+ // Set Parent Handle
+ RootBridge->Io.ParentHandle = HostBridge->Handle;
+
+ // Attach the Root Bridge to the PCI Host Bridge Instance
+ RootBridge->HostBridge = HostBridge;
+
+ // Set Device Path for this Root Bridge
+ RootBridge->DevicePath.Acpi.UID = PciAcpiUid;
+
+ RootBridge->BusStart = FixedPcdGet32 (PcdPciBusMin);
+ RootBridge->BusLength = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
+
+ // PCI Attributes
+ RootBridge->Supports = 0;
+ RootBridge->Attributes = 0;
+
+ // Install Protocol Instances. It will also generate a device handle for the PCI Root Bridge
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &RootBridge->Handle,
+ &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
+ NULL
+ );
+ ASSERT (RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
+ if (EFI_ERROR (Status)) {
+ PCI_TRACE ("PciRbConstructor(): ERROR: Fail to install Protocol Interfaces");
+ FreePool (RootBridge);
+ return EFI_DEVICE_ERROR;
+ }
+
+ HostBridge->RootBridge = RootBridge;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRbDestructor (
+ IN PCI_ROOT_BRIDGE_INSTANCE* RootBridge
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ RootBridge->Handle,
+ &gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
+ NULL
+ );
+
+ FreePool (RootBridge);
+
+ return Status;
+}
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.c
new file mode 100644
index 0000000000..06de6d5d9a
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.c
@@ -0,0 +1,167 @@
+/** @file
+* Initialize the XPress-RICH3 PCIe Root complex
+*
+* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "PciHostBridge.h"
+
+#include <Protocol/Cpu.h>
+
+#include "ArmPlatform.h"
+
+EFI_CPU_ARCH_PROTOCOL *mCpu;
+
+#define PCI_BRIDGE_REVISION_ID 1
+#define CLASS_CODE_REGISTER(Class, SubClass, ProgIf) ((Class << 16) | (SubClass << 8) | ProgIf)
+#define PLDA_BRIDGE_CCR CLASS_CODE_REGISTER(PCI_CLASS_BRIDGE, \
+ PCI_CLASS_BRIDGE_P2P, \
+ PCI_IF_BRIDGE_P2P)
+
+STATIC
+VOID
+SetTranslationAddressEntry (
+ IN EFI_CPU_IO2_PROTOCOL *CpuIo,
+ IN UINTN Entry,
+ IN UINT64 SourceAddress,
+ IN UINT64 TranslatedAddress,
+ IN UINT64 TranslationSize,
+ IN UINT64 TranslationParameter
+ )
+{
+ UINTN Log2Size = HighBitSet64 (TranslationSize);
+
+ // Ensure the size is a power of two. Restriction form the AXI Translation logic
+ // Othwerwise we increase the translation size
+ if (TranslationSize != (1ULL << Log2Size)) {
+ DEBUG ((EFI_D_WARN, "PCI: The size 0x%lX of the region 0x%lx has been increased to "
+ "be a power of two for the AXI translation table.\n",
+ TranslationSize, SourceAddress));
+ Log2Size++;
+ }
+
+ PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_SRC_ADDR_LOW_SIZE,
+ (UINT32)SourceAddress | ((Log2Size - 1) << 1) | 0x1);
+ PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_SRC_ADDR_HI, SourceAddress >> 32);
+
+ PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_ADDR_LOW, (UINT32)TranslatedAddress);
+ PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_ADDR_HI, TranslatedAddress >> 32);
+
+ PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_PARAM, TranslationParameter);
+}
+
+EFI_STATUS
+HWPciRbInit (
+ IN EFI_CPU_IO2_PROTOCOL *CpuIo
+ )
+{
+ UINT32 Value;
+ UINT32 Index;
+ UINTN TranslationTable;
+
+ PCI_TRACE ("VExpressPciRbInit()");
+
+ PCI_TRACE ("PCIe Setting up Address Translation");
+
+ PCIE_ROOTPORT_WRITE32 (PCIE_BAR_WIN, PCIE_BAR_WIN_SUPPORT_IO | PCIE_BAR_WIN_SUPPORT_MEM | PCIE_BAR_WIN_SUPPORT_MEM64);
+
+ // Setup the PCI Configuration Registers
+ // Offset 0a: SubClass 04 PCI-PCI Bridge
+ // Offset 0b: BaseClass 06 Bridge Device
+ // The Class Code register is a 24 bit and can be configured by setting up the PCIE_PCI_IDS
+ // Refer [1] Chapter 13
+ PCIE_ROOTPORT_WRITE32 (PCIE_PCI_IDS + PCIE_PCI_IDS_CLASSCODE_OFFSET, ((PLDA_BRIDGE_CCR << 8) | PCI_BRIDGE_REVISION_ID));
+
+ //
+ // PCIE Window 0 -> AXI4 Slave 0 Address Translations
+ //
+ TranslationTable = VEXPRESS_ATR_PCIE_WIN0;
+
+ // MSI Support
+ SetTranslationAddressEntry (CpuIo, TranslationTable, ARM_JUNO_GIV2M_MSI_BASE, ARM_JUNO_GIV2M_MSI_BASE,
+ ARM_JUNO_GIV2M_MSI_SZ, PCI_ATR_TRSLID_AXIDEVICE);
+ TranslationTable += PCI_ATR_ENTRY_SIZE;
+
+ // System Memory Support
+ SetTranslationAddressEntry (CpuIo, TranslationTable, PcdGet64 (PcdSystemMemoryBase), PcdGet64 (PcdSystemMemoryBase),
+ PcdGet64 (PcdSystemMemorySize), PCI_ATR_TRSLID_AXIMEMORY);
+ TranslationTable += PCI_ATR_ENTRY_SIZE;
+ SetTranslationAddressEntry (CpuIo, TranslationTable, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE,
+ ARM_JUNO_EXTRA_SYSTEM_MEMORY_SZ, PCI_ATR_TRSLID_AXIMEMORY);
+
+ //
+ // PCIE Window 0 -> AXI4 Slave 0 Address Translations
+ //
+ TranslationTable = VEXPRESS_ATR_AXI4_SLV1;
+
+ // PCI ECAM Support
+ SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_ECAM_BASE, PCI_ECAM_BASE, PCI_ECAM_SIZE, PCI_ATR_TRSLID_PCIE_CONF);
+ TranslationTable += PCI_ATR_ENTRY_SIZE;
+
+ // PCI IO Support
+ SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_IO_BASE, PCI_IO_BASE, PCI_IO_SIZE, PCI_ATR_TRSLID_PCIE_IO);
+ TranslationTable += PCI_ATR_ENTRY_SIZE;
+
+ // PCI MEM32 Support
+ SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM32_BASE, PCI_MEM32_BASE, PCI_MEM32_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);
+ TranslationTable += PCI_ATR_ENTRY_SIZE;
+
+ // PCI MEM64 Support
+ SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM64_BASE, PCI_MEM64_BASE, PCI_MEM64_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);
+
+ // Add credits
+ PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED, 0x00f0b818);
+ PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED + 4, 0x1);
+
+ // Allow ECRC
+ PCIE_ROOTPORT_WRITE32 (PCIE_PEX_SPC2, 0x6006);
+
+ // Reset controller
+ PCIE_CONTROL_WRITE32 (PCIE_CONTROL_RST_CTL, PCIE_CONTROL_RST_CTL_RCPHY_REL);
+
+ // Wait for reset
+ for (Index = 0; Index < 1000; Index++) {
+ gBS->Stall (1000);
+ PCIE_CONTROL_READ32 (PCIE_CONTROL_RST_STS, Value);
+ if ((Value & PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) == PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) {
+ break;
+ }
+ }
+
+ // Check for reset
+ if (!(Value & PCIE_CONTROL_RST_STS_RCPHYPLL_OUT)) {
+ DEBUG ((EFI_D_ERROR, "PCIe failed to come out of reset: %x.\n", Value));
+ return EFI_NOT_READY;
+ }
+
+ gBS->Stall (1000);
+ PCI_TRACE ("Checking link Status...");
+
+ // Wait for Link Up
+ for (Index = 0; Index < 1000; Index++) {
+ gBS->Stall (1000);
+ PCIE_ROOTPORT_READ32 (VEXPRESS_BASIC_STATUS, Value);
+ if (Value & LINK_UP) {
+ break;
+ }
+ }
+
+ // Check for link up
+ if (!(Value & LINK_UP)) {
+ DEBUG ((EFI_D_ERROR, "PCIe link not up: %x.\n", Value));
+ return EFI_NOT_READY;
+ }
+
+ PCIE_ROOTPORT_WRITE32 (PCIE_IMASK_LOCAL, PCIE_INT_MSI | PCIE_INT_INTx);
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.h b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.h
new file mode 100644
index 0000000000..a0c11a7056
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.h
@@ -0,0 +1,111 @@
+/** @file
+* Header containing the Xpress-RICH3 PCIe Root Complex specific values
+*
+* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __XPRESS_RICH3_H__
+#define __XPRESS_RICH3_H__
+
+#include <Protocol/CpuIo2.h>
+#include <Library/PcdLib.h>
+
+#define PCI_ECAM_BASE FixedPcdGet64 (PcdPciConfigurationSpaceBaseAddress)
+#define PCI_ECAM_SIZE FixedPcdGet64 (PcdPciConfigurationSpaceSize)
+#define PCI_IO_BASE FixedPcdGet64 (PcdPciIoBase)
+#define PCI_IO_SIZE FixedPcdGet64 (PcdPciIoSize)
+#define PCI_MEM32_BASE FixedPcdGet64 (PcdPciMmio32Base)
+#define PCI_MEM32_SIZE FixedPcdGet64 (PcdPciMmio32Size)
+#define PCI_MEM64_BASE FixedPcdGet64 (PcdPciMmio64Base)
+#define PCI_MEM64_SIZE FixedPcdGet64 (PcdPciMmio64Size)
+
+/*
+ * Bridge Internal Registers
+ */
+
+// PCIe Available Credit Settings
+#define PCIE_VC_CRED 0x090
+// PCIe PCI Standard Configuration Identification Settings registers
+#define PCIE_PCI_IDS 0x098
+#define PCIE_PCI_IDS_CLASSCODE_OFFSET 0x4
+// PCIe Specific 2 Capabilities Settings
+#define PCIE_PEX_SPC2 0x0d8
+// PCIe Windows Settings register
+#define PCIE_BAR_WIN 0x0FC
+// Local Processor Interrupt Mask
+#define PCIE_IMASK_LOCAL 0x180
+
+#define PCIE_BAR_WIN_SUPPORT_IO BIT0
+#define PCIE_BAR_WIN_SUPPORT_IO32 BIT1
+#define PCIE_BAR_WIN_SUPPORT_MEM BIT2
+#define PCIE_BAR_WIN_SUPPORT_MEM64 BIT3
+
+#define PCIE_INT_MSI BIT28
+#define PCIE_INT_A BIT24
+#define PCIE_INT_B BIT25
+#define PCIE_INT_C BIT26
+#define PCIE_INT_D BIT27
+#define PCIE_INT_INTx (PCIE_INT_A | PCIE_INT_B |\
+ PCIE_INT_C | PCIE_INT_D)
+
+/*
+ * PCIe Control Registers
+ */
+#define PCIE_CONTROL_RST_CTL 0x1004
+#define PCIE_CONTROL_RST_STS 0x1008
+
+/*
+ * PCI Express Address Translation registers
+ * All are offsets from PcdPcieControlBaseAddress
+ */
+#define VEXPRESS_ATR_PCIE_WIN0 0x600
+#define VEXPRESS_ATR_AXI4_SLV0 0x800
+#define VEXPRESS_ATR_AXI4_SLV1 0x820
+
+#define PCI_ATR_ENTRY_SIZE 0x20
+#define PCI_ATR_SRC_ADDR_LOW_SIZE 0
+#define PCI_ATR_SRC_ADDR_HI 0x4
+#define PCI_ATR_TRSL_ADDR_LOW 0x8
+#define PCI_ATR_TRSL_ADDR_HI 0xc
+#define PCI_ATR_TRSL_PARAM 0x10
+
+#define PCI_ATR_TRSLID_AXIDEVICE 0x420004
+#define PCI_ATR_TRSLID_AXIMEMORY 0x4e0004
+#define PCI_ATR_TRSLID_PCIE_CONF 0x000001
+#define PCI_ATR_TRSLID_PCIE_IO 0x020000
+#define PCI_ATR_TRSLID_PCIE_MEMORY 0x000000
+
+#define PCIE_CONTROL_RST_CTL_RC_REL (1 << 1)
+#define PCIE_CONTROL_RST_CTL_PHY_REL (1 << 0)
+#define PCIE_CONTROL_RST_CTL_RCPHY_REL (PCIE_CONTROL_RST_CTL_RC_REL | PCIE_CONTROL_RST_CTL_PHY_REL)
+
+#define PCIE_CONTROL_RST_STS_RC_ST (1 << 2)
+#define PCIE_CONTROL_RST_STS_PHY_ST (1 << 1)
+#define PCIE_CONTROL_RST_STS_PLL_ST (1 << 0)
+#define PCIE_CONTROL_RST_STS_RCPHYPLL_OUT (PCIE_CONTROL_RST_STS_RC_ST | PCIE_CONTROL_RST_STS_PHY_ST | PCIE_CONTROL_RST_STS_PLL_ST)
+
+#define VEXPRESS_BASIC_STATUS 0x18
+#define LINK_UP 0xff
+
+/*
+ * Initialize Versatile Express PCIe Host Bridge
+ */
+EFI_STATUS
+VExpressPciRbInit (
+ IN EFI_CPU_IO2_PROTOCOL *CpuIo
+ );
+
+// Does not support neither EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
+// nor EFI_PCI_HOST_BRIDGE_MEM64_DECODE
+#define PCI_MEMORY_ALLOCATION_ATTRIBUTES 0
+
+#endif