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