Browse Source

Silicon/ARM/N1SoC: Implement the PciHostBridgeLib library

Neoverse N1 SoC includes a PCIe root complex to which a AHCI, GbE and
USB controllers are attached as an endpoint. So implement the
PciHostBridgeLib glue layer and enable support for PCIe controller and
all the devices connected over the PCIe bus.

Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Signed-off-by: Pranav Madhu <pranav.madhu@arm.com>
Reviewed-by: Thomas Abraham <thomas.abraham@arm.com>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
Deepak Pandey 3 years ago
parent
commit
a7d24fe3b9

+ 184 - 0
Silicon/ARM/NeoverseN1Soc/Library/PciHostBridgeLib/PciHostBridgeLib.c

@@ -0,0 +1,184 @@
+/** @file
+*  PCI Host Bridge Library instance for ARM Neoverse N1 platform
+*
+*  Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
+*
+*  SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+STATIC CHAR16 CONST * CONST mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
+  L"Mem", L"I/O", L"Bus"
+};
+
+#pragma pack (1)
+typedef struct {
+  ACPI_HID_DEVICE_PATH     AcpiDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+#pragma pack ()
+
+STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[] = {
+  // PCIe
+  {
+    {
+      {
+        ACPI_DEVICE_PATH,
+        ACPI_DP,
+        {
+          (UINT8)sizeof (ACPI_HID_DEVICE_PATH),
+          (UINT8)(sizeof (ACPI_HID_DEVICE_PATH) >> 8)
+        }
+      },
+      EISA_PNP_ID (0x0A08), // PCIe
+      0
+    },
+    {
+      END_DEVICE_PATH_TYPE,
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,
+      {
+        END_DEVICE_PATH_LENGTH,
+        0
+      }
+    }
+  }
+};
+
+STATIC PCI_ROOT_BRIDGE mPciRootBridge[] = {
+  {
+    0,                                              // Segment
+    0,                                              // Supports
+    0,                                              // Attributes
+    TRUE,                                           // DmaAbove4G
+    FALSE,                                          // NoExtendedConfigSpace
+    FALSE,                                          // ResourceAssigned
+    EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |          // AllocationAttributes
+    EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+    {
+      // Bus
+      FixedPcdGet32 (PcdPcieBusMin),
+      FixedPcdGet32 (PcdPcieBusMax)
+    }, {
+      // Io
+      FixedPcdGet64 (PcdPcieIoBase),
+      FixedPcdGet64 (PcdPcieIoBase) + FixedPcdGet64 (PcdPcieIoSize) - 1
+    }, {
+      // Mem
+      FixedPcdGet32 (PcdPcieMmio32Base),
+      FixedPcdGet32 (PcdPcieMmio32Base) + FixedPcdGet32 (PcdPcieMmio32Size) - 1
+    }, {
+      // MemAbove4G
+      FixedPcdGet64 (PcdPcieMmio64Base),
+      FixedPcdGet64 (PcdPcieMmio64Base) + FixedPcdGet64 (PcdPcieMmio64Size) - 1
+    }, {
+      // PMem
+      MAX_UINT64,
+      0
+    }, {
+      // PMemAbove4G
+      MAX_UINT64,
+      0
+    },
+    (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[0]
+  }
+};
+
+/**
+  Return all the root bridge instances in an array.
+
+  @param Count  Return the count of root bridge instances.
+
+  @return All the root bridge instances in an array.
+          The array should be passed into PciHostBridgeFreeRootBridges()
+          when it's not used.
+**/
+PCI_ROOT_BRIDGE *
+EFIAPI
+PciHostBridgeGetRootBridges (
+  UINTN                             *Count
+  )
+{
+  *Count = ARRAY_SIZE (mPciRootBridge);
+  return mPciRootBridge;
+}
+
+/**
+  Free the root bridge instances array returned from PciHostBridgeGetRootBridges().
+
+  @param Bridges The root bridge instances array.
+  @param Count   The count of the array.
+**/
+VOID
+EFIAPI
+PciHostBridgeFreeRootBridges (
+  PCI_ROOT_BRIDGE                   *Bridges,
+  UINTN                             Count
+  )
+{
+}
+
+/**
+  Inform the platform that the resource conflict happens.
+
+  @param HostBridgeHandle Handle of the Host Bridge.
+  @param Configuration    Pointer to PCI I/O and PCI memory resource
+                          descriptors. The Configuration contains the resources
+                          for all the root bridges. The resource for each root
+                          bridge is terminated with END descriptor and an
+                          additional END is appended indicating the end of the
+                          entire resources. The resource descriptor field
+                          values follow the description in
+                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\
+                          SubmitResources().
+**/
+VOID
+EFIAPI
+PciHostBridgeResourceConflict (
+  EFI_HANDLE                        HostBridgeHandle,
+  VOID                              *Configuration
+  )
+{
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
+
+  DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happened!\n"));
+  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
+      ASSERT (Descriptor->ResType <
+              (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /
+               sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])
+               )
+              );
+      DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
+              mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
+              Descriptor->AddrLen, Descriptor->AddrRangeMax
+              ));
+      if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+        DEBUG ((DEBUG_ERROR, "     Granularity/SpecificFlag = %ld / %02x%s\n",
+                Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
+                ((Descriptor->SpecificFlag &
+                  EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
+                  ) != 0) ? L" (Prefetchable)" : L""
+                ));
+      }
+    }
+    //
+    // Skip the END descriptor for root bridge
+    //
+    ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
+    Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
+                   (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
+                   );
+  }
+}

+ 49 - 0
Silicon/ARM/NeoverseN1Soc/Library/PciHostBridgeLib/PciHostBridgeLib.inf

@@ -0,0 +1,49 @@
+## @file
+#  PCI Host Bridge Library instance for ARM Neoverse N1 platform.
+#
+#  Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = PciHostBridgeLib
+  FILE_GUID                      = daa340e1-89dd-4bd2-b645-ebe75e541f8b
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciHostBridgeLib|DXE_DRIVER
+
+[Sources]
+  PciHostBridgeLib.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  DevicePathLib
+  IoLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+
+[FixedPcd]
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieBusMin
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieBusMax
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieIoBase
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieIoSize
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio32Base
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio32Size
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio64Base
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio64Size
+
+[Protocols]
+  gEfiCpuIo2ProtocolGuid
+
+[Depex]
+  gEfiCpuIo2ProtocolGuid

+ 11 - 0
Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLib.inf

@@ -29,11 +29,22 @@
   AArch64/Helper.S | GCC
 
 [FixedPcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
   gArmTokenSpaceGuid.PcdSystemMemoryBase
   gArmTokenSpaceGuid.PcdSystemMemorySize
   gArmTokenSpaceGuid.PcdArmPrimaryCore
   gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
 
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieBusMax
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieBusMin
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio32Base
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio32Size
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio64Base
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio64Size
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieRootPortConfigBaseAddress
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieRootPortConfigBaseSize
+
   gArmNeoverseN1SocTokenSpaceGuid.PcdDramBlock2Base
 
 [Guids]

+ 27 - 1
Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c

@@ -13,7 +13,7 @@
 #include <NeoverseN1Soc.h>
 
 // The total number of descriptors, including the final "end-of-table" descriptor.
-#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 9
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 13
 
 /**
   Returns the Virtual Memory Map of the platform.
@@ -88,6 +88,32 @@ ArmPlatformGetVirtualMemoryMap (
   VirtualMemoryTable[Index].Length          = NEOVERSEN1SOC_NON_SECURE_SRAM_SZ;
   VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;
 
+  // PCIe RC Configuration Space
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet32 (PcdPcieRootPortConfigBaseAddress);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet32 (PcdPcieRootPortConfigBaseAddress);
+  VirtualMemoryTable[Index].Length          = PcdGet32 (PcdPcieRootPortConfigBaseSize);
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // PCIe ECAM Configuration Space
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet64 (PcdPciExpressBaseAddress);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet64 (PcdPciExpressBaseAddress);
+  VirtualMemoryTable[Index].Length          = (FixedPcdGet32 (PcdPcieBusMax) -
+                                               FixedPcdGet32 (PcdPcieBusMin) + 1) *
+                                              SIZE_1MB;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // PCIe MMIO32 Memory Space
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet32 (PcdPcieMmio32Base);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet32 (PcdPcieMmio32Base);
+  VirtualMemoryTable[Index].Length          = PcdGet32 (PcdPcieMmio32Size);
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // PCIe MMIO64 Memory Space
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet64 (PcdPcieMmio64Base);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet64 (PcdPcieMmio64Base);
+  VirtualMemoryTable[Index].Length          = PcdGet64 (PcdPcieMmio64Size);
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
   // SubSystem Pheripherals - UART0
   VirtualMemoryTable[++Index].PhysicalBase  = NEOVERSEN1SOC_UART0_BASE;
   VirtualMemoryTable[Index].VirtualBase     = NEOVERSEN1SOC_UART0_BASE;

+ 15 - 0
Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec

@@ -29,3 +29,18 @@
   #PCIe
   gArmNeoverseN1SocTokenSpaceGuid.PcdPcieRootPortConfigBaseAddress|0x60000000|UINT32|0x00000002
   gArmNeoverseN1SocTokenSpaceGuid.PcdPcieRootPortConfigBaseSize|0x00001000|UINT32|0x00000003
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieBusCount|18|UINT32|0x00000004
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieBusMax|17|UINT32|0x00000005
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieBusMin|0|UINT32|0x00000006
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieIoBase|0x0|UINT32|0x00000007
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieIoMaxBase|0x00FFFFFF|UINT32|0x00000008
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieIoSize|0x01000000|UINT32|0x00000009
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieIoTranslation|0x75200000|UINT32|0x0000000A
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio32Base|0x71200000|UINT32|0x0000000B
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio32MaxBase|0x751FFFFF|UINT32|0x0000000C
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio32Size|0x04000000|UINT32|0x0000000D
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio32Translation|0x0|UINT32|0x0000000E
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio64Base|0x0900000000|UINT64|0x0000000F
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio64MaxBase|0x28FFFFFFFF|UINT64|0x00000010
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio64Size|0x2000000000|UINT64|0x00000011
+  gArmNeoverseN1SocTokenSpaceGuid.PcdPcieMmio64Translation|0x0|UINT64|0x00000012