[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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+#/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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