]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPlatformPkg/ArmJunoPkg: Added PCI support
authorOlivier Martin <olivier.martin@arm.com>
Mon, 11 May 2015 17:48:39 +0000 (17:48 +0000)
committeroliviermartin <oliviermartin@Edk2>
Mon, 11 May 2015 17:48:39 +0000 (17:48 +0000)
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

ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec
ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.c [new file with mode: 0644]
ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridge.h [new file with mode: 0644]
ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf [new file with mode: 0644]
ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c [new file with mode: 0644]
ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciRootBridge.c [new file with mode: 0644]
ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.c [new file with mode: 0644]
ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.h [new file with mode: 0644]

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