mirror of https://github.com/acidanthera/audk.git
ArmPlatformPkg/ArmJunoPkg: Added PCI support
Added driver for the Juno R1 root complex. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> Reviewed-by: Ronald Cron <Ronald.Cron@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17412 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
f66eab9b9c
commit
4595449b3e
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
/** @file
|
||||
* Pci Host Bridge support for the Xpress-RICH3 PCIe Root Complex
|
||||
*
|
||||
* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "PciHostBridge.h"
|
||||
|
||||
#include <Guid/EventGroup.h>
|
||||
|
||||
/**
|
||||
* PCI Root Bridge Description
|
||||
*/
|
||||
typedef struct {
|
||||
UINT32 AcpiUid;
|
||||
UINT64 MemAllocAttributes;
|
||||
} PCI_ROOT_BRIDGE_DESC;
|
||||
|
||||
PCI_ROOT_BRIDGE_DESC PciRbDescriptions = {
|
||||
0, // AcpiUid
|
||||
PCI_MEMORY_ALLOCATION_ATTRIBUTES // MemAllocAttributes
|
||||
};
|
||||
|
||||
/**
|
||||
* Template for PCI Host Bridge Instance
|
||||
**/
|
||||
STATIC CONST PCI_HOST_BRIDGE_INSTANCE
|
||||
gPciHostBridgeInstanceTemplate = {
|
||||
PCI_HOST_BRIDGE_SIGNATURE, //Signature
|
||||
NULL, // Handle
|
||||
NULL, // ImageHandle
|
||||
NULL, // RootBridge
|
||||
TRUE, // CanRestarted
|
||||
NULL, // CpuIo
|
||||
NULL, // Metronome
|
||||
{ // ResAlloc
|
||||
PciHbRaNotifyPhase, // ResAlloc.NotifyPhase
|
||||
PciHbRaGetNextRootBridge, // ResAlloc.GetNextRootBridge
|
||||
PciHbRaGetAllocAttributes, // ResAlloc.GetAllocAttributes
|
||||
PciHbRaStartBusEnumeration, // ResAlloc.StartBusEnumeration
|
||||
PciHbRaSetBusNumbers, // ResAlloc.SetBusNumbers
|
||||
PciHbRaSubmitResources, // ResAlloc.SubmitResources
|
||||
PciHbRaGetProposedResources, // ResAlloc.GetProposedResources
|
||||
PciHbRaPreprocessController // ResAlloc.PreprocessController
|
||||
}
|
||||
};
|
||||
PCI_HOST_BRIDGE_INSTANCE* gpPciHostBridgeInstance;
|
||||
|
||||
EFI_STATUS
|
||||
HostBridgeConstructor (
|
||||
IN OUT PCI_HOST_BRIDGE_INSTANCE** Instance,
|
||||
IN EFI_HANDLE ImageHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
PCI_HOST_BRIDGE_INSTANCE* HostBridge;
|
||||
|
||||
PCI_TRACE ("HostBridgeConstructor()");
|
||||
|
||||
if (Instance == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
HostBridge = AllocateCopyPool (sizeof (PCI_HOST_BRIDGE_INSTANCE), &gPciHostBridgeInstanceTemplate);
|
||||
if (HostBridge == NULL) {
|
||||
PCI_TRACE ("HostBridgeConstructor(): FAIL to allocate resources");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
// It will also create a device handle for the PCI Host Bridge (as HostBridge->Handle == NULL)
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&HostBridge->Handle,
|
||||
&gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
PCI_TRACE ("HostBridgeConstructor(): FAIL to install resource allocator");
|
||||
FreePool (HostBridge);
|
||||
return EFI_DEVICE_ERROR;
|
||||
} else {
|
||||
PCI_TRACE ("HostBridgeConstructor(): SUCCEED to install resource allocator");
|
||||
}
|
||||
|
||||
Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)(&(HostBridge->CpuIo)));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)(&(HostBridge->Metronome)));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
HostBridge->ImageHandle = ImageHandle;
|
||||
|
||||
*Instance = HostBridge;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
HostBridgeDestructor (
|
||||
IN PCI_HOST_BRIDGE_INSTANCE* HostBridge
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
HostBridge->Handle,
|
||||
&gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (HostBridge->RootBridge) {
|
||||
PciRbDestructor (HostBridge->RootBridge);
|
||||
}
|
||||
|
||||
FreePool (HostBridge);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Entry point of this driver
|
||||
|
||||
@param ImageHandle Handle of driver image
|
||||
@param SystemTable Point to EFI_SYSTEM_TABLE
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
|
||||
@retval EFI_DEVICE_ERROR Can not install the protocol instance
|
||||
@retval EFI_SUCCESS Success to initialize the Pci host bridge.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PciHostBridgeEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
PCI_TRACE ("PciHostBridgeEntryPoint()");
|
||||
|
||||
// Creation of the PCI Host Bridge Instance
|
||||
Status = HostBridgeConstructor (&gpPciHostBridgeInstance, ImageHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
PCI_TRACE ("PciHostBridgeEntryPoint(): ERROR: Fail to construct PCI Host Bridge.");
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Creation of the PCIe Root Bridge
|
||||
Status = PciRbConstructor (gpPciHostBridgeInstance, PciRbDescriptions.AcpiUid, PciRbDescriptions.MemAllocAttributes);
|
||||
if (EFI_ERROR (Status)) {
|
||||
PCI_TRACE ("PciHostBridgeEntryPoint(): ERROR: Fail to construct PCI Root Bridge.");
|
||||
return Status;
|
||||
}
|
||||
ASSERT (gpPciHostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
|
||||
|
||||
// PCI 32bit Memory Space
|
||||
Status = gDS->AddMemorySpace (
|
||||
EfiGcdMemoryTypeMemoryMappedIo,
|
||||
PCI_MEM32_BASE,
|
||||
PCI_MEM32_SIZE,
|
||||
0
|
||||
);
|
||||
|
||||
// PCI 64bit Memory Space
|
||||
Status = gDS->AddMemorySpace (
|
||||
EfiGcdMemoryTypeMemoryMappedIo,
|
||||
PCI_MEM64_BASE,
|
||||
PCI_MEM64_SIZE,
|
||||
0
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PciHostBridgeUnload (
|
||||
IN EFI_HANDLE ImageHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
// Free Reserved memory space in GCD
|
||||
gDS->RemoveMemorySpace (PCI_MEM32_BASE, PCI_MEM32_SIZE);
|
||||
gDS->RemoveMemorySpace (PCI_MEM64_BASE, PCI_MEM64_SIZE);
|
||||
|
||||
// Free the allocated memory
|
||||
Status = HostBridgeDestructor (gpPciHostBridgeInstance);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,324 @@
|
|||
/** @file
|
||||
* Header containing the structure specific to the Xpress-RICH3 PCIe Root Complex
|
||||
*
|
||||
* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PCIHOSTBRIDGE_H
|
||||
#define __PCIHOSTBRIDGE_H
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include "XPressRich3.h"
|
||||
|
||||
#include <IndustryStandard/Pci.h>
|
||||
#include <IndustryStandard/Acpi.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/DxeServicesTableLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
|
||||
#include <Protocol/PciHostBridgeResourceAllocation.h>
|
||||
#include <Protocol/PciRootBridgeIo.h>
|
||||
#include <Protocol/PciIo.h>
|
||||
#include <Protocol/DevicePath.h>
|
||||
#include <Protocol/CpuIo2.h>
|
||||
#include <Protocol/Metronome.h>
|
||||
|
||||
#define PCI_TRACE(txt) DEBUG((EFI_D_VERBOSE, "ARM_PCI: " txt "\n"))
|
||||
|
||||
#define PCIE_ROOTPORT_WRITE32(Add, Val) { UINT32 Value = (UINT32)(Val); CpuIo->Mem.Write (CpuIo,EfiCpuIoWidthUint32,(UINT64)(PcdGet64 (PcdPcieRootPortBaseAddress)+(Add)),1,&Value); }
|
||||
#define PCIE_ROOTPORT_READ32(Add, Val) { CpuIo->Mem.Read (CpuIo,EfiCpuIoWidthUint32,(UINT64)(PcdGet64 (PcdPcieRootPortBaseAddress)+(Add)),1,&Val); }
|
||||
|
||||
#define PCIE_CONTROL_WRITE32(Add, Val) { UINT32 Value = (UINT32)(Val); CpuIo->Mem.Write (CpuIo,EfiCpuIoWidthUint32,(UINT64)(PcdGet64 (PcdPcieControlBaseAddress)+(Add)),1,&Value); }
|
||||
#define PCIE_CONTROL_READ32(Add, Val) { CpuIo->Mem.Read (CpuIo,EfiCpuIoWidthUint32,(UINT64)(PcdGet64 (PcdPcieControlBaseAddress)+(Add)),1,&Val); }
|
||||
|
||||
/**
|
||||
* PCI Root Bridge Device Path (ACPI Device Node + End Node)
|
||||
*/
|
||||
typedef struct {
|
||||
ACPI_HID_DEVICE_PATH Acpi;
|
||||
EFI_DEVICE_PATH_PROTOCOL End;
|
||||
} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
|
||||
|
||||
typedef enum {
|
||||
ResTypeIo = 0,
|
||||
ResTypeMem32,
|
||||
ResTypePMem32,
|
||||
ResTypeMem64,
|
||||
ResTypePMem64,
|
||||
ResTypeMax
|
||||
} PCI_RESOURCE_TYPE;
|
||||
|
||||
#define ACPI_SPECFLAG_PREFETCHABLE 0x06
|
||||
#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
|
||||
#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
|
||||
|
||||
typedef struct {
|
||||
UINT64 Base;
|
||||
UINT64 Length;
|
||||
UINT64 Alignment;
|
||||
} PCI_RESOURCE_ALLOC;
|
||||
|
||||
typedef struct _PCI_HOST_BRIDGE_INSTANCE PCI_HOST_BRIDGE_INSTANCE;
|
||||
|
||||
/**
|
||||
* PCI Root Bridge Instance structure
|
||||
**/
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
EFI_HANDLE Handle;
|
||||
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
|
||||
//
|
||||
// Set Type of memory allocation (could be EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
|
||||
// and EFI_PCI_HOST_BRIDGE_MEM64_DECODE).
|
||||
//
|
||||
UINT64 MemAllocAttributes;
|
||||
PCI_RESOURCE_ALLOC ResAlloc[ResTypeMax];
|
||||
UINTN BusStart;
|
||||
UINTN BusLength;
|
||||
UINT64 Supports;
|
||||
UINT64 Attributes;
|
||||
EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
|
||||
} PCI_ROOT_BRIDGE_INSTANCE;
|
||||
|
||||
/**
|
||||
* PCI Host Bridge Instance structure
|
||||
**/
|
||||
struct _PCI_HOST_BRIDGE_INSTANCE {
|
||||
UINTN Signature;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_HANDLE ImageHandle;
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
|
||||
//
|
||||
// The enumeration cannot be restarted after the process goes into the non initial
|
||||
// enumeration phase.
|
||||
//
|
||||
BOOLEAN CanRestarted;
|
||||
EFI_CPU_IO2_PROTOCOL *CpuIo;
|
||||
EFI_METRONOME_ARCH_PROTOCOL *Metronome;
|
||||
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc;
|
||||
};
|
||||
|
||||
#define PCI_HOST_BRIDGE_SIGNATURE SIGNATURE_32 ('e', 'h', 's', 't')
|
||||
#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('e', '2', 'p', 'b')
|
||||
#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) CR (a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
|
||||
#define INSTANCE_FROM_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
|
||||
|
||||
/**
|
||||
* PCI Host Bridge Resource Allocator Functions
|
||||
**/
|
||||
EFI_STATUS PciHbRaNotifyPhase (
|
||||
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||||
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
|
||||
);
|
||||
|
||||
EFI_STATUS PciHbRaGetNextRootBridge (
|
||||
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||||
IN OUT EFI_HANDLE *RootBridgeHandle
|
||||
);
|
||||
|
||||
EFI_STATUS PciHbRaGetAllocAttributes (
|
||||
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||||
IN EFI_HANDLE RootBridgeHandle,
|
||||
OUT UINT64 *Attributes
|
||||
);
|
||||
|
||||
EFI_STATUS PciHbRaStartBusEnumeration (
|
||||
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||||
IN EFI_HANDLE RootBridgeHandle,
|
||||
OUT VOID **Configuration
|
||||
);
|
||||
|
||||
EFI_STATUS PciHbRaSetBusNumbers (
|
||||
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||||
IN EFI_HANDLE RootBridgeHandle,
|
||||
IN VOID *Configuration
|
||||
);
|
||||
|
||||
EFI_STATUS PciHbRaSubmitResources (
|
||||
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||||
IN EFI_HANDLE RootBridgeHandle,
|
||||
IN VOID *Configuration
|
||||
);
|
||||
|
||||
EFI_STATUS PciHbRaGetProposedResources (
|
||||
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||||
IN EFI_HANDLE RootBridgeHandle,
|
||||
OUT VOID **Configuration
|
||||
);
|
||||
|
||||
EFI_STATUS PciHbRaPreprocessController (
|
||||
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||||
IN EFI_HANDLE RootBridgeHandle,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
|
||||
IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* PCI Root Bridge
|
||||
**/
|
||||
EFI_STATUS PciRbPollMem (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINT64 Mask,
|
||||
IN UINT64 Value,
|
||||
IN UINT64 Delay,
|
||||
OUT UINT64 *Result
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbPollIo (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINT64 Mask,
|
||||
IN UINT64 Value,
|
||||
IN UINT64 Delay,
|
||||
OUT UINT64 *Result
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbMemRead (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbMemWrite (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbIoRead (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbIoWrite (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbPciRead (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbPciWrite (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbCopyMem (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 DestAddress,
|
||||
IN UINT64 SrcAddress,
|
||||
IN UINTN Count
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbMap (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
|
||||
IN VOID *HostAddress,
|
||||
IN OUT UINTN *NumberOfBytes,
|
||||
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
|
||||
OUT VOID **Mapping
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbUnMap (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN VOID *Mapping
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbAllocateBuffer (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_ALLOCATE_TYPE Type,
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN Pages,
|
||||
IN OUT VOID **HostAddress,
|
||||
IN UINT64 Attributes
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbFreeBuffer (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN UINTN Pages,
|
||||
IN VOID *HostAddress
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbFlush (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbSetAttributes (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN UINT64 Attributes,
|
||||
IN OUT UINT64 *ResourceBase,
|
||||
IN OUT UINT64 *ResourceLength
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbGetAttributes (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
OUT UINT64 *Supports,
|
||||
OUT UINT64 *Attributes
|
||||
);
|
||||
|
||||
EFI_STATUS PciRbConfiguration (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
OUT VOID **Resources
|
||||
);
|
||||
|
||||
/**
|
||||
* PCI Root Bridge Functions
|
||||
**/
|
||||
EFI_STATUS
|
||||
PciRbConstructor (
|
||||
IN PCI_HOST_BRIDGE_INSTANCE *HostBridge,
|
||||
IN UINT32 PciAcpiUid,
|
||||
IN UINT64 MemAllocAttributes
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
PciRbDestructor (
|
||||
IN PCI_ROOT_BRIDGE_INSTANCE* RootBridge
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
HWPciRbInit (
|
||||
IN EFI_CPU_IO2_PROTOCOL *CpuIo
|
||||
);
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,745 @@
|
|||
/** @file
|
||||
* Implementation of the PCI Root Bridge Protocol for XPress-RICH3 PCIe Root Complex
|
||||
*
|
||||
* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "PciHostBridge.h"
|
||||
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/DmaLib.h>
|
||||
|
||||
#define CPUIO_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->CpuIo)
|
||||
#define METRONOME_FROM_ROOT_BRIDGE_INSTANCE(Instance) (Instance->HostBridge->Metronome)
|
||||
|
||||
/**
|
||||
* PCI Root Bridge Instance Templates
|
||||
*/
|
||||
STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH gDevicePathTemplate = {
|
||||
{
|
||||
{ ACPI_DEVICE_PATH,
|
||||
ACPI_DP,
|
||||
{ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
|
||||
(UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) }
|
||||
},
|
||||
EISA_PNP_ID (0x0A03),
|
||||
0
|
||||
},
|
||||
{
|
||||
END_DEVICE_PATH_TYPE,
|
||||
END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
||||
{ END_DEVICE_PATH_LENGTH, 0 }
|
||||
}
|
||||
};
|
||||
|
||||
STATIC CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL gIoTemplate = {
|
||||
0,
|
||||
PciRbPollMem,
|
||||
PciRbPollIo,
|
||||
{
|
||||
PciRbMemRead,
|
||||
PciRbMemWrite
|
||||
},
|
||||
{
|
||||
PciRbIoRead,
|
||||
PciRbIoWrite
|
||||
},
|
||||
{
|
||||
PciRbPciRead,
|
||||
PciRbPciWrite
|
||||
},
|
||||
PciRbCopyMem,
|
||||
PciRbMap,
|
||||
PciRbUnMap,
|
||||
PciRbAllocateBuffer,
|
||||
PciRbFreeBuffer,
|
||||
PciRbFlush,
|
||||
PciRbGetAttributes,
|
||||
PciRbSetAttributes,
|
||||
PciRbConfiguration,
|
||||
0
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[ResTypeMax+1];
|
||||
EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;
|
||||
} RESOURCE_CONFIGURATION;
|
||||
|
||||
|
||||
RESOURCE_CONFIGURATION Configuration = {
|
||||
{{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_IO , 0, 0, 0, 0, 0, 0, 0},
|
||||
{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 32, 0, 0, 0, 0},
|
||||
{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 32, 0, 0, 0, 0},
|
||||
{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 64, 0, 0, 0, 0},
|
||||
{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 64, 0, 0, 0, 0},
|
||||
{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_BUS, 0, 0, 0, 0, 255, 0, 255}},
|
||||
{ACPI_END_TAG_DESCRIPTOR, 0}
|
||||
};
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
PciRbPollMem (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINT64 Mask,
|
||||
IN UINT64 Value,
|
||||
IN UINT64 Delay,
|
||||
OUT UINT64 *Result
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 NumberOfTicks;
|
||||
UINT32 Remainder;
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||||
EFI_METRONOME_ARCH_PROTOCOL *Metronome;
|
||||
|
||||
PCI_TRACE ("PciRbPollMem()");
|
||||
|
||||
RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
|
||||
Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
|
||||
|
||||
if (Result == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Width > EfiPciWidthUint64) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// No matter what, always do a single poll.
|
||||
Status = This->Mem.Read (This, Width, Address, 1, Result);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
if ((*Result & Mask) == Value) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (Delay == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);
|
||||
if (Remainder != 0) {
|
||||
NumberOfTicks += 1;
|
||||
}
|
||||
NumberOfTicks += 1;
|
||||
|
||||
while (NumberOfTicks) {
|
||||
Metronome->WaitForTick (Metronome, 1);
|
||||
|
||||
Status = This->Mem.Read (This, Width, Address, 1, Result);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((*Result & Mask) == Value) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
NumberOfTicks -= 1;
|
||||
}
|
||||
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbPollIo (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINT64 Mask,
|
||||
IN UINT64 Value,
|
||||
IN UINT64 Delay,
|
||||
OUT UINT64 *Result
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 NumberOfTicks;
|
||||
UINT32 Remainder;
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||||
EFI_METRONOME_ARCH_PROTOCOL *Metronome;
|
||||
|
||||
PCI_TRACE ("PciRbPollIo()");
|
||||
|
||||
RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
|
||||
Metronome = METRONOME_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
|
||||
|
||||
if (Result == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Width > EfiPciWidthUint64) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// No matter what, always do a single poll.
|
||||
Status = This->Io.Read (This, Width, Address, 1, Result);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
if ((*Result & Mask) == Value) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (Delay == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) Metronome->TickPeriod, &Remainder);
|
||||
if (Remainder != 0) {
|
||||
NumberOfTicks += 1;
|
||||
}
|
||||
NumberOfTicks += 1;
|
||||
|
||||
while (NumberOfTicks) {
|
||||
Metronome->WaitForTick (Metronome, 1);
|
||||
|
||||
Status = This->Io.Read (This, Width, Address, 1, Result);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((*Result & Mask) == Value) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
NumberOfTicks -= 1;
|
||||
}
|
||||
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbMemRead (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||||
EFI_CPU_IO2_PROTOCOL *CpuIo;
|
||||
|
||||
PCI_TRACE ("PciRbMemRead()");
|
||||
|
||||
RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
|
||||
CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
|
||||
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Width >= EfiPciWidthMaximum) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&
|
||||
((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbMemWrite (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||||
EFI_CPU_IO2_PROTOCOL *CpuIo;
|
||||
|
||||
PCI_TRACE ("PciRbMemWrite()");
|
||||
|
||||
RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
|
||||
CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
|
||||
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Width >= EfiPciWidthMaximum) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (((Address < PCI_MEM32_BASE) || (Address > (PCI_MEM32_BASE + PCI_MEM32_SIZE))) &&
|
||||
((Address < PCI_MEM64_BASE) || (Address > (PCI_MEM64_BASE + PCI_MEM64_SIZE)))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbIoRead (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
PCI_TRACE ("PciRbIoRead()");
|
||||
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Width >= EfiPciWidthMaximum) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// IO currently unsupported
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbIoWrite (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
PCI_TRACE ("PciRbIoWrite()");
|
||||
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Width >= EfiPciWidthMaximum) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// IO currently unsupported
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbPciRead (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 EfiAddress,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
UINT32 Offset;
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||||
EFI_CPU_IO2_PROTOCOL *CpuIo;
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
|
||||
UINT64 Address;
|
||||
|
||||
EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
|
||||
RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
|
||||
CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
|
||||
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Width >= EfiPciWidthMaximum) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (EfiPciAddress->ExtendedRegister) {
|
||||
Offset = EfiPciAddress->ExtendedRegister;
|
||||
} else {
|
||||
Offset = EfiPciAddress->Register;
|
||||
}
|
||||
|
||||
// The UEFI PCI enumerator scans for devices at all possible addresses,
|
||||
// and ignores some PCI rules - this results in some hardware being
|
||||
// detected multiple times. We work around this by faking absent
|
||||
// devices
|
||||
if ((EfiPciAddress->Bus == 0) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {
|
||||
*((UINT32 *)Buffer) = 0xffffffff;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
if ((EfiPciAddress->Bus == 1) && ((EfiPciAddress->Device != 0) || (EfiPciAddress->Function != 0))) {
|
||||
*((UINT32 *)Buffer) = 0xffffffff;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// Work around incorrect class ID in the root bridge
|
||||
if ((EfiPciAddress->Bus == 0) && (EfiPciAddress->Device == 0) && (EfiPciAddress->Function == 0) && (Offset == 8)) {
|
||||
*((UINT32 *)Buffer) = 0x06040001;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |
|
||||
(EfiPciAddress->Device << 15) |
|
||||
(EfiPciAddress->Function << 12) | Offset);
|
||||
|
||||
if ((Address < PCI_ECAM_BASE) || (Address > PCI_ECAM_BASE + PCI_ECAM_SIZE)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return CpuIo->Mem.Read (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbPciWrite (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 EfiAddress,
|
||||
IN UINTN Count,
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
UINT32 Offset;
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||||
EFI_CPU_IO2_PROTOCOL *CpuIo;
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *EfiPciAddress;
|
||||
UINT64 Address;
|
||||
|
||||
EfiPciAddress = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&EfiAddress;
|
||||
RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
|
||||
CpuIo = CPUIO_FROM_ROOT_BRIDGE_INSTANCE (RootBridgeInstance);
|
||||
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Width >= EfiPciWidthMaximum) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (EfiPciAddress->ExtendedRegister)
|
||||
Offset = EfiPciAddress->ExtendedRegister;
|
||||
else
|
||||
Offset = EfiPciAddress->Register;
|
||||
|
||||
Address = PCI_ECAM_BASE + ((EfiPciAddress->Bus << 20) |
|
||||
(EfiPciAddress->Device << 15) |
|
||||
(EfiPciAddress->Function << 12) | Offset);
|
||||
|
||||
if (Address < PCI_ECAM_BASE || Address > PCI_ECAM_BASE + PCI_ECAM_SIZE) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return CpuIo->Mem.Write (CpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH)Width, Address, Count, Buffer);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbCopyMem (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 DestAddress,
|
||||
IN UINT64 SrcAddress,
|
||||
IN UINTN Count
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN Direction;
|
||||
UINTN Stride;
|
||||
UINTN Index;
|
||||
UINT64 Result;
|
||||
|
||||
PCI_TRACE ("PciRbCopyMem()");
|
||||
|
||||
if (Width > EfiPciWidthUint64) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (DestAddress == SrcAddress) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Stride = (UINTN)(1 << Width);
|
||||
|
||||
Direction = TRUE;
|
||||
if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
|
||||
Direction = FALSE;
|
||||
SrcAddress = SrcAddress + (Count-1) * Stride;
|
||||
DestAddress = DestAddress + (Count-1) * Stride;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
Status = PciRbMemRead (
|
||||
This,
|
||||
Width,
|
||||
SrcAddress,
|
||||
1,
|
||||
&Result
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
Status = PciRbMemWrite (
|
||||
This,
|
||||
Width,
|
||||
DestAddress,
|
||||
1,
|
||||
&Result
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
if (Direction) {
|
||||
SrcAddress += Stride;
|
||||
DestAddress += Stride;
|
||||
} else {
|
||||
SrcAddress -= Stride;
|
||||
DestAddress -= Stride;
|
||||
}
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbMap (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
|
||||
IN VOID *HostAddress,
|
||||
IN OUT UINTN *NumberOfBytes,
|
||||
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
|
||||
OUT VOID **Mapping
|
||||
)
|
||||
{
|
||||
DMA_MAP_OPERATION DmaOperation;
|
||||
|
||||
PCI_TRACE ("PciRbMap()");
|
||||
|
||||
if (Operation == EfiPciOperationBusMasterRead) {
|
||||
DmaOperation = MapOperationBusMasterRead;
|
||||
} else if (Operation == EfiPciOperationBusMasterWrite) {
|
||||
DmaOperation = MapOperationBusMasterWrite;
|
||||
} else if (Operation == EfiPciOperationBusMasterCommonBuffer) {
|
||||
DmaOperation = MapOperationBusMasterCommonBuffer;
|
||||
} else {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbUnMap (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN VOID *Mapping
|
||||
)
|
||||
{
|
||||
PCI_TRACE ("PciRbUnMap()");
|
||||
return DmaUnmap (Mapping);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbAllocateBuffer (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN EFI_ALLOCATE_TYPE Type,
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN Pages,
|
||||
IN OUT VOID **HostAddress,
|
||||
IN UINT64 Attributes
|
||||
)
|
||||
{
|
||||
PCI_TRACE ("PciRbAllocateBuffer()");
|
||||
|
||||
if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbFreeBuffer (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN UINTN Pages,
|
||||
IN VOID *HostAddress
|
||||
)
|
||||
{
|
||||
PCI_TRACE ("PciRbFreeBuffer()");
|
||||
return DmaFreeBuffer (Pages, HostAddress);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbFlush (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
PCI_TRACE ("PciRbFlush()");
|
||||
|
||||
//TODO: Not supported yet
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbSetAttributes (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
IN UINT64 Attributes,
|
||||
IN OUT UINT64 *ResourceBase,
|
||||
IN OUT UINT64 *ResourceLength
|
||||
)
|
||||
{
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||||
|
||||
PCI_TRACE ("PciRbSetAttributes()");
|
||||
|
||||
RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
|
||||
|
||||
if (Attributes) {
|
||||
if ((Attributes & (~(RootBridgeInstance->Supports))) != 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Cannot allowed to change attributes
|
||||
if (Attributes & ~RootBridgeInstance->Attributes) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbGetAttributes (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
OUT UINT64 *Supported,
|
||||
OUT UINT64 *Attributes
|
||||
)
|
||||
{
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||||
|
||||
PCI_TRACE ("PciRbGetAttributes()");
|
||||
|
||||
RootBridgeInstance = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
|
||||
|
||||
if (Attributes == NULL && Supported == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Set the return value for Supported and Attributes
|
||||
if (Supported) {
|
||||
*Supported = RootBridgeInstance->Supports;
|
||||
}
|
||||
|
||||
if (Attributes) {
|
||||
*Attributes = RootBridgeInstance->Attributes;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbConfiguration (
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
|
||||
OUT VOID **Resources
|
||||
)
|
||||
{
|
||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
|
||||
UINTN Index;
|
||||
|
||||
PCI_TRACE ("PciRbConfiguration()");
|
||||
|
||||
RootBridge = INSTANCE_FROM_ROOT_BRIDGE_IO_THIS (This);
|
||||
|
||||
for (Index = 0; Index < ResTypeMax; Index++) {
|
||||
//if (ResAlloc[Index].Length != 0) => Resource allocated
|
||||
if (RootBridge->ResAlloc[Index].Length != 0) {
|
||||
Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->ResAlloc[Index].Base;
|
||||
Configuration.SpaceDesp[Index].AddrRangeMax = RootBridge->ResAlloc[Index].Base + RootBridge->ResAlloc[Index].Length - 1;
|
||||
Configuration.SpaceDesp[Index].AddrLen = RootBridge->ResAlloc[Index].Length;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up Configuration for the bus
|
||||
Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->BusStart;
|
||||
Configuration.SpaceDesp[Index].AddrLen = RootBridge->BusLength;
|
||||
|
||||
*Resources = &Configuration;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbConstructor (
|
||||
IN PCI_HOST_BRIDGE_INSTANCE *HostBridge,
|
||||
IN UINT32 PciAcpiUid,
|
||||
IN UINT64 MemAllocAttributes
|
||||
)
|
||||
{
|
||||
PCI_ROOT_BRIDGE_INSTANCE* RootBridge;
|
||||
EFI_STATUS Status;
|
||||
|
||||
PCI_TRACE ("PciRbConstructor()");
|
||||
|
||||
// Allocate Memory for the Instance from a Template
|
||||
RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));
|
||||
if (RootBridge == NULL) {
|
||||
PCI_TRACE ("PciRbConstructor(): ERROR: Out of Resources");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
|
||||
CopyMem (&(RootBridge->DevicePath), &gDevicePathTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH));
|
||||
CopyMem (&(RootBridge->Io), &gIoTemplate, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL));
|
||||
|
||||
// Set Parent Handle
|
||||
RootBridge->Io.ParentHandle = HostBridge->Handle;
|
||||
|
||||
// Attach the Root Bridge to the PCI Host Bridge Instance
|
||||
RootBridge->HostBridge = HostBridge;
|
||||
|
||||
// Set Device Path for this Root Bridge
|
||||
RootBridge->DevicePath.Acpi.UID = PciAcpiUid;
|
||||
|
||||
RootBridge->BusStart = FixedPcdGet32 (PcdPciBusMin);
|
||||
RootBridge->BusLength = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
|
||||
|
||||
// PCI Attributes
|
||||
RootBridge->Supports = 0;
|
||||
RootBridge->Attributes = 0;
|
||||
|
||||
// Install Protocol Instances. It will also generate a device handle for the PCI Root Bridge
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&RootBridge->Handle,
|
||||
&gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
|
||||
&gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
|
||||
NULL
|
||||
);
|
||||
ASSERT (RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
PCI_TRACE ("PciRbConstructor(): ERROR: Fail to install Protocol Interfaces");
|
||||
FreePool (RootBridge);
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
HostBridge->RootBridge = RootBridge;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PciRbDestructor (
|
||||
IN PCI_ROOT_BRIDGE_INSTANCE* RootBridge
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
RootBridge->Handle,
|
||||
&gEfiDevicePathProtocolGuid, &RootBridge->DevicePath,
|
||||
&gEfiPciRootBridgeIoProtocolGuid, &RootBridge->Io,
|
||||
NULL
|
||||
);
|
||||
|
||||
FreePool (RootBridge);
|
||||
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/** @file
|
||||
* Initialize the XPress-RICH3 PCIe Root complex
|
||||
*
|
||||
* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "PciHostBridge.h"
|
||||
|
||||
#include <Protocol/Cpu.h>
|
||||
|
||||
#include "ArmPlatform.h"
|
||||
|
||||
EFI_CPU_ARCH_PROTOCOL *mCpu;
|
||||
|
||||
#define PCI_BRIDGE_REVISION_ID 1
|
||||
#define CLASS_CODE_REGISTER(Class, SubClass, ProgIf) ((Class << 16) | (SubClass << 8) | ProgIf)
|
||||
#define PLDA_BRIDGE_CCR CLASS_CODE_REGISTER(PCI_CLASS_BRIDGE, \
|
||||
PCI_CLASS_BRIDGE_P2P, \
|
||||
PCI_IF_BRIDGE_P2P)
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
SetTranslationAddressEntry (
|
||||
IN EFI_CPU_IO2_PROTOCOL *CpuIo,
|
||||
IN UINTN Entry,
|
||||
IN UINT64 SourceAddress,
|
||||
IN UINT64 TranslatedAddress,
|
||||
IN UINT64 TranslationSize,
|
||||
IN UINT64 TranslationParameter
|
||||
)
|
||||
{
|
||||
UINTN Log2Size = HighBitSet64 (TranslationSize);
|
||||
|
||||
// Ensure the size is a power of two. Restriction form the AXI Translation logic
|
||||
// Othwerwise we increase the translation size
|
||||
if (TranslationSize != (1ULL << Log2Size)) {
|
||||
DEBUG ((EFI_D_WARN, "PCI: The size 0x%lX of the region 0x%lx has been increased to "
|
||||
"be a power of two for the AXI translation table.\n",
|
||||
TranslationSize, SourceAddress));
|
||||
Log2Size++;
|
||||
}
|
||||
|
||||
PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_SRC_ADDR_LOW_SIZE,
|
||||
(UINT32)SourceAddress | ((Log2Size - 1) << 1) | 0x1);
|
||||
PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_SRC_ADDR_HI, SourceAddress >> 32);
|
||||
|
||||
PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_ADDR_LOW, (UINT32)TranslatedAddress);
|
||||
PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_ADDR_HI, TranslatedAddress >> 32);
|
||||
|
||||
PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_PARAM, TranslationParameter);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
HWPciRbInit (
|
||||
IN EFI_CPU_IO2_PROTOCOL *CpuIo
|
||||
)
|
||||
{
|
||||
UINT32 Value;
|
||||
UINT32 Index;
|
||||
UINTN TranslationTable;
|
||||
|
||||
PCI_TRACE ("VExpressPciRbInit()");
|
||||
|
||||
PCI_TRACE ("PCIe Setting up Address Translation");
|
||||
|
||||
PCIE_ROOTPORT_WRITE32 (PCIE_BAR_WIN, PCIE_BAR_WIN_SUPPORT_IO | PCIE_BAR_WIN_SUPPORT_MEM | PCIE_BAR_WIN_SUPPORT_MEM64);
|
||||
|
||||
// Setup the PCI Configuration Registers
|
||||
// Offset 0a: SubClass 04 PCI-PCI Bridge
|
||||
// Offset 0b: BaseClass 06 Bridge Device
|
||||
// The Class Code register is a 24 bit and can be configured by setting up the PCIE_PCI_IDS
|
||||
// Refer [1] Chapter 13
|
||||
PCIE_ROOTPORT_WRITE32 (PCIE_PCI_IDS + PCIE_PCI_IDS_CLASSCODE_OFFSET, ((PLDA_BRIDGE_CCR << 8) | PCI_BRIDGE_REVISION_ID));
|
||||
|
||||
//
|
||||
// PCIE Window 0 -> AXI4 Slave 0 Address Translations
|
||||
//
|
||||
TranslationTable = VEXPRESS_ATR_PCIE_WIN0;
|
||||
|
||||
// MSI Support
|
||||
SetTranslationAddressEntry (CpuIo, TranslationTable, ARM_JUNO_GIV2M_MSI_BASE, ARM_JUNO_GIV2M_MSI_BASE,
|
||||
ARM_JUNO_GIV2M_MSI_SZ, PCI_ATR_TRSLID_AXIDEVICE);
|
||||
TranslationTable += PCI_ATR_ENTRY_SIZE;
|
||||
|
||||
// System Memory Support
|
||||
SetTranslationAddressEntry (CpuIo, TranslationTable, PcdGet64 (PcdSystemMemoryBase), PcdGet64 (PcdSystemMemoryBase),
|
||||
PcdGet64 (PcdSystemMemorySize), PCI_ATR_TRSLID_AXIMEMORY);
|
||||
TranslationTable += PCI_ATR_ENTRY_SIZE;
|
||||
SetTranslationAddressEntry (CpuIo, TranslationTable, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE,
|
||||
ARM_JUNO_EXTRA_SYSTEM_MEMORY_SZ, PCI_ATR_TRSLID_AXIMEMORY);
|
||||
|
||||
//
|
||||
// PCIE Window 0 -> AXI4 Slave 0 Address Translations
|
||||
//
|
||||
TranslationTable = VEXPRESS_ATR_AXI4_SLV1;
|
||||
|
||||
// PCI ECAM Support
|
||||
SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_ECAM_BASE, PCI_ECAM_BASE, PCI_ECAM_SIZE, PCI_ATR_TRSLID_PCIE_CONF);
|
||||
TranslationTable += PCI_ATR_ENTRY_SIZE;
|
||||
|
||||
// PCI IO Support
|
||||
SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_IO_BASE, PCI_IO_BASE, PCI_IO_SIZE, PCI_ATR_TRSLID_PCIE_IO);
|
||||
TranslationTable += PCI_ATR_ENTRY_SIZE;
|
||||
|
||||
// PCI MEM32 Support
|
||||
SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM32_BASE, PCI_MEM32_BASE, PCI_MEM32_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);
|
||||
TranslationTable += PCI_ATR_ENTRY_SIZE;
|
||||
|
||||
// PCI MEM64 Support
|
||||
SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM64_BASE, PCI_MEM64_BASE, PCI_MEM64_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);
|
||||
|
||||
// Add credits
|
||||
PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED, 0x00f0b818);
|
||||
PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED + 4, 0x1);
|
||||
|
||||
// Allow ECRC
|
||||
PCIE_ROOTPORT_WRITE32 (PCIE_PEX_SPC2, 0x6006);
|
||||
|
||||
// Reset controller
|
||||
PCIE_CONTROL_WRITE32 (PCIE_CONTROL_RST_CTL, PCIE_CONTROL_RST_CTL_RCPHY_REL);
|
||||
|
||||
// Wait for reset
|
||||
for (Index = 0; Index < 1000; Index++) {
|
||||
gBS->Stall (1000);
|
||||
PCIE_CONTROL_READ32 (PCIE_CONTROL_RST_STS, Value);
|
||||
if ((Value & PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) == PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for reset
|
||||
if (!(Value & PCIE_CONTROL_RST_STS_RCPHYPLL_OUT)) {
|
||||
DEBUG ((EFI_D_ERROR, "PCIe failed to come out of reset: %x.\n", Value));
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
|
||||
gBS->Stall (1000);
|
||||
PCI_TRACE ("Checking link Status...");
|
||||
|
||||
// Wait for Link Up
|
||||
for (Index = 0; Index < 1000; Index++) {
|
||||
gBS->Stall (1000);
|
||||
PCIE_ROOTPORT_READ32 (VEXPRESS_BASIC_STATUS, Value);
|
||||
if (Value & LINK_UP) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for link up
|
||||
if (!(Value & LINK_UP)) {
|
||||
DEBUG ((EFI_D_ERROR, "PCIe link not up: %x.\n", Value));
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
|
||||
PCIE_ROOTPORT_WRITE32 (PCIE_IMASK_LOCAL, PCIE_INT_MSI | PCIE_INT_INTx);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/** @file
|
||||
* Header containing the Xpress-RICH3 PCIe Root Complex specific values
|
||||
*
|
||||
* Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __XPRESS_RICH3_H__
|
||||
#define __XPRESS_RICH3_H__
|
||||
|
||||
#include <Protocol/CpuIo2.h>
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
#define PCI_ECAM_BASE FixedPcdGet64 (PcdPciConfigurationSpaceBaseAddress)
|
||||
#define PCI_ECAM_SIZE FixedPcdGet64 (PcdPciConfigurationSpaceSize)
|
||||
#define PCI_IO_BASE FixedPcdGet64 (PcdPciIoBase)
|
||||
#define PCI_IO_SIZE FixedPcdGet64 (PcdPciIoSize)
|
||||
#define PCI_MEM32_BASE FixedPcdGet64 (PcdPciMmio32Base)
|
||||
#define PCI_MEM32_SIZE FixedPcdGet64 (PcdPciMmio32Size)
|
||||
#define PCI_MEM64_BASE FixedPcdGet64 (PcdPciMmio64Base)
|
||||
#define PCI_MEM64_SIZE FixedPcdGet64 (PcdPciMmio64Size)
|
||||
|
||||
/*
|
||||
* Bridge Internal Registers
|
||||
*/
|
||||
|
||||
// PCIe Available Credit Settings
|
||||
#define PCIE_VC_CRED 0x090
|
||||
// PCIe PCI Standard Configuration Identification Settings registers
|
||||
#define PCIE_PCI_IDS 0x098
|
||||
#define PCIE_PCI_IDS_CLASSCODE_OFFSET 0x4
|
||||
// PCIe Specific 2 Capabilities Settings
|
||||
#define PCIE_PEX_SPC2 0x0d8
|
||||
// PCIe Windows Settings register
|
||||
#define PCIE_BAR_WIN 0x0FC
|
||||
// Local Processor Interrupt Mask
|
||||
#define PCIE_IMASK_LOCAL 0x180
|
||||
|
||||
#define PCIE_BAR_WIN_SUPPORT_IO BIT0
|
||||
#define PCIE_BAR_WIN_SUPPORT_IO32 BIT1
|
||||
#define PCIE_BAR_WIN_SUPPORT_MEM BIT2
|
||||
#define PCIE_BAR_WIN_SUPPORT_MEM64 BIT3
|
||||
|
||||
#define PCIE_INT_MSI BIT28
|
||||
#define PCIE_INT_A BIT24
|
||||
#define PCIE_INT_B BIT25
|
||||
#define PCIE_INT_C BIT26
|
||||
#define PCIE_INT_D BIT27
|
||||
#define PCIE_INT_INTx (PCIE_INT_A | PCIE_INT_B |\
|
||||
PCIE_INT_C | PCIE_INT_D)
|
||||
|
||||
/*
|
||||
* PCIe Control Registers
|
||||
*/
|
||||
#define PCIE_CONTROL_RST_CTL 0x1004
|
||||
#define PCIE_CONTROL_RST_STS 0x1008
|
||||
|
||||
/*
|
||||
* PCI Express Address Translation registers
|
||||
* All are offsets from PcdPcieControlBaseAddress
|
||||
*/
|
||||
#define VEXPRESS_ATR_PCIE_WIN0 0x600
|
||||
#define VEXPRESS_ATR_AXI4_SLV0 0x800
|
||||
#define VEXPRESS_ATR_AXI4_SLV1 0x820
|
||||
|
||||
#define PCI_ATR_ENTRY_SIZE 0x20
|
||||
#define PCI_ATR_SRC_ADDR_LOW_SIZE 0
|
||||
#define PCI_ATR_SRC_ADDR_HI 0x4
|
||||
#define PCI_ATR_TRSL_ADDR_LOW 0x8
|
||||
#define PCI_ATR_TRSL_ADDR_HI 0xc
|
||||
#define PCI_ATR_TRSL_PARAM 0x10
|
||||
|
||||
#define PCI_ATR_TRSLID_AXIDEVICE 0x420004
|
||||
#define PCI_ATR_TRSLID_AXIMEMORY 0x4e0004
|
||||
#define PCI_ATR_TRSLID_PCIE_CONF 0x000001
|
||||
#define PCI_ATR_TRSLID_PCIE_IO 0x020000
|
||||
#define PCI_ATR_TRSLID_PCIE_MEMORY 0x000000
|
||||
|
||||
#define PCIE_CONTROL_RST_CTL_RC_REL (1 << 1)
|
||||
#define PCIE_CONTROL_RST_CTL_PHY_REL (1 << 0)
|
||||
#define PCIE_CONTROL_RST_CTL_RCPHY_REL (PCIE_CONTROL_RST_CTL_RC_REL | PCIE_CONTROL_RST_CTL_PHY_REL)
|
||||
|
||||
#define PCIE_CONTROL_RST_STS_RC_ST (1 << 2)
|
||||
#define PCIE_CONTROL_RST_STS_PHY_ST (1 << 1)
|
||||
#define PCIE_CONTROL_RST_STS_PLL_ST (1 << 0)
|
||||
#define PCIE_CONTROL_RST_STS_RCPHYPLL_OUT (PCIE_CONTROL_RST_STS_RC_ST | PCIE_CONTROL_RST_STS_PHY_ST | PCIE_CONTROL_RST_STS_PLL_ST)
|
||||
|
||||
#define VEXPRESS_BASIC_STATUS 0x18
|
||||
#define LINK_UP 0xff
|
||||
|
||||
/*
|
||||
* Initialize Versatile Express PCIe Host Bridge
|
||||
*/
|
||||
EFI_STATUS
|
||||
VExpressPciRbInit (
|
||||
IN EFI_CPU_IO2_PROTOCOL *CpuIo
|
||||
);
|
||||
|
||||
// Does not support neither EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
|
||||
// nor EFI_PCI_HOST_BRIDGE_MEM64_DECODE
|
||||
#define PCI_MEMORY_ALLOCATION_ATTRIBUTES 0
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue