public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support
@ 2019-05-09  9:53 Marcin Wojtas
  2019-05-09  9:53 ` [edk2-platforms: PATCH 01/14] Marvell/Library: MvGpioLib: Extend GPIO pin description Marcin Wojtas
                   ` (14 more replies)
  0 siblings, 15 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

Hi,

Hereby I submit Armada7k8k PCIE support. The commits
allow to use single controller on each of currently
supported boards (MacchiatoBin, A7040/A8040-DB) both in
firmware and in OS with ACPI boot. Multiple slots,
using custom PciSegmentLib, will be added later.

Current patchset can be grouped following way:
1. Preparation patches for Armada platforms (SoC and
   Board description libraries and protocol)

2. Implement PciHostBridgeLib/PciExpressLib and
   enable compilation.

3. ACPI support for each board + switch to pci-host-generic
   in MacchiatoBin DT.

4. Additional 2 small patches.

Thank to these commits (and all previously merged support), we can
now use mainline ARM-TF + EDK2 with DT and ACPI distributions and
operating systems. Example logs:
* McBin DT boot with pci-host-generic driver https://pastebin.com/5dRVCjRR
* McBin + Centos AltArch7 https://pastebin.com/BGx3Q6w0
* ACPI boot on Armada7040Db with USB over PCIE https://pastebin.com/kMMUnEr8

In case anyone wishes to try, for your convenience, I uploaded
the McBin binary built from the PCIE branch on top of the
latest edk2/edk2-platforms with today's ARM-TF:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/wiki/files/flash-image-mcbin-mainline-r20190509.bin

The patches are available in the github:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/pcie-upstream-r20190509

I'm looking forward to your comments or remarks.

Best regards,
Marcin

Ard Biesheuvel (1):
  Marvell/Armada7k8k: Add PciExpressLib implementation

Marcin Wojtas (13):
  Marvell/Library: MvGpioLib: Extend GPIO pin description
  Marvell/Library: ArmadaSoCDescLib: Add PCIE information
  Marvell/Library: ArmadaBoardDescLib: Add PCIE information
  Marvell/Armada7k8k: Extend board description libraries with PCIE
  Marvell/Armada7k8k: MvBoardDesc: Extend protocol with PCIE support
  Marvell/Armada7k8k: Implement PciHostBridgeLib
  Marvell/Armada7k8k: Enable PCIE support
  Marvell/Armada80x0McBin: Enable ACPI PCIE support
  Marvell/Armada80x0Db: Enable ACPI PCIE support
  Marvell/Armada70x0Db: Enable ACPI PCIE support
  Marvell/Armada80x0McBin: DeviceTree: Use pci-host-generic driver
  Marvell/Armada7k8k: Remove duplication in .dsc files
  Marvell/Armada7k8: Add 'acpiview' shell command to build

 Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc                                               |   18 +-
 Platform/Marvell/Armada70x0Db/Armada70x0Db.dsc                                              |    4 +-
 Platform/Marvell/Armada80x0Db/Armada80x0Db.dsc                                              |    4 +-
 Platform/SolidRun/Armada80x0McBin/Armada80x0McBin.dsc                                       |    4 +-
 Silicon/Marvell/Armada7k8k/Armada7k8k.fdf                                                   |    5 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf                                      |    1 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf                                      |    1 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf                                   |    1 +
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf                |   42 +
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf          |   52 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h                                   |   25 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h                                   |   25 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h                                |   25 +
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h |   95 ++
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h              |    6 +
 Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h                                        |   46 +
 Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h                                          |   20 +
 Silicon/Marvell/Include/Library/MvGpioLib.h                                                 |    1 +
 Silicon/Marvell/Include/Protocol/BoardDesc.h                                                |   22 +
 Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c           |   48 +
 Platform/Marvell/Armada70x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c               |    4 +
 Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c           |   48 +
 Platform/Marvell/Armada80x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c               |    6 +
 Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c |   48 +
 Platform/SolidRun/Armada80x0McBin/NonDiscoverableInitLib/NonDiscoverableInitLib.c           |    1 +
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c                  | 1529 ++++++++++++++++++++
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c            |  244 ++++
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c |  330 +++++
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c              |   44 +
 Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c                                          |   86 ++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl                                 |  217 +++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc                                |   47 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl                                 |  217 +++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc                                |   47 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl                              |  217 +++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc                             |   47 +
 Silicon/Marvell/Armada7k8k/DeviceTree/armada-8040-mcbin.dts                                 |    3 +
 37 files changed, 3569 insertions(+), 11 deletions(-)
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc

-- 
2.7.4


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 01/14] Marvell/Library: MvGpioLib: Extend GPIO pin description
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-09  9:53 ` [edk2-platforms: PATCH 02/14] Marvell/Library: ArmadaSoCDescLib: Add PCIE information Marcin Wojtas
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

In order to avoid hardcoding the controller type when using
MV_GPIO_PIN, extend this structure with new according field.
This patch is required to properly handle PCIE slot reset
with the GPIO pin.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Include/Library/MvGpioLib.h                                       | 1 +
 Platform/Marvell/Armada70x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c     | 4 ++++
 Platform/Marvell/Armada80x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c     | 6 ++++++
 Platform/SolidRun/Armada80x0McBin/NonDiscoverableInitLib/NonDiscoverableInitLib.c | 1 +
 4 files changed, 12 insertions(+)

diff --git a/Silicon/Marvell/Include/Library/MvGpioLib.h b/Silicon/Marvell/Include/Library/MvGpioLib.h
index a14acdf..2d5fa94 100644
--- a/Silicon/Marvell/Include/Library/MvGpioLib.h
+++ b/Silicon/Marvell/Include/Library/MvGpioLib.h
@@ -53,6 +53,7 @@ typedef struct {
 } MV_GPIO_DEVICE_PATH;
 
 typedef struct {
+  MV_GPIO_DRIVER_TYPE  ControllerType;
   UINTN    ControllerId;
   UINTN    PinNumber;
   BOOLEAN  ActiveHigh;
diff --git a/Platform/Marvell/Armada70x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c b/Platform/Marvell/Armada70x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c
index d8dba6e..62a57f7 100644
--- a/Platform/Marvell/Armada70x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c
+++ b/Platform/Marvell/Armada70x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c
@@ -29,21 +29,25 @@
 
 STATIC CONST MV_GPIO_PIN mXhciVbusPins[] = {
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_70x0_DB_IO_EXPANDER0,
     ARMADA_70x0_DB_VBUS0_PIN,
     TRUE,
   },
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_70x0_DB_IO_EXPANDER0,
     ARMADA_70x0_DB_VBUS0_LIMIT_PIN,
     TRUE,
   },
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_70x0_DB_IO_EXPANDER0,
     ARMADA_70x0_DB_VBUS1_PIN,
     TRUE,
   },
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_70x0_DB_IO_EXPANDER0,
     ARMADA_70x0_DB_VBUS1_LIMIT_PIN,
     TRUE,
diff --git a/Platform/Marvell/Armada80x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c b/Platform/Marvell/Armada80x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c
index e7a1d1e..1220163 100644
--- a/Platform/Marvell/Armada80x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c
+++ b/Platform/Marvell/Armada80x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c
@@ -29,31 +29,37 @@
 
 STATIC CONST MV_GPIO_PIN mXhciVbusPins[] = {
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_80x0_DB_IO_EXPANDER0,
     ARMADA_80x0_DB_VBUS0_PIN,
     TRUE,
   },
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_80x0_DB_IO_EXPANDER0,
     ARMADA_80x0_DB_VBUS0_LIMIT_PIN,
     TRUE,
   },
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_80x0_DB_IO_EXPANDER0,
     ARMADA_80x0_DB_VBUS1_PIN,
     TRUE,
   },
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_80x0_DB_IO_EXPANDER0,
     ARMADA_80x0_DB_VBUS1_LIMIT_PIN,
     TRUE,
   },
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_80x0_DB_IO_EXPANDER1,
     ARMADA_80x0_DB_VBUS2_PIN,
     TRUE,
   },
   {
+    MV_GPIO_DRIVER_TYPE_PCA95XX,
     ARMADA_80x0_DB_IO_EXPANDER1,
     ARMADA_80x0_DB_VBUS2_LIMIT_PIN,
     TRUE,
diff --git a/Platform/SolidRun/Armada80x0McBin/NonDiscoverableInitLib/NonDiscoverableInitLib.c b/Platform/SolidRun/Armada80x0McBin/NonDiscoverableInitLib/NonDiscoverableInitLib.c
index d1055cb..08c383f 100644
--- a/Platform/SolidRun/Armada80x0McBin/NonDiscoverableInitLib/NonDiscoverableInitLib.c
+++ b/Platform/SolidRun/Armada80x0McBin/NonDiscoverableInitLib/NonDiscoverableInitLib.c
@@ -28,6 +28,7 @@
 #include "NonDiscoverableInitLib.h"
 
 STATIC CONST MV_GPIO_PIN mXhciVbusPin = {
+  MV_GPIO_DRIVER_TYPE_SOC_CONTROLLER,
   MV_GPIO_CP0_CONTROLLER1,
   ARMADA_80x0_MCBIN_VBUS0_PIN,
   TRUE,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 02/14] Marvell/Library: ArmadaSoCDescLib: Add PCIE information
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
  2019-05-09  9:53 ` [edk2-platforms: PATCH 01/14] Marvell/Library: MvGpioLib: Extend GPIO pin description Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-10 14:59   ` Leif Lindholm
  2019-05-09  9:53 ` [edk2-platforms: PATCH 03/14] Marvell/Library: ArmadaBoardDescLib: " Marcin Wojtas
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

This patch introduces new library callback (ArmadaSoCPcieGet ()),
which dynamically allocates and fills array with all available PCIE
controllers' base addresses. It is needed for the configuration of PCIE,
whose support will be added in the upcoming patches.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h |  6 +++
 Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h                             | 20 +++++++++
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c | 44 ++++++++++++++++++++
 3 files changed, 70 insertions(+)

diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h
index 8bbc5b0..e904222 100644
--- a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h
+++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h
@@ -82,6 +82,12 @@
 #define MV_SOC_MDIO_ID(Cp)               (Cp)
 
 //
+// Platform description of PCIE
+//
+#define MV_SOC_PCIE_PER_CP_COUNT         3
+#define MV_SOC_PCIE_BASE(Index)          (0x600000 + ((Index) * 0x20000))
+
+//
 // Platform description of PP2 NIC
 //
 #define MV_SOC_PP2_BASE(Cp)              MV_SOC_CP_BASE (Cp)
diff --git a/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h b/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h
index fc17c3a..ff617e6 100644
--- a/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h
+++ b/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h
@@ -191,6 +191,26 @@ ArmadaSoCDescXhciGet (
   IN OUT UINTN              *DescCount
   );
 
+/**
+  This function returns the total number of PCIE controllers and an array
+  with their base addresses.
+
+  @param[in out] **PcieBaseAddresses  Array containing PCIE controllers' base
+                                     adresses.
+  @param[in out]  *Count             Total amount of available PCIE controllers.
+
+  @retval EFI_SUCCESS                The data were obtained successfully.
+  @retval EFI_OUT_OF_RESOURCES       The request could not be completed due to a
+                                     lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmadaSoCPcieGet (
+  IN OUT EFI_PHYSICAL_ADDRESS  **PcieBaseAddresses,
+  IN OUT UINTN                  *Count
+  );
+
 //
 // PP2 NIC devices SoC description
 //
diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c
index 355be64..4f8a59a 100644
--- a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c
+++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c
@@ -278,6 +278,50 @@ ArmadaSoCDescAhciGet (
   return EFI_SUCCESS;
 }
 
+/**
+  This function returns the total number of PCIE controllers and an array
+  with their base addresses.
+
+  @param[in out] **PcieBaseAddresses Array containing PCIE controllers' base
+                                     adresses.
+  @param[in out]  *Count             Total amount of available PCIE controllers.
+
+  @retval EFI_SUCCESS                The data were obtained successfully.
+  @retval EFI_OUT_OF_RESOURCES       The request could not be completed due to a
+                                     lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmadaSoCPcieGet (
+  IN OUT EFI_PHYSICAL_ADDRESS  **PcieBaseAddresses,
+  IN OUT UINTN                  *Count
+  )
+{
+  UINTN CpCount, CpIndex, Index;
+  EFI_PHYSICAL_ADDRESS *BaseAddress;
+
+  CpCount = FixedPcdGet8 (PcdMaxCpCount);
+
+  *Count = CpCount * MV_SOC_PCIE_PER_CP_COUNT;
+  BaseAddress = AllocateZeroPool (*Count * sizeof (EFI_PHYSICAL_ADDRESS));
+  if (BaseAddress == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  *PcieBaseAddresses = BaseAddress;
+
+  for (CpIndex = 0; CpIndex < CpCount; CpIndex++) {
+    for (Index = 0; Index < MV_SOC_PCIE_PER_CP_COUNT; Index++) {
+      *BaseAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_PCIE_BASE (Index);
+      BaseAddress++;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
 EFI_STATUS
 EFIAPI
 ArmadaSoCDescPp2Get (
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 03/14] Marvell/Library: ArmadaBoardDescLib: Add PCIE information
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
  2019-05-09  9:53 ` [edk2-platforms: PATCH 01/14] Marvell/Library: MvGpioLib: Extend GPIO pin description Marcin Wojtas
  2019-05-09  9:53 ` [edk2-platforms: PATCH 02/14] Marvell/Library: ArmadaSoCDescLib: Add PCIE information Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-16 13:57   ` Ard Biesheuvel
  2019-05-09  9:53 ` [edk2-platforms: PATCH 04/14] Marvell/Armada7k8k: Extend board description libraries with PCIE Marcin Wojtas
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

Introduce new callback that can provide information
about PCIE controller per-board description.
A new structure is defined containing base addresses,
windows/bus configuration and reset GPIO usage indication.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h | 46 ++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h b/Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h
index 6ec5ace..530a2ba 100644
--- a/Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h
+++ b/Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h
@@ -15,6 +15,7 @@
 #define __ARMADA_BOARD_DESC_LIB_H__
 
 #include <Library/ArmadaSoCDescLib.h>
+#include <Library/MvGpioLib.h>
 
 //
 // COMPHY controllers per-board description
@@ -111,6 +112,51 @@ typedef struct {
 } MV_BOARD_XHCI_DESC;
 
 //
+// PCIE controllers description
+//
+typedef struct {
+  EFI_PHYSICAL_ADDRESS PcieBaseAddress;
+  EFI_PHYSICAL_ADDRESS ConfigSpaceAddress;
+  BOOLEAN HaveResetGpio;
+  MV_GPIO_PIN PcieResetGpio;
+  UINT64 PcieBusMin;
+  UINT64 PcieBusMax;
+  UINT64 PcieIoTranslation;
+  UINT64 PcieIoWinBase;
+  UINT64 PcieIoWinSize;
+  UINT64 PcieMmio32Translation;
+  UINT64 PcieMmio32WinBase;
+  UINT64 PcieMmio32WinSize;
+  UINT64 PcieMmio64Translation;
+  UINT64 PcieMmio64WinBase;
+  UINT64 PcieMmio64WinSize;
+} MV_PCIE_CONTROLLER;
+
+typedef struct {
+  MV_PCIE_CONTROLLER *PcieControllers;
+  UINTN               PcieControllerCount;
+} MV_BOARD_PCIE_DESCRIPTION;
+
+/**
+  Return the number and description of PCIE controllers used on the platform.
+
+  @param[in out] **PcieControllers      Array containing PCIE controllers'
+                                        description.
+  @param[in out]  *PcieControllerCount  Amount of used PCIE controllers.
+
+  @retval EFI_SUCCESS                   The data were obtained successfully.
+  @retval EFI_NOT_FOUND                 None of the controllers is used.
+  @retval other                         Return error status.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmadaBoardPcieControllerGet (
+  IN OUT MV_PCIE_CONTROLLER **PcieControllers,
+  IN OUT UINTN               *PcieControllerCount
+  );
+
+//
 // PP2 NIC devices per-board description
 //
 typedef struct {
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 04/14] Marvell/Armada7k8k: Extend board description libraries with PCIE
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (2 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 03/14] Marvell/Library: ArmadaBoardDescLib: " Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-09 10:16   ` Marcin Wojtas
  2019-05-09  9:53 ` [edk2-platforms: PATCH 05/14] Marvell/Armada7k8k: MvBoardDesc: Extend protocol with PCIE support Marcin Wojtas
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

This patch extends ArmadaBoardDescLib libraries for all
existing Armada7k8k-based platforms with PCIE.
It introduces ArmadaBoardPcieControllerGet routine with
per-board PCIE controllers description.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c           | 48 ++++++++++++++++++++
 Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c           | 48 ++++++++++++++++++++
 Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c | 48 ++++++++++++++++++++
 3 files changed, 144 insertions(+)

diff --git a/Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c b/Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c
index f0133ec..cbd23cc 100644
--- a/Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c
+++ b/Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c
@@ -46,6 +46,54 @@ ArmadaBoardGpioExpanderGet (
 }
 
 //
+// PCIE
+//
+STATIC
+MV_PCIE_CONTROLLER mPcieController[] = {
+  { /* PCIE2 @0xF2640000 */
+    .PcieBaseAddress       = 0xF2640000,
+    .ConfigSpaceAddress    = 0xE0000000,
+    .HaveResetGpio         = FALSE,
+    .PcieResetGpio         = { 0 },
+    .PcieBusMin            = 0,
+    .PcieBusMax            = 0xFE,
+    .PcieIoTranslation     = 0xEFF00000,
+    .PcieIoWinBase         = 0x0,
+    .PcieIoWinSize         = 0x10000,
+    .PcieMmio32Translation = 0,
+    .PcieMmio32WinBase     = 0xC0000000,
+    .PcieMmio32WinSize     = 0x20000000,
+    .PcieMmio64Translation = 0,
+    .PcieMmio64WinBase     = 0x800000000,
+    .PcieMmio64WinSize     = 0x100000000,
+  }
+};
+
+/**
+  Return the number and description of PCIE controllers used on the platform.
+
+  @param[in out] **PcieControllers      Array containing PCIE controllers'
+                                        description.
+  @param[in out]  *PcieControllerCount  Amount of used PCIE controllers.
+
+  @retval EFI_SUCCESS                   The data were obtained successfully.
+  @retval other                         Return error status.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmadaBoardPcieControllerGet (
+  IN OUT MV_PCIE_CONTROLLER **PcieControllers,
+  IN OUT UINTN               *PcieControllerCount
+  )
+{
+  *PcieControllers = mPcieController;
+  *PcieControllerCount = ARRAY_SIZE (mPcieController);
+
+  return EFI_SUCCESS;
+}
+
+//
 // Order of devices in SdMmcDescTemplate has to be in par with ArmadaSoCDescLib
 //
 STATIC
diff --git a/Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c b/Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c
index 61b6202..5781756 100644
--- a/Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c
+++ b/Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c
@@ -52,6 +52,54 @@ ArmadaBoardGpioExpanderGet (
 }
 
 //
+// PCIE
+//
+STATIC
+MV_PCIE_CONTROLLER mPcieController[] = {
+  { /* PCIE0 @0xF2600000 */
+    .PcieBaseAddress       = 0xF2600000,
+    .ConfigSpaceAddress    = 0xE0000000,
+    .HaveResetGpio         = FALSE,
+    .PcieResetGpio         = { 0 },
+    .PcieBusMin            = 0,
+    .PcieBusMax            = 0xFE,
+    .PcieIoTranslation     = 0xEFF00000,
+    .PcieIoWinBase         = 0x0,
+    .PcieIoWinSize         = 0x10000,
+    .PcieMmio32Translation = 0,
+    .PcieMmio32WinBase     = 0xC0000000,
+    .PcieMmio32WinSize     = 0x20000000,
+    .PcieMmio64Translation = 0,
+    .PcieMmio64WinBase     = 0x800000000,
+    .PcieMmio64WinSize     = 0x100000000,
+  }
+};
+
+/**
+  Return the number and description of PCIE controllers used on the platform.
+
+  @param[in out] **PcieControllers      Array containing PCIE controllers'
+                                        description.
+  @param[in out]  *PcieControllerCount  Amount of used PCIE controllers.
+
+  @retval EFI_SUCCESS                   The data were obtained successfully.
+  @retval other                         Return error status.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmadaBoardPcieControllerGet (
+  IN OUT MV_PCIE_CONTROLLER **PcieControllers,
+  IN OUT UINTN               *PcieControllerCount
+  )
+{
+  *PcieControllers = mPcieController;
+  *PcieControllerCount = ARRAY_SIZE (mPcieController);
+
+  return EFI_SUCCESS;
+}
+
+//
 // Order of devices in SdMmcDescTemplate has to be in par with ArmadaSoCDescLib
 //
 STATIC
diff --git a/Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c b/Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c
index 32596ad..11a889b 100644
--- a/Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c
+++ b/Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c
@@ -39,6 +39,54 @@ ArmadaBoardGpioExpanderGet (
 }
 
 //
+// PCIE
+//
+STATIC
+MV_PCIE_CONTROLLER mPcieController[] = {
+  { /* PCIE0 @0xF2600000 */
+    .PcieBaseAddress       = 0xF2600000,
+    .ConfigSpaceAddress    = 0xE0000000,
+    .HaveResetGpio         = FALSE,
+    .PcieResetGpio         = { 0 },
+    .PcieBusMin            = 0,
+    .PcieBusMax            = 0xFE,
+    .PcieIoTranslation     = 0xEFF00000,
+    .PcieIoWinBase         = 0x0,
+    .PcieIoWinSize         = 0x10000,
+    .PcieMmio32Translation = 0,
+    .PcieMmio32WinBase     = 0xC0000000,
+    .PcieMmio32WinSize     = 0x20000000,
+    .PcieMmio64Translation = 0,
+    .PcieMmio64WinBase     = 0x800000000,
+    .PcieMmio64WinSize     = 0x100000000,
+  }
+};
+
+/**
+  Return the number and description of PCIE controllers used on the platform.
+
+  @param[in out] **PcieControllers      Array containing PCIE controllers'
+                                        description.
+  @param[in out]  *PcieControllerCount  Amount of used PCIE controllers.
+
+  @retval EFI_SUCCESS                   The data were obtained successfully.
+  @retval other                         Return error status.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmadaBoardPcieControllerGet (
+  IN OUT MV_PCIE_CONTROLLER **PcieControllers,
+  IN OUT UINTN               *PcieControllerCount
+  )
+{
+  *PcieControllers = mPcieController;
+  *PcieControllerCount = ARRAY_SIZE (mPcieController);
+
+  return EFI_SUCCESS;
+}
+
+//
 // Order of devices in SdMmcDescTemplate has to be in par with ArmadaSoCDescLib
 //
 STATIC
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 05/14] Marvell/Armada7k8k: MvBoardDesc: Extend protocol with PCIE support
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (3 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 04/14] Marvell/Armada7k8k: Extend board description libraries with PCIE Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-16 13:53   ` Ard Biesheuvel
  2019-05-09  9:53 ` [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation Marcin Wojtas
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

Introduce new callback that can provide information about PCIE
controllers, which are used on the platform. According ArmadaSoCDescLib
ArmadaBoardDescLib routines are used for obtaining required data.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Include/Protocol/BoardDesc.h       | 22 +++++
 Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c | 86 ++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/Silicon/Marvell/Include/Protocol/BoardDesc.h b/Silicon/Marvell/Include/Protocol/BoardDesc.h
index 02905ea..c38ad86 100644
--- a/Silicon/Marvell/Include/Protocol/BoardDesc.h
+++ b/Silicon/Marvell/Include/Protocol/BoardDesc.h
@@ -90,6 +90,27 @@ EFI_STATUS
   IN OUT MV_BOARD_XHCI_DESC      **XhciDesc
   );
 
+/**
+  Return the description of PCIE controllers used on the platform.
+
+  @param[in out]  *This                 Pointer to board description protocol.
+  @param[in out] **PcieDescription      Array containing PCIE controllers'
+                                        description.
+
+  @retval EFI_SUCCESS                   The data were obtained successfully.
+  @retval EFI_NOT_FOUND                 None of the controllers is used.
+  @retval EFI_INVALID_PARAMETER         Description wrongly defined.
+  @retval EFI_OUT_OF_RESOURCES          Lack of resources.
+  @retval Other                         Return error status.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *MV_BOARD_PCIE_DESCRIPTION_GET) (
+  IN MARVELL_BOARD_DESC_PROTOCOL     *This,
+  IN OUT MV_BOARD_PCIE_DESCRIPTION  **PcieDescription
+  );
+
 typedef
 EFI_STATUS
 (EFIAPI *MV_BOARD_DESC_PP2_GET) (
@@ -121,6 +142,7 @@ struct _MARVELL_BOARD_DESC_PROTOCOL {
   MV_BOARD_DESC_XHCI_GET         BoardDescXhciGet;
   MV_BOARD_DESC_FREE             BoardDescFree;
   MV_BOARD_GPIO_DESCRIPTION_GET  GpioDescriptionGet;
+  MV_BOARD_PCIE_DESCRIPTION_GET  PcieDescriptionGet;
 };
 
 #endif // __MARVELL_BOARD_DESC_PROTOCOL_H__
diff --git a/Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c b/Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c
index 973c362..9cd95bd 100644
--- a/Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c
+++ b/Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 MV_BOARD_DESC *mBoardDescInstance;
 
 STATIC MV_BOARD_GPIO_DESCRIPTION *mGpioDescription;
+STATIC MV_BOARD_PCIE_DESCRIPTION *mPcieDescription;
 
 STATIC
 EFI_STATUS
@@ -444,6 +445,90 @@ MvBoardDescXhciGet (
   return EFI_SUCCESS;
 }
 
+/**
+  Return the description of PCIE controllers used on the platform.
+
+  @param[in out]  *This                 Pointer to board description protocol.
+  @param[in out] **PcieDescription      Array containing PCIE controllers'
+                                        description.
+
+  @retval EFI_SUCCESS                   The data were obtained successfully.
+  @retval EFI_NOT_FOUND                 None of the controllers is used.
+  @retval EFI_INVALID_PARAMETER         Description wrongly defined.
+  @retval EFI_OUT_OF_RESOURCES          Lack of resources.
+  @retval Other                         Return error status.
+
+**/
+STATIC
+EFI_STATUS
+MvBoardPcieDescriptionGet (
+  IN MARVELL_BOARD_DESC_PROTOCOL    *This,
+  IN OUT MV_BOARD_PCIE_DESCRIPTION **PcieDescription
+  )
+{
+  UINTN SoCPcieControllerCount, BoardPcieControllerCount, SoCIndex, BoardIndex;
+  EFI_PHYSICAL_ADDRESS *PcieBaseAddresses;
+  MV_PCIE_CONTROLLER *PcieControllers;
+  EFI_STATUS Status;
+
+  /* Use existing structure if already created. */
+  if (mPcieDescription != NULL) {
+    *PcieDescription = mPcieDescription;
+    return EFI_SUCCESS;
+  }
+
+  /* Get SoC data about all available PCIE controllers. */
+  Status = ArmadaSoCPcieGet (&PcieBaseAddresses, &SoCPcieControllerCount);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  /* Get per-board information about all used PCIE controllers. */
+  Status = ArmadaBoardPcieControllerGet (&PcieControllers,
+             &BoardPcieControllerCount);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  /* Sanity check of the board description. */
+  if (BoardPcieControllerCount > SoCPcieControllerCount) {
+    DEBUG ((DEBUG_ERROR, "%a: Too many controllers described\n", __FUNCTION__));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  for (BoardIndex = 0; BoardIndex < BoardPcieControllerCount; BoardIndex++) {
+    for (SoCIndex = 0; SoCIndex < SoCPcieControllerCount; SoCIndex++) {
+      if (PcieControllers[BoardIndex].PcieBaseAddress ==
+          PcieBaseAddresses[SoCIndex]) {
+          /* Match found */
+          break;
+      }
+    }
+    if (SoCIndex == SoCPcieControllerCount) {
+      DEBUG ((DEBUG_ERROR,
+        "%a: Controller #%d base address invalid: 0x%x\n",
+        __FUNCTION__,
+        BoardIndex,
+        PcieControllers[BoardIndex].PcieBaseAddress));
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  /* Allocate and fill board description. */
+  mPcieDescription = AllocateZeroPool (sizeof (MV_BOARD_PCIE_DESCRIPTION));
+  if (mPcieDescription == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  mPcieDescription->PcieControllers = PcieControllers;
+  mPcieDescription->PcieControllerCount = BoardPcieControllerCount;
+
+  *PcieDescription = mPcieDescription;
+
+  return EFI_SUCCESS;
+}
+
 STATIC
 EFI_STATUS
 MvBoardDescPp2Get (
@@ -621,6 +706,7 @@ MvBoardDescInitProtocol (
   BoardDescProtocol->BoardDescXhciGet = MvBoardDescXhciGet;
   BoardDescProtocol->BoardDescFree = MvBoardDescFree;
   BoardDescProtocol->GpioDescriptionGet = MvBoardGpioDescriptionGet;
+  BoardDescProtocol->PcieDescriptionGet = MvBoardPcieDescriptionGet;
 
   return EFI_SUCCESS;
 }
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (4 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 05/14] Marvell/Armada7k8k: MvBoardDesc: Extend protocol with PCIE support Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-10 15:25   ` Leif Lindholm
  2019-05-16 14:02   ` Ard Biesheuvel
  2019-05-09  9:53 ` [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib Marcin Wojtas
                   ` (8 subsequent siblings)
  14 siblings, 2 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

From: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Implement a special version of PciExpressLib that takes the quirky
nature of the Synopsys Designware PCIe IP into account. In particular,
we need to ignores config space accesses to all devices on the first
bus except device 0, because the broadcast nature of type 0 configuration
cycles will result in whatever device is in the slot to appear at each
of the 32 device positions.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf |   42 +
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c   | 1529 ++++++++++++++++++++
 2 files changed, 1571 insertions(+)
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c

diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
new file mode 100644
index 0000000..8f09820
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
@@ -0,0 +1,42 @@
+## @file
+#
+#  Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
+#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
+#
+#  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                    = 0x0001001B
+  BASE_NAME                      = Armada7k8kPciExpressLib
+  FILE_GUID                      = f0926204-3061-40ed-8261-2aeccc7914c9
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciExpressLib
+
+[Sources]
+  PciExpressLib.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
+  PcdLib
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress  ## CONSUMES
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdPciBusMin
+  gArmTokenSpaceGuid.PcdPciBusMax
diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
new file mode 100644
index 0000000..8fa2eb6
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
@@ -0,0 +1,1529 @@
+/** @file
+
+  Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
+
+  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 <Base.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciExpressLib.h>
+
+/**
+  Assert the validity of a PCI address. A valid PCI address should contain 1's
+  only in the low 28 bits.
+
+  @param  A The address to validate.
+
+**/
+#define ASSERT_INVALID_PCI_ADDRESS(A) \
+  ASSERT (((A) & ~0xfffffff) == 0)
+
+/**
+  Registers a PCI device so PCI configuration registers may be accessed after
+  SetVirtualAddressMap().
+
+  Registers the PCI device specified by Address so all the PCI configuration
+  registers associated with that PCI device may be accessed after SetVirtualAddressMap()
+  is called.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @retval RETURN_SUCCESS           The PCI device was registered for runtime access.
+  @retval RETURN_UNSUPPORTED       An attempt was made to call this function
+                                   after ExitBootServices().
+  @retval RETURN_UNSUPPORTED       The resources required to access the PCI device
+                                   at runtime could not be mapped.
+  @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
+                                   complete the registration.
+
+**/
+RETURN_STATUS
+EFIAPI
+PciExpressRegisterForRuntimeAccess (
+  IN UINTN  Address
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  return RETURN_UNSUPPORTED;
+}
+
+#define ECAM_BUS_SIZE       SIZE_1MB
+#define ECAM_DEV_SIZE       SIZE_32KB
+
+STATIC
+BOOLEAN
+IgnoreBusDeviceFunction (
+  IN  UINTN   Address
+  )
+{
+  ASSERT (Address >= FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE);
+  ASSERT (Address < (FixedPcdGet32 (PcdPciBusMax) + 1) * ECAM_BUS_SIZE);
+
+  //
+  // Type 0 configuration cycles don't contain a b/d/f specifier, and so it
+  // is up to the bus that delivers them to ensure they only end up at the
+  // correct device/function. Sadly, the Synopsys IP does not implement this,
+  // and so we have to ignore config space accesses for all devices on the
+  // first bus except device 0.
+  //
+  return (Address >= (FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE +
+                      ECAM_DEV_SIZE) &&
+          Address < (FixedPcdGet32 (PcdPciBusMin) + 1) * ECAM_BUS_SIZE);
+}
+
+/**
+  Gets the base address of PCI Express.
+
+  This internal functions retrieves PCI Express Base Address via a PCD entry
+  PcdPciExpressBaseAddress.
+
+  @return The base address of PCI Express.
+
+**/
+VOID*
+GetPciExpressBaseAddress (
+  VOID
+  )
+{
+  return (VOID*)(UINTN) PcdGet64 (PcdPciExpressBaseAddress);
+}
+
+/**
+  Reads an 8-bit PCI configuration register.
+
+  Reads and returns the 8-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @return The read value from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressRead8 (
+  IN      UINTN                     Address
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
+}
+
+/**
+  Writes an 8-bit PCI configuration register.
+
+  Writes the 8-bit PCI configuration register specified by Address with the
+  value specified by Value. Value is returned. This function must guarantee
+  that all PCI read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  Value   The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressWrite8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
+}
+
+/**
+  Performs a bitwise OR of an 8-bit PCI configuration register with
+  an 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 8-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressOr8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
+}
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
+  value.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 8-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressAnd8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
+}
+
+/**
+  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
+  value, followed a  bitwise OR with another 8-bit value.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and
+  the value specified by OrData, and writes the result to the 8-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressAndThenOr8 (
+  IN      UINTN                     Address,
+  IN      UINT8                     AndData,
+  IN      UINT8                     OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioAndThenOr8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field of a PCI configuration register.
+
+  Reads the bit field in an 8-bit PCI configuration register. The bit field is
+  specified by the StartBit and the EndBit. The value of the bit field is
+  returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to read.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+
+  @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldRead8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioBitFieldRead8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit
+           );
+}
+
+/**
+  Writes a bit field to a PCI configuration register.
+
+  Writes Value to the bit field of the PCI configuration register. The bit
+  field is specified by the StartBit and the EndBit. All other bits in the
+  destination PCI configuration register are preserved. The new value of the
+  8-bit register is returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  Value     The new value of the bit field.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldWrite8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioBitFieldWrite8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           Value
+           );
+}
+
+/**
+  Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
+  writes the result back to the bit field in the 8-bit port.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 8-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized. Extra left bits in OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldOr8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioBitFieldOr8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
+  AND, and writes the result back to the bit field in the 8-bit register.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 8-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized. Extra left bits in AndData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldAnd8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioBitFieldAnd8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData
+           );
+}
+
+/**
+  Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
+  bitwise OR, and writes the result back to the bit field in the
+  8-bit port.
+
+  Reads the 8-bit PCI configuration register specified by Address, performs a
+  bitwise AND followed by a bitwise OR between the read result and
+  the value specified by AndData, and writes the result to the 8-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized. Extra left bits in both AndData and
+  OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If StartBit is greater than 7, then ASSERT().
+  If EndBit is greater than 7, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..7.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..7.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldAndThenOr8 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT8                     AndData,
+  IN      UINT8                     OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xff;
+  }
+  return MmioBitFieldAndThenOr8 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a 16-bit PCI configuration register.
+
+  Reads and returns the 16-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @return The read value from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressRead16 (
+  IN      UINTN                     Address
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
+}
+
+/**
+  Writes a 16-bit PCI configuration register.
+
+  Writes the 16-bit PCI configuration register specified by Address with the
+  value specified by Value. Value is returned. This function must guarantee
+  that all PCI read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  Value   The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressWrite16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
+}
+
+/**
+  Performs a bitwise OR of a 16-bit PCI configuration register with
+  a 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 16-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
+}
+
+/**
+  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
+  value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 16-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressAnd16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
+}
+
+/**
+  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
+  value, followed a  bitwise OR with another 16-bit value.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and
+  the value specified by OrData, and writes the result to the 16-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressAndThenOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData,
+  IN      UINT16                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioAndThenOr16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field of a PCI configuration register.
+
+  Reads the bit field in a 16-bit PCI configuration register. The bit field is
+  specified by the StartBit and the EndBit. The value of the bit field is
+  returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to read.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+
+  @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldRead16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioBitFieldRead16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit
+           );
+}
+
+/**
+  Writes a bit field to a PCI configuration register.
+
+  Writes Value to the bit field of the PCI configuration register. The bit
+  field is specified by the StartBit and the EndBit. All other bits in the
+  destination PCI configuration register are preserved. The new value of the
+  16-bit register is returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  Value     The new value of the bit field.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldWrite16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioBitFieldWrite16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           Value
+           );
+}
+
+/**
+  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
+  writes the result back to the bit field in the 16-bit port.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 16-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized. Extra left bits in OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldOr16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioBitFieldOr16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
+  AND, and writes the result back to the bit field in the 16-bit register.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 16-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized. Extra left bits in AndData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldAnd16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioBitFieldAnd16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData
+           );
+}
+
+/**
+  Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
+  bitwise OR, and writes the result back to the bit field in the
+  16-bit port.
+
+  Reads the 16-bit PCI configuration register specified by Address, performs a
+  bitwise AND followed by a bitwise OR between the read result and
+  the value specified by AndData, and writes the result to the 16-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized. Extra left bits in both AndData and
+  OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+  If StartBit is greater than 15, then ASSERT().
+  If EndBit is greater than 15, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..15.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..15.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldAndThenOr16 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT16                    AndData,
+  IN      UINT16                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffff;
+  }
+  return MmioBitFieldAndThenOr16 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a 32-bit PCI configuration register.
+
+  Reads and returns the 32-bit PCI configuration register specified by Address.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+
+  @return The read value from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressRead32 (
+  IN      UINTN                     Address
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+  return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address);
+}
+
+/**
+  Writes a 32-bit PCI configuration register.
+
+  Writes the 32-bit PCI configuration register specified by Address with the
+  value specified by Value. Value is returned. This function must guarantee
+  that all PCI read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  Value   The value to write.
+
+  @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressWrite32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+  return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
+}
+
+/**
+  Performs a bitwise OR of a 32-bit PCI configuration register with
+  a 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 32-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  OrData  The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+  return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
+}
+
+/**
+  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
+  value.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 32-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressAnd32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
+}
+
+/**
+  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
+  value, followed a  bitwise OR with another 32-bit value.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData,
+  performs a bitwise OR between the result of the AND operation and
+  the value specified by OrData, and writes the result to the 32-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The address that encodes the PCI Bus, Device, Function and
+                  Register.
+  @param  AndData The value to AND with the PCI configuration register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressAndThenOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData,
+  IN      UINT32                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+  return MmioAndThenOr32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field of a PCI configuration register.
+
+  Reads the bit field in a 32-bit PCI configuration register. The bit field is
+  specified by the StartBit and the EndBit. The value of the bit field is
+  returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to read.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+
+  @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldRead32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+  return MmioBitFieldRead32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit
+           );
+}
+
+/**
+  Writes a bit field to a PCI configuration register.
+
+  Writes Value to the bit field of the PCI configuration register. The bit
+  field is specified by the StartBit and the EndBit. All other bits in the
+  destination PCI configuration register are preserved. The new value of the
+  32-bit register is returned.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  Value     The new value of the bit field.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldWrite32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    Value
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+  return MmioBitFieldWrite32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           Value
+           );
+}
+
+/**
+  Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
+  writes the result back to the bit field in the 32-bit port.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise OR between the read result and the value specified by
+  OrData, and writes the result to the 32-bit PCI configuration register
+  specified by Address. The value written to the PCI configuration register is
+  returned. This function must guarantee that all PCI read and write operations
+  are serialized. Extra left bits in OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  OrData    The value to OR with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldOr32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+  return MmioBitFieldOr32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           OrData
+           );
+}
+
+/**
+  Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
+  AND, and writes the result back to the bit field in the 32-bit register.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND between the read result and the value specified by AndData, and
+  writes the result to the 32-bit PCI configuration register specified by
+  Address. The value written to the PCI configuration register is returned.
+  This function must guarantee that all PCI read and write operations are
+  serialized. Extra left bits in AndData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  AndData   The value to AND with the PCI configuration register.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldAnd32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    AndData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+  return MmioBitFieldAnd32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData
+           );
+}
+
+/**
+  Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
+  bitwise OR, and writes the result back to the bit field in the
+  32-bit port.
+
+  Reads the 32-bit PCI configuration register specified by Address, performs a
+  bitwise AND followed by a bitwise OR between the read result and
+  the value specified by AndData, and writes the result to the 32-bit PCI
+  configuration register specified by Address. The value written to the PCI
+  configuration register is returned. This function must guarantee that all PCI
+  read and write operations are serialized. Extra left bits in both AndData and
+  OrData are stripped.
+
+  If Address > 0x0FFFFFFF, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+  If StartBit is greater than 31, then ASSERT().
+  If EndBit is greater than 31, then ASSERT().
+  If EndBit is less than StartBit, then ASSERT().
+  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+  @param  Address   The PCI configuration register to write.
+  @param  StartBit  The ordinal of the least significant bit in the bit field.
+                    Range 0..31.
+  @param  EndBit    The ordinal of the most significant bit in the bit field.
+                    Range 0..31.
+  @param  AndData   The value to AND with the PCI configuration register.
+  @param  OrData    The value to OR with the result of the AND operation.
+
+  @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldAndThenOr32 (
+  IN      UINTN                     Address,
+  IN      UINTN                     StartBit,
+  IN      UINTN                     EndBit,
+  IN      UINT32                    AndData,
+  IN      UINT32                    OrData
+  )
+{
+  ASSERT_INVALID_PCI_ADDRESS (Address);
+  if (IgnoreBusDeviceFunction (Address)) {
+    return 0xffffffff;
+  }
+  return MmioBitFieldAndThenOr32 (
+           (UINTN) GetPciExpressBaseAddress () + Address,
+           StartBit,
+           EndBit,
+           AndData,
+           OrData
+           );
+}
+
+/**
+  Reads a range of PCI configuration registers into a caller supplied buffer.
+
+  Reads the range of PCI configuration registers specified by StartAddress and
+  Size into the buffer specified by Buffer. This function only allows the PCI
+  configuration registers from a single PCI function to be read. Size is
+  returned. When possible 32-bit PCI configuration read cycles are used to read
+  from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit
+  and 16-bit PCI configuration read cycles may be used at the beginning and the
+  end of the range.
+
+  If StartAddress > 0x0FFFFFFF, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer receiving the data read.
+
+  @return Size read data from StartAddress.
+
+**/
+UINTN
+EFIAPI
+PciExpressReadBuffer (
+  IN      UINTN                     StartAddress,
+  IN      UINTN                     Size,
+  OUT     VOID                      *Buffer
+  )
+{
+  UINTN   ReturnValue;
+
+  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
+  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+  if (Size == 0) {
+    return Size;
+  }
+
+  ASSERT (Buffer != NULL);
+
+  //
+  // Save Size for return
+  //
+  ReturnValue = Size;
+
+  if ((StartAddress & 1) != 0) {
+    //
+    // Read a byte if StartAddress is byte aligned
+    //
+    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
+    StartAddress += sizeof (UINT8);
+    Size -= sizeof (UINT8);
+    Buffer = (UINT8*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
+    //
+    // Read a word if StartAddress is word aligned
+    //
+    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
+
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Read as many double words as possible
+    //
+    WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress));
+
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Read the last remaining word if exist
+    //
+    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT8)) {
+    //
+    // Read the last remaining byte if exist
+    //
+    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
+  }
+
+  return ReturnValue;
+}
+
+/**
+  Copies the data in a caller supplied buffer to a specified range of PCI
+  configuration space.
+
+  Writes the range of PCI configuration registers specified by StartAddress and
+  Size from the buffer specified by Buffer. This function only allows the PCI
+  configuration registers from a single PCI function to be written. Size is
+  returned. When possible 32-bit PCI configuration write cycles are used to
+  write from StartAddress to StartAddress + Size. Due to alignment restrictions,
+  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
+  and the end of the range.
+
+  If StartAddress > 0x0FFFFFFF, then ASSERT().
+  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+  If Size > 0 and Buffer is NULL, then ASSERT().
+
+  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
+                        Function and Register.
+  @param  Size          The size in bytes of the transfer.
+  @param  Buffer        The pointer to a buffer containing the data to write.
+
+  @return Size written to StartAddress.
+
+**/
+UINTN
+EFIAPI
+PciExpressWriteBuffer (
+  IN      UINTN                     StartAddress,
+  IN      UINTN                     Size,
+  IN      VOID                      *Buffer
+  )
+{
+  UINTN                             ReturnValue;
+
+  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
+  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+  if (Size == 0) {
+    return 0;
+  }
+
+  ASSERT (Buffer != NULL);
+
+  //
+  // Save Size for return
+  //
+  ReturnValue = Size;
+
+  if ((StartAddress & 1) != 0) {
+    //
+    // Write a byte if StartAddress is byte aligned
+    //
+    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
+    StartAddress += sizeof (UINT8);
+    Size -= sizeof (UINT8);
+    Buffer = (UINT8*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
+    //
+    // Write a word if StartAddress is word aligned
+    //
+    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Write as many double words as possible
+    //
+    PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Write the last remaining word if exist
+    //
+    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + 1;
+  }
+
+  if (Size >= sizeof (UINT8)) {
+    //
+    // Write the last remaining byte if exist
+    //
+    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
+  }
+
+  return ReturnValue;
+}
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (5 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-10 15:50   ` Leif Lindholm
  2019-05-16 14:14   ` Ard Biesheuvel
  2019-05-09  9:53 ` [edk2-platforms: PATCH 08/14] Marvell/Armada7k8k: Enable PCIE support Marcin Wojtas
                   ` (7 subsequent siblings)
  14 siblings, 2 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

Add an implementation of the PciHostBridgeLib glue library that
describes the PCIe RC on this SoC so that the generic PCI host bridge
driver can attach to it.

This includes a constructor which performs the SoC specific init and
training sequences.

This patch is based on work of Ard Biesheuvel <ard.biesheuvel@linaro.org>
and Jing Hua <jinghua@marvell.com>/

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf          |  52 +++
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h |  95 ++++++
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c            | 244 +++++++++++++++
 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c | 330 ++++++++++++++++++++
 4 files changed, 721 insertions(+)
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
 create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c

diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
new file mode 100644
index 0000000..e46f71d
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
@@ -0,0 +1,52 @@
+## @file
+#  PCI Host Bridge Library instance for Marvell Armada 7k/8k SOC
+#
+#  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
+#
+#  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                    = 0x0001001B
+  BASE_NAME                      = Armada7k8kPciHostBridgeLib
+  FILE_GUID                      = 7f989c9d-02a0-4348-8aeb-ab2e1566fb18
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciHostBridgeLib|DXE_DRIVER
+  CONSTRUCTOR                    = Armada7k8kPciHostBridgeLibConstructor
+
+[Sources]
+  PciHostBridgeLib.c
+  PciHostBridgeLibConstructor.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/Marvell/Marvell.dec
+
+[LibraryClasses]
+  ArmLib
+  ArmadaSoCDescLib
+  DebugLib
+  DevicePathLib
+  MemoryAllocationLib
+  MvGpioLib
+  UefiBootServicesTableLib
+
+[Protocols]
+  gEmbeddedGpioProtocolGuid
+  gMarvellBoardDescProtocolGuid
+
+[Depex]
+  gMarvellPlatformInitCompleteProtocolGuid
diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
new file mode 100644
index 0000000..ff9d919
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
@@ -0,0 +1,95 @@
+/** @file
+  PCI Host Bridge Library instance for Marvell 70x0/80x0
+
+  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
+
+  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 __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
+#define __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
+
+#define IATU_VIEWPORT_OFF                                   0x900
+#define IATU_VIEWPORT_INBOUND                               BIT31
+#define IATU_VIEWPORT_OUTBOUND                              0
+#define IATU_VIEWPORT_REGION_INDEX(Idx)                     ((Idx) & 7)
+
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0                   0x904
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM          0x0
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO           0x2
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0         0x4
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1         0x5
+
+#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0                   0x908
+#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN         BIT31
+#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE    BIT28
+
+#define IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0                   0x90C
+#define IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0                 0x910
+#define IATU_LIMIT_ADDR_OFF_OUTBOUND_0                      0x914
+#define IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0                 0x918
+#define IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0               0x91C
+
+#define PORT_LINK_CTRL_OFF                                  0x710
+#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x1                  (0x01 << 16)
+#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x2                  (0x03 << 16)
+#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4                  (0x07 << 16)
+#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x8                  (0x0f << 16)
+#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x16                 (0x1f << 16)
+#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK                (0x3f << 16)
+
+#define GEN2_CTRL_OFF                                       0x80c
+#define GEN2_CTRL_OFF_NUM_OF_LANES(n)                       (((n) & 0x1f) << 8)
+#define GEN2_CTRL_OFF_NUM_OF_LANES_MASK                     (0x1f << 8)
+#define GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE                   BIT17
+
+#define PCIE_GLOBAL_CTRL_OFFSET                             0x8000
+#define PCIE_GLOBAL_APP_LTSSM_EN                            BIT2
+#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC                     (0x4 << 4)
+#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK                   (0xF << 4)
+
+#define PCIE_GLOBAL_STATUS_REG                              0x8008
+#define PCIE_GLOBAL_STATUS_RDLH_LINK_UP                     BIT1
+#define PCIE_GLOBAL_STATUS_PHY_LINK_UP                      BIT9
+
+#define PCIE_PM_STATUS                                      0x8014
+#define PCIE_PM_LTSSM_STAT_MASK                             (0x3f << 3)
+
+#define PCIE_GLOBAL_INT_MASK1_REG                           0x8020
+#define PCIE_INT_A_ASSERT_MASK                              BIT9
+#define PCIE_INT_B_ASSERT_MASK                              BIT10
+#define PCIE_INT_C_ASSERT_MASK                              BIT11
+#define PCIE_INT_D_ASSERT_MASK                              BIT12
+
+#define PCIE_ARCACHE_TRC_REG                                0x8050
+#define PCIE_AWCACHE_TRC_REG                                0x8054
+#define PCIE_ARUSER_REG                                     0x805C
+#define PCIE_AWUSER_REG                                     0x8060
+
+#define ARCACHE_DEFAULT_VALUE                               0x3511
+#define AWCACHE_DEFAULT_VALUE                               0x5311
+
+#define AX_USER_DOMAIN_INNER_SHAREABLE                      (0x1 << 4)
+#define AX_USER_DOMAIN_OUTER_SHAREABLE                      (0x2 << 4)
+#define AX_USER_DOMAIN_MASK                                 (0x3 << 4)
+
+#define PCIE_LINK_CAPABILITY                                0x7C
+#define PCIE_LINK_CTL_2                                     0xA0
+#define TARGET_LINK_SPEED_MASK                              0xF
+#define LINK_SPEED_GEN_1                                    0x1
+#define LINK_SPEED_GEN_2                                    0x2
+#define LINK_SPEED_GEN_3                                    0x3
+
+#define PCIE_GEN3_EQU_CTRL                                  0x8A8
+#define GEN3_EQU_EVAL_2MS_DISABLE                           BIT5
+
+#define PCIE_LINK_UP_TIMEOUT_US                             40000
+
+#endif
diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
new file mode 100644
index 0000000..ff6288c
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
@@ -0,0 +1,244 @@
+/** @file
+  PCI Host Bridge Library instance for Marvell Armada 70x0/80x0
+
+  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
+
+  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 <PiDxe.h>
+
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/BoardDesc.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#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 = {
+  {
+    {
+      ACPI_DEVICE_PATH,
+      ACPI_DP,
+      {
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
+      }
+    },
+    EISA_PNP_ID(0x0A08), // PCI Express
+    0
+  },
+
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      END_DEVICE_PATH_LENGTH,
+      0
+    }
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
+  L"Mem", L"I/O", L"Bus"
+};
+
+/**
+  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
+  )
+{
+  MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol;
+  MV_BOARD_PCIE_DESCRIPTION   *BoardPcieDescription;
+  MV_PCIE_CONTROLLER          *PcieController;
+  PCI_ROOT_BRIDGE             *PciRootBridges;
+  PCI_ROOT_BRIDGE             *RootBridge;
+  EFI_STATUS                   Status;
+  UINTN                        Index;
+
+  *Count = 0;
+
+  /* Obtain list of available controllers */
+  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
+                  NULL,
+                  (VOID **)&BoardDescriptionProtocol);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "%a: Cannot locate BoardDesc protocol\n",
+      __FUNCTION__));
+    return NULL;
+  }
+
+  Status = BoardDescriptionProtocol->PcieDescriptionGet (
+                                       BoardDescriptionProtocol,
+                                       &BoardPcieDescription);
+  if (Status == EFI_NOT_FOUND) {
+    /* No controllers used on the platform, exit silently */
+    return NULL;
+  } else if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "%a: Cannot get Pcie board desc from BoardDesc protocol\n",
+      __FUNCTION__));
+    return NULL;
+  }
+
+  /* Assign return values */
+  PciRootBridges = AllocateZeroPool (BoardPcieDescription->PcieControllerCount *
+                                     sizeof (PCI_ROOT_BRIDGE));
+  if (PciRootBridges == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate resources\n", __FUNCTION__));
+    return NULL;
+  }
+
+  *Count = BoardPcieDescription->PcieControllerCount;
+  RootBridge = PciRootBridges;
+
+  /* Fill information of all root bridge instances */
+  for (Index = 0; Index < *Count; Index++, RootBridge++) {
+
+    PcieController = &(BoardPcieDescription->PcieControllers[Index]);
+
+    RootBridge->Segment   = 0;
+    RootBridge->Supports  = 0;
+    RootBridge->Attributes  = RootBridge->Supports;
+
+    RootBridge->DmaAbove4G  = FALSE;
+
+    RootBridge->AllocationAttributes  = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |
+                                        EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
+
+    RootBridge->Bus.Base = PcieController->PcieBusMin;
+    RootBridge->Bus.Limit = PcieController->PcieBusMax;
+    RootBridge->Io.Base = PcieController->PcieIoWinBase;
+    RootBridge->Io.Limit = PcieController->PcieIoWinBase +
+                           PcieController->PcieIoWinSize - 1;
+    RootBridge->Mem.Base = PcieController->PcieMmio32WinBase;
+    RootBridge->Mem.Limit = PcieController->PcieMmio32WinBase +
+                            PcieController->PcieMmio32WinSize - 1;
+    RootBridge->MemAbove4G.Base = PcieController->PcieMmio64WinBase;
+    RootBridge->MemAbove4G.Limit = PcieController->PcieMmio64WinBase +
+                                   PcieController->PcieMmio64WinSize - 1;
+
+    /* No separate ranges for prefetchable and non-prefetchable BARs */
+    RootBridge->PMem.Base           = MAX_UINT64;
+    RootBridge->PMem.Limit          = 0;
+    RootBridge->PMemAbove4G.Base    = MAX_UINT64;
+    RootBridge->PMemAbove4G.Limit   = 0;
+
+    ASSERT (PcieController->PcieMmio64Translation == 0);
+    ASSERT (PcieController->PcieMmio32Translation == 0);
+
+    RootBridge->NoExtendedConfigSpace = FALSE;
+
+    RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath;
+  }
+
+  return PciRootBridges;
+}
+
+/**
+  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
+  )
+{
+  FreePool (Bridges);
+}
+
+/**
+  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;
+  UINTN                              RootBridgeIndex;
+
+  DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
+
+  RootBridgeIndex = 0;
+  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+
+    DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
+
+    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);
+  }
+}
diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
new file mode 100644
index 0000000..ced2c12
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
@@ -0,0 +1,330 @@
+/** @file
+  PCI Host Bridge Library instance for Marvell 70x0/80x0
+
+  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
+
+  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 <PiDxe.h>
+
+#include <IndustryStandard/Pci22.h>
+
+#include <Library/ArmLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MvGpioLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/BoardDesc.h>
+
+#include "PciHostBridgeLibConstructor.h"
+
+/**
+  This function configures PCIE controllers IATU windows.
+
+  @param [in] PcieBaseAddress PCIE controller base address.
+  @param [in] Index           IATU window index.
+  @param [in] CpuBase         Address from the CPU perspective.
+  @param [in] PciBase         Target PCIE address.
+  @param [in] Size            IATU window size.
+  @param [in] Type            IATU window type.
+  @param [in] EnableFlags     Extra configuration flags.
+
+  @retval none
+
+**/
+STATIC
+VOID
+ConfigureWindow (
+  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress,
+  IN UINTN                Index,
+  IN UINT64               CpuBase,
+  IN UINT64               PciBase,
+  IN UINT64               Size,
+  IN UINTN                Type,
+  IN UINTN                EnableFlags
+  )
+{
+  ArmDataMemoryBarrier ();
+
+  MmioWrite32 (PcieBaseAddress + IATU_VIEWPORT_OFF,
+    IATU_VIEWPORT_OUTBOUND | IATU_VIEWPORT_REGION_INDEX (Index));
+
+  ArmDataMemoryBarrier ();
+
+  MmioWrite32 (PcieBaseAddress + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
+    (UINT32)(CpuBase & 0xFFFFFFFF));
+  MmioWrite32 (PcieBaseAddress + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
+    (UINT32)(CpuBase >> 32));
+  MmioWrite32 (PcieBaseAddress + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
+    (UINT32)(CpuBase + Size - 1));
+  MmioWrite32 (PcieBaseAddress + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
+    (UINT32)(PciBase & 0xFFFFFFFF));
+  MmioWrite32 (PcieBaseAddress + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
+    (UINT32)(PciBase >> 32));
+  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
+    Type);
+  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
+    IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN | EnableFlags);
+}
+
+/**
+  Perform PCIE slot reset using external GPIO pin.
+
+  @param [in] PcieBaseAddress  PCIE controller base address.
+
+  @retval none
+
+**/
+STATIC
+VOID
+WaitForLink (
+  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress
+  )
+{
+  UINT32 Mask;
+  UINT32 Status;
+  UINT32 Timeout;
+
+  if (!(MmioRead32 (PcieBaseAddress + PCIE_PM_STATUS) & PCIE_PM_LTSSM_STAT_MASK)) {
+    DEBUG ((DEBUG_INIT, "%a: no PCIE device detected\n", __FUNCTION__));
+    return;
+  }
+
+  /* Wait for the link to establish itself */
+  DEBUG ((DEBUG_INIT, "%a: waiting for PCIE link\n", __FUNCTION__));
+
+  Mask = PCIE_GLOBAL_STATUS_RDLH_LINK_UP | PCIE_GLOBAL_STATUS_PHY_LINK_UP;
+  Timeout = PCIE_LINK_UP_TIMEOUT_US / 10;
+  do {
+    Status = MmioRead32 (PcieBaseAddress + PCIE_GLOBAL_STATUS_REG);
+    if ((Status & Mask) == Mask) {
+      DEBUG ((DEBUG_ERROR, "pcie@0x%x link UP\n", PcieBaseAddress));
+      break;
+    }
+    gBS->Stall (10);
+  } while (Timeout--);
+}
+
+/**
+  Perform PCIE slot reset using external GPIO pin.
+
+  @param [in] *PcieResetGpio  GPIO pin description.
+
+  @retval EFI_SUCEESS         PCIE slot reset succeeded.
+  @retval Other               Return error status.
+
+**/
+STATIC
+EFI_STATUS
+ResetPcieSlot (
+  IN MV_GPIO_PIN *PcieResetGpio
+  )
+{
+  EMBEDDED_GPIO_MODE   Mode;
+  EMBEDDED_GPIO_PIN    GpioPin;
+  EMBEDDED_GPIO       *GpioProtocol;
+  EFI_STATUS           Status;
+
+  /* Get GPIO protocol */
+  Status = MvGpioGetProtocol (PcieResetGpio->ControllerType, &GpioProtocol);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Unable to find GPIO protocol\n", __FUNCTION__));
+    return Status;
+  }
+
+  GpioPin = GPIO (PcieResetGpio->ControllerId, PcieResetGpio->PinNumber),
+
+  /* Reset the slot by toggling the GPIO pin */
+  Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_1 : GPIO_MODE_OUTPUT_0;
+  Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode);
+  gBS->Stall (10 * 1000);
+
+  Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_0 : GPIO_MODE_OUTPUT_1;
+  Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode);
+  gBS->Stall (20 * 1000);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Obtain resources and perform a low-level PCIE controllers
+  configuration.
+
+  @param [in]  ImageHandle  The image handle.
+  @param [in] *SystemTable  The system table.
+
+  @retval EFI_SUCEESS       PCIE configuration successful.
+  @retval Other             Return error status.
+
+**/
+EFI_STATUS
+EFIAPI
+Armada7k8kPciHostBridgeLibConstructor (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol;
+  MV_BOARD_PCIE_DESCRIPTION   *BoardPcieDescription;
+  MV_PCIE_CONTROLLER          *PcieController;
+  EFI_PHYSICAL_ADDRESS         PcieBaseAddress;
+  EFI_STATUS                   Status;
+  UINTN                        Index;
+
+  /* Obtain list of available controllers */
+  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
+                  NULL,
+                  (VOID **)&BoardDescriptionProtocol);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "%a: Cannot locate BoardDesc protocol\n",
+      __FUNCTION__));
+    return EFI_DEVICE_ERROR;
+  }
+
+  Status = BoardDescriptionProtocol->PcieDescriptionGet (
+                                       BoardDescriptionProtocol,
+                                       &BoardPcieDescription);
+  if (Status == EFI_NOT_FOUND) {
+    /* No controllers used on the platform, exit silently */
+    return EFI_SUCCESS;
+  } else if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "%a: Cannot get Pcie board desc from BoardDesc protocol\n",
+      __FUNCTION__));
+    return EFI_DEVICE_ERROR;
+  }
+
+  for (Index = 0; Index < BoardPcieDescription->PcieControllerCount; Index++) {
+
+    PcieController = &(BoardPcieDescription->PcieControllers[Index]);
+
+    ASSERT (PcieController->PcieBusMin == 0);
+    ASSERT (PcieController->ConfigSpaceAddress % SIZE_256MB == 0);
+
+    if (PcieController->HaveResetGpio == TRUE) {
+      /* Reset PCIE slot */
+      Status = ResetPcieSlot (&PcieController->PcieResetGpio);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR,
+          "%a: Cannot reset Pcie Slot\n",
+          __FUNCTION__));
+        return EFI_DEVICE_ERROR;
+      }
+    }
+
+    /* Low level PCIE controller configuration */
+    PcieBaseAddress = PcieController->PcieBaseAddress;
+
+    MmioAndThenOr32 (PcieBaseAddress + PORT_LINK_CTRL_OFF,
+      ~PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK,
+      PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4);
+
+    MmioAndThenOr32 (PcieBaseAddress + GEN2_CTRL_OFF,
+      ~GEN2_CTRL_OFF_NUM_OF_LANES_MASK,
+      GEN2_CTRL_OFF_NUM_OF_LANES(4) | GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE);
+
+    MmioAndThenOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET,
+      ~(PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK | PCIE_GLOBAL_APP_LTSSM_EN),
+      PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC);
+
+    MmioWrite32 (PcieBaseAddress + PCIE_ARCACHE_TRC_REG,
+      ARCACHE_DEFAULT_VALUE);
+
+    MmioWrite32 (PcieBaseAddress + PCIE_AWCACHE_TRC_REG,
+      AWCACHE_DEFAULT_VALUE);
+
+    MmioAndThenOr32 (PcieBaseAddress + PCIE_ARUSER_REG,
+      ~AX_USER_DOMAIN_MASK,
+      AX_USER_DOMAIN_OUTER_SHAREABLE);
+
+    MmioAndThenOr32 (PcieBaseAddress + PCIE_AWUSER_REG,
+      ~AX_USER_DOMAIN_MASK,
+      AX_USER_DOMAIN_OUTER_SHAREABLE);
+
+    MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CTL_2,
+      ~TARGET_LINK_SPEED_MASK,
+      LINK_SPEED_GEN_3);
+
+    MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CAPABILITY,
+      ~TARGET_LINK_SPEED_MASK,
+      LINK_SPEED_GEN_3);
+
+    MmioOr32 (PcieBaseAddress + PCIE_GEN3_EQU_CTRL,
+      GEN3_EQU_EVAL_2MS_DISABLE);
+
+    MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET,
+      PCIE_GLOBAL_APP_LTSSM_EN);
+
+    /* Region 0: MMIO32 range */
+    ConfigureWindow (PcieBaseAddress,
+      0,
+      PcieController->PcieMmio32WinBase,
+      PcieController->PcieMmio32WinBase,
+      PcieController->PcieMmio32WinSize,
+      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
+      0);
+
+    /* Region 1: Type 0 config space */
+    ConfigureWindow (PcieBaseAddress,
+      1,
+      PcieController->ConfigSpaceAddress,
+      0x0,
+      SIZE_64KB,
+      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0,
+      IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
+
+    /* Region 2: Type 1 config space */
+    ConfigureWindow (PcieBaseAddress,
+      2,
+      PcieController->ConfigSpaceAddress + SIZE_64KB,
+      0x0,
+      PcieController->PcieBusMax * SIZE_1MB,
+      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1,
+      IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
+
+    /* Region 3: port I/O range */
+    ConfigureWindow (PcieBaseAddress,
+      3,
+      PcieController->PcieIoTranslation,
+      PcieController->PcieIoWinBase,
+      PcieController->PcieIoWinSize,
+      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO,
+      0);
+
+    /* Region 4: MMIO64 range */
+    ConfigureWindow (PcieBaseAddress,
+      4,
+      PcieController->PcieMmio64WinBase,
+      PcieController->PcieMmio64WinBase,
+      PcieController->PcieMmio64WinSize,
+      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
+      0);
+
+    MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_INT_MASK1_REG,
+      PCIE_INT_A_ASSERT_MASK |
+      PCIE_INT_B_ASSERT_MASK |
+      PCIE_INT_C_ASSERT_MASK |
+      PCIE_INT_D_ASSERT_MASK);
+
+    WaitForLink (PcieBaseAddress);
+
+    /* Enable the RC */
+    MmioOr32 (PcieBaseAddress + PCI_COMMAND_OFFSET,
+      EFI_PCI_COMMAND_IO_SPACE |
+      EFI_PCI_COMMAND_MEMORY_SPACE |
+      EFI_PCI_COMMAND_BUS_MASTER);
+  }
+
+  return EFI_SUCCESS;
+}
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 08/14] Marvell/Armada7k8k: Enable PCIE support
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (6 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-16 14:16   ` Ard Biesheuvel
  2019-05-09  9:53 ` [edk2-platforms: PATCH 09/14] Marvell/Armada80x0McBin: Enable ACPI " Marcin Wojtas
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

Wire up the platform libraries to the generic drivers so that we can use
PCI devices and UEFI, and leave the controller initialized so that the
OS can boot it using a generic driver of its own.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc | 17 +++++++++++++++--
 Silicon/Marvell/Armada7k8k/Armada7k8k.fdf     |  5 +++++
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
index 545b369..f78a76b 100644
--- a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
+++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
@@ -70,8 +70,10 @@
   IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
-  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
-  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+  PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+  PciHostBridgeLib|Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
+  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
+  PciExpressLib|Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
 
 # Basic UEFI services libraries
   UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
@@ -407,6 +409,12 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x00010000
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x00010000
 
+  # PCIE
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000
+
+  # SoC Configuration Space
+  gMarvellTokenSpaceGuid.PcdConfigSpaceBaseAddress|0xE0000000
+
 !if $(CAPSULE_ENABLE)
 [PcdsDynamicExDefault.common.DEFAULT]
   gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
@@ -520,6 +528,11 @@
   MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
   Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf
 
+  # PCI
+  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
+  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+
   # Console packages
   MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
   MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf b/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf
index 3a320ba..e22f514 100644
--- a/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf
+++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf
@@ -174,6 +174,11 @@ FvNameGuid         = 5eda4200-2c5f-43cb-9da3-0baf74b1b30c
   INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
   INF Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf
 
+  # PCI
+  INF ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
+  INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+  INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+
   # Multiple Console IO support
   INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
   INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 09/14] Marvell/Armada80x0McBin: Enable ACPI PCIE support
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (7 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 08/14] Marvell/Armada7k8k: Enable PCIE support Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-10 15:54   ` Leif Lindholm
  2019-05-16 14:23   ` Ard Biesheuvel
  2019-05-09  9:53 ` [edk2-platforms: PATCH 10/14] Marvell/Armada80x0Db: " Marcin Wojtas
                   ` (5 subsequent siblings)
  14 siblings, 2 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

This patch adds description of the PCIE controller in
ACPI tables of MacchiatoBin community board.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf       |   1 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h    |  25 +++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl  | 217 ++++++++++++++++++++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc |  47 +++++
 4 files changed, 290 insertions(+)
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc

diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf
index 9e52281..e627932 100644
--- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf
@@ -25,6 +25,7 @@
 
 [Sources]
   Armada80x0McBin/Dsdt.asl
+  Armada80x0McBin/Mcfg.aslc
   Fadt.aslc
   Gtdt.aslc
   Madt.aslc
diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
new file mode 100644
index 0000000..93631c2
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
@@ -0,0 +1,25 @@
+/**
+
+  Copyright (C) 2019, Marvell International Ltd. and its affiliates.
+
+  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.
+
+**/
+
+#define PCI_BUS_MIN        0x0
+#define PCI_BUS_MAX        0x0
+#define PCI_BUS_COUNT      0x1
+#define PCI_MMIO32_BASE    0xC0000000
+#define PCI_MMIO32_SIZE    0x20000000
+#define PCI_MMIO64_BASE    0x800000000
+#define PCI_MMIO64_SIZE    0x100000000
+#define PCI_IO_BASE        0x0
+#define PCI_IO_SIZE        0x10000
+#define PCI_IO_TRANSLATION 0xEFF00000
+#define PCI_ECAM_BASE      0xE0008000
diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl
index 87cb93a..caf5cb9 100644
--- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl
@@ -14,6 +14,7 @@
 
 **/
 
+#include "Armada80x0McBin/Pcie.h"
 #include "IcuInterrupts.h"
 
 DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
@@ -306,5 +307,221 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
                 }
             })
         }
+
+        //
+        // PCIe Root Bus
+        //
+        Device (PCI0)
+        {
+            Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
+            Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
+            Name (_SEG, 0x00)  // _SEG: PCI Segment
+            Name (_BBN, 0x00)  // _BBN: BIOS Bus Number
+            Name (_CCA, 0x01)  // _CCA: Cache Coherency Attribute
+            Name (_PRT, Package ()  // _PRT: PCI Routing Table
+            {
+                Package () { 0xFFFF, 0x0, 0x0, 0x40 },
+                Package () { 0xFFFF, 0x1, 0x0, 0x40 },
+                Package () { 0xFFFF, 0x2, 0x0, 0x40 },
+                Package () { 0xFFFF, 0x3, 0x0, 0x40 }
+            })
+
+            Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings
+            {
+                Name (RBUF, ResourceTemplate ()
+                {
+                    WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+                        0x0000,                             // Granularity
+                        PCI_BUS_MIN,                        // Range Minimum
+                        PCI_BUS_MAX,                        // Range Maximum
+                        0x0000,                             // Translation Offset
+                        PCI_BUS_COUNT                       // Length
+                        )
+                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+                        0x00000000,                         // Granularity
+                        PCI_MMIO32_BASE,                    // Range Minimum
+                        0xDFFFFFFF,                         // Range Maximum
+                        0x00000000,                         // Translation Offset
+                        PCI_MMIO32_SIZE                     // Length
+                        )
+                    QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+                        0x0000000000000000,                 // Granularity
+                        PCI_MMIO64_BASE,                    // Range Minimum
+                        0x8FFFFFFFF,                        // Range Maximum
+                        0x00000000,                         // Translation Offset
+                        PCI_MMIO64_SIZE                     // Length
+                        )
+                    DWordIo (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                        0x00000000,                         // Granularity
+                        PCI_IO_BASE,                        // Range Minimum
+                        0x0000FFFF,                         // Range Maximum
+                        PCI_IO_TRANSLATION,                 // Translation Address
+                        PCI_IO_SIZE,                        // Length
+                        ,
+                        ,
+                        ,
+                        TypeTranslation
+                        )
+                })
+                Return (RBUF) /* \_SB_.PCI0._CRS.RBUF */
+            } // Method(_CRS)
+
+            Device (RES0)
+            {
+                Name (_HID, "PNP0C02")
+                Name (_CRS, ResourceTemplate ()
+                {
+                    Memory32Fixed (ReadWrite,
+                                   PCI_ECAM_BASE,
+                                   0x10000000
+                                   )
+                })
+            }
+            Name (SUPP, 0x00)
+            Name (CTRL, 0x00)
+            Method (_OSC, 4, NotSerialized)  // _OSC: Operating System Capabilities
+            {
+                CreateDWordField (Arg3, 0x00, CDW1)
+                If (LEqual (Arg0, ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") /* PCI Host Bridge Device */))
+                {
+                    CreateDWordField (Arg3, 0x04, CDW2)
+                    CreateDWordField (Arg3, 0x08, CDW3)
+                    Store (CDW2, SUPP) /* \_SB_.PCI0.SUPP */
+                    Store (CDW3, CTRL) /* \_SB_.PCI0.CTRL */
+                    If (LNotEqual (And (SUPP, 0x16), 0x16))
+                    {
+                        And (CTRL, 0x1E, CTRL) /* \_SB_.PCI0.CTRL */
+                    }
+
+                    And (CTRL, 0x1D, CTRL) /* \_SB_.PCI0.CTRL */
+                    If (LNotEqual (Arg1, One))
+                    {
+                        Or (CDW1, 0x08, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
+                    }
+
+                    If (LNotEqual (CDW3, CTRL))
+                    {
+                        Or (CDW1, 0x10, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
+                    }
+
+                    Store (CTRL, CDW3) /* \_SB_.PCI0._OSC.CDW3 */
+                    Return (Arg3)
+                }
+                Else
+                {
+                    Or (CDW1, 0x04, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
+                    Return (Arg3)
+                }
+            } // Method(_OSC)
+
+            //
+            // Device-Specific Methods
+            //
+            Method(_DSM, 0x4, NotSerialized) {
+              If (LEqual(Arg0, ToUUID("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
+                switch (ToInteger(Arg2)) {
+                  //
+                  // Function 0: Return supported functions
+                  //
+                  case(0) {
+                    Return (Buffer() {0xFF})
+                  }
+
+                  //
+                  // Function 1: Return PCIe Slot Information
+                  //
+                  case(1) {
+                    Return (Package(2) {
+                      One, // Success
+                      Package(3) {
+                        0x1,  // x1 PCIe link
+                        0x1,  // PCI express card slot
+                        0x1   // WAKE# signal supported
+                      }
+                    })
+                  }
+
+                  //
+                  // Function 2: Return PCIe Slot Number.
+                  //
+                  case(2) {
+                    Return (Package(1) {
+                      Package(4) {
+                        2,  // Source ID
+                        4,  // Token ID: ID refers to a slot
+                        0,  // Start bit of the field to use.
+                        7   // End bit of the field to use.
+                      }
+                    })
+                  }
+
+                  //
+                  // Function 4: Return PCI Bus Capabilities
+                  //
+                  case(4) {
+                    Return (Package(2) {
+                      One, // Success
+                      Buffer() {
+                        1,0,            // Version
+                        0,0,            // Status, 0:Success
+                        24,0,0,0,       // Length
+                        1,0,            // PCI
+                        16,0,           // Length
+                        0,              // Attributes
+                        0x0D,           // Current Speed/Mode
+                        0x3F,0,         // Supported Speeds/Modes
+                        0,              // Voltage
+                        0,0,0,0,0,0,0   // Reserved
+                      }
+                    })
+                  }
+
+                  //
+                  // Function 5: Return Ignore PCI Boot Configuration
+                  //
+                  case(5) {
+                    Return (Package(1) {1})
+                  }
+
+                  //
+                  // Function 6: Return LTR Maximum Latency
+                  //
+                  case(6) {
+                    Return (Package(4) {
+                      Package(1){0},  // Maximum Snoop Latency Scale
+                      Package(1){0},  // Maximum Snoop Latency Value
+                      Package(1){0},  // Maximum No-Snoop Latency Scale
+                      Package(1){0}   // Maximum No-Snoop Latency Value
+                    })
+                  }
+
+                  //
+                  // Function 7: Return PCI Express Naming
+                  //
+                  case(7) {
+                    Return (Package(2) {
+                      Package(1) {0},
+                      Package(1) {Unicode("PCI0")}
+                    })
+                  }
+
+                  //
+                  // Not supported
+                  //
+                  default {
+                  }
+                }
+              }
+              Return (Buffer(){0})
+            } // Method(_DSM)
+
+            //
+            // Root-Complex 0
+            //
+            Device (RP0)
+            {
+                Name (_ADR, PCI_ECAM_BASE)  // _ADR: Bus 0, Dev 0, Func 0
+            }
+        }
     }
 }
diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc
new file mode 100644
index 0000000..bda5800
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc
@@ -0,0 +1,47 @@
+/** @file
+
+  Memory mapped config space base address table (MCFG)
+
+  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+  Copyright (c) 2019, Marvell International Ltd. and its affiliates.<BR>
+
+  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 <Library/AcpiLib.h>
+
+#include "AcpiHeader.h"
+#include "Armada80x0McBin/Pcie.h"
+
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+#pragma pack(1)
+typedef struct {
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE Structure;
+} ACPI_6_0_MCFG_STRUCTURE;
+#pragma pack()
+
+STATIC ACPI_6_0_MCFG_STRUCTURE Mcfg = {
+  {
+    __ACPI_HEADER (EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+                   ACPI_6_0_MCFG_STRUCTURE,
+                   EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION),
+    EFI_ACPI_RESERVED_QWORD
+  }, {
+    PCI_ECAM_BASE,                   // BaseAddress
+    0,                               // PciSegmentGroupNumber
+    PCI_BUS_MIN,                     // StartBusNumber
+    PCI_BUS_MAX,                     // EndBusNumber
+    EFI_ACPI_RESERVED_DWORD          // Reserved
+  }
+};
+
+VOID CONST * CONST ReferenceAcpiTable = &Mcfg;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 10/14] Marvell/Armada80x0Db: Enable ACPI PCIE support
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (8 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 09/14] Marvell/Armada80x0McBin: Enable ACPI " Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-16 14:25   ` [edk2-devel] " Ard Biesheuvel
  2019-05-09  9:53 ` [edk2-platforms: PATCH 11/14] Marvell/Armada70x0Db: " Marcin Wojtas
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

This patch adds description of the PCIE controller in
ACPI tables of Armada 8040 DB board.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf       |   1 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h    |  25 +++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl  | 217 ++++++++++++++++++++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc |  47 +++++
 4 files changed, 290 insertions(+)
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc

diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf
index 35a679b..9b37eb7 100644
--- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf
@@ -25,6 +25,7 @@
 
 [Sources]
   Armada80x0Db/Dsdt.asl
+  Armada80x0Db/Mcfg.aslc
   Fadt.aslc
   Gtdt.aslc
   Madt.aslc
diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h
new file mode 100644
index 0000000..93631c2
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h
@@ -0,0 +1,25 @@
+/**
+
+  Copyright (C) 2019, Marvell International Ltd. and its affiliates.
+
+  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.
+
+**/
+
+#define PCI_BUS_MIN        0x0
+#define PCI_BUS_MAX        0x0
+#define PCI_BUS_COUNT      0x1
+#define PCI_MMIO32_BASE    0xC0000000
+#define PCI_MMIO32_SIZE    0x20000000
+#define PCI_MMIO64_BASE    0x800000000
+#define PCI_MMIO64_SIZE    0x100000000
+#define PCI_IO_BASE        0x0
+#define PCI_IO_SIZE        0x10000
+#define PCI_IO_TRANSLATION 0xEFF00000
+#define PCI_ECAM_BASE      0xE0008000
diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl
index 7c65949..0f78e39 100644
--- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl
@@ -15,6 +15,7 @@
 
 **/
 
+#include "Armada80x0Db/Pcie.h"
 #include "IcuInterrupts.h"
 
 DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
@@ -326,5 +327,221 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
                 }
             })
         }
+
+        //
+        // PCIe Root Bus
+        //
+        Device (PCI0)
+        {
+            Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
+            Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
+            Name (_SEG, 0x00)  // _SEG: PCI Segment
+            Name (_BBN, 0x00)  // _BBN: BIOS Bus Number
+            Name (_CCA, 0x01)  // _CCA: Cache Coherency Attribute
+            Name (_PRT, Package ()  // _PRT: PCI Routing Table
+            {
+                Package () { 0xFFFF, 0x0, 0x0, 0x40 },
+                Package () { 0xFFFF, 0x1, 0x0, 0x40 },
+                Package () { 0xFFFF, 0x2, 0x0, 0x40 },
+                Package () { 0xFFFF, 0x3, 0x0, 0x40 }
+            })
+
+            Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings
+            {
+                Name (RBUF, ResourceTemplate ()
+                {
+                    WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+                        0x0000,                             // Granularity
+                        PCI_BUS_MIN,                        // Range Minimum
+                        PCI_BUS_MAX,                        // Range Maximum
+                        0x0000,                             // Translation Offset
+                        PCI_BUS_COUNT                       // Length
+                        )
+                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+                        0x00000000,                         // Granularity
+                        PCI_MMIO32_BASE,                    // Range Minimum
+                        0xDFFFFFFF,                         // Range Maximum
+                        0x00000000,                         // Translation Offset
+                        PCI_MMIO32_SIZE                     // Length
+                        )
+                    QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+                        0x0000000000000000,                 // Granularity
+                        PCI_MMIO64_BASE,                    // Range Minimum
+                        0x8FFFFFFFF,                        // Range Maximum
+                        0x00000000,                         // Translation Offset
+                        PCI_MMIO64_SIZE                     // Length
+                        )
+                    DWordIo (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                        0x00000000,                         // Granularity
+                        PCI_IO_BASE,                        // Range Minimum
+                        0x0000FFFF,                         // Range Maximum
+                        PCI_IO_TRANSLATION,                 // Translation Address
+                        PCI_IO_SIZE,                        // Length
+                        ,
+                        ,
+                        ,
+                        TypeTranslation
+                        )
+                })
+                Return (RBUF) /* \_SB_.PCI0._CRS.RBUF */
+            } // Method(_CRS)
+
+            Device (RES0)
+            {
+                Name (_HID, "PNP0C02")
+                Name (_CRS, ResourceTemplate ()
+                {
+                    Memory32Fixed (ReadWrite,
+                                   PCI_ECAM_BASE,
+                                   0x10000000
+                                   )
+                })
+            }
+            Name (SUPP, 0x00)
+            Name (CTRL, 0x00)
+            Method (_OSC, 4, NotSerialized)  // _OSC: Operating System Capabilities
+            {
+                CreateDWordField (Arg3, 0x00, CDW1)
+                If (LEqual (Arg0, ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") /* PCI Host Bridge Device */))
+                {
+                    CreateDWordField (Arg3, 0x04, CDW2)
+                    CreateDWordField (Arg3, 0x08, CDW3)
+                    Store (CDW2, SUPP) /* \_SB_.PCI0.SUPP */
+                    Store (CDW3, CTRL) /* \_SB_.PCI0.CTRL */
+                    If (LNotEqual (And (SUPP, 0x16), 0x16))
+                    {
+                        And (CTRL, 0x1E, CTRL) /* \_SB_.PCI0.CTRL */
+                    }
+
+                    And (CTRL, 0x1D, CTRL) /* \_SB_.PCI0.CTRL */
+                    If (LNotEqual (Arg1, One))
+                    {
+                        Or (CDW1, 0x08, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
+                    }
+
+                    If (LNotEqual (CDW3, CTRL))
+                    {
+                        Or (CDW1, 0x10, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
+                    }
+
+                    Store (CTRL, CDW3) /* \_SB_.PCI0._OSC.CDW3 */
+                    Return (Arg3)
+                }
+                Else
+                {
+                    Or (CDW1, 0x04, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
+                    Return (Arg3)
+                }
+            } // Method(_OSC)
+
+            //
+            // Device-Specific Methods
+            //
+            Method(_DSM, 0x4, NotSerialized) {
+              If (LEqual(Arg0, ToUUID("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
+                switch (ToInteger(Arg2)) {
+                  //
+                  // Function 0: Return supported functions
+                  //
+                  case(0) {
+                    Return (Buffer() {0xFF})
+                  }
+
+                  //
+                  // Function 1: Return PCIe Slot Information
+                  //
+                  case(1) {
+                    Return (Package(2) {
+                      One, // Success
+                      Package(3) {
+                        0x1,  // x1 PCIe link
+                        0x1,  // PCI express card slot
+                        0x1   // WAKE# signal supported
+                      }
+                    })
+                  }
+
+                  //
+                  // Function 2: Return PCIe Slot Number.
+                  //
+                  case(2) {
+                    Return (Package(1) {
+                      Package(4) {
+                        2,  // Source ID
+                        4,  // Token ID: ID refers to a slot
+                        0,  // Start bit of the field to use.
+                        7   // End bit of the field to use.
+                      }
+                    })
+                  }
+
+                  //
+                  // Function 4: Return PCI Bus Capabilities
+                  //
+                  case(4) {
+                    Return (Package(2) {
+                      One, // Success
+                      Buffer() {
+                        1,0,            // Version
+                        0,0,            // Status, 0:Success
+                        24,0,0,0,       // Length
+                        1,0,            // PCI
+                        16,0,           // Length
+                        0,              // Attributes
+                        0x0D,           // Current Speed/Mode
+                        0x3F,0,         // Supported Speeds/Modes
+                        0,              // Voltage
+                        0,0,0,0,0,0,0   // Reserved
+                      }
+                    })
+                  }
+
+                  //
+                  // Function 5: Return Ignore PCI Boot Configuration
+                  //
+                  case(5) {
+                    Return (Package(1) {1})
+                  }
+
+                  //
+                  // Function 6: Return LTR Maximum Latency
+                  //
+                  case(6) {
+                    Return (Package(4) {
+                      Package(1){0},  // Maximum Snoop Latency Scale
+                      Package(1){0},  // Maximum Snoop Latency Value
+                      Package(1){0},  // Maximum No-Snoop Latency Scale
+                      Package(1){0}   // Maximum No-Snoop Latency Value
+                    })
+                  }
+
+                  //
+                  // Function 7: Return PCI Express Naming
+                  //
+                  case(7) {
+                    Return (Package(2) {
+                      Package(1) {0},
+                      Package(1) {Unicode("PCI0")}
+                    })
+                  }
+
+                  //
+                  // Not supported
+                  //
+                  default {
+                  }
+                }
+              }
+              Return (Buffer(){0})
+            } // Method(_DSM)
+
+            //
+            // Root-Complex 0
+            //
+            Device (RP0)
+            {
+                Name (_ADR, PCI_ECAM_BASE)  // _ADR: Bus 0, Dev 0, Func 0
+            }
+        }
     }
 }
diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc
new file mode 100644
index 0000000..da152b7
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc
@@ -0,0 +1,47 @@
+/** @file
+
+  Memory mapped config space base address table (MCFG)
+
+  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+  Copyright (c) 2019, Marvell International Ltd. and its affiliates.<BR>
+
+  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 <Library/AcpiLib.h>
+
+#include "AcpiHeader.h"
+#include "Armada80x0Db/Pcie.h"
+
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+#pragma pack(1)
+typedef struct {
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE Structure;
+} ACPI_6_0_MCFG_STRUCTURE;
+#pragma pack()
+
+STATIC ACPI_6_0_MCFG_STRUCTURE Mcfg = {
+  {
+    __ACPI_HEADER (EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+                   ACPI_6_0_MCFG_STRUCTURE,
+                   EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION),
+    EFI_ACPI_RESERVED_QWORD
+  }, {
+    PCI_ECAM_BASE,                   // BaseAddress
+    0,                               // PciSegmentGroupNumber
+    PCI_BUS_MIN,                     // StartBusNumber
+    PCI_BUS_MAX,                     // EndBusNumber
+    EFI_ACPI_RESERVED_DWORD          // Reserved
+  }
+};
+
+VOID CONST * CONST ReferenceAcpiTable = &Mcfg;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 11/14] Marvell/Armada70x0Db: Enable ACPI PCIE support
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (9 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 10/14] Marvell/Armada80x0Db: " Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-16 14:26   ` [edk2-devel] " Ard Biesheuvel
  2019-05-09  9:53 ` [edk2-platforms: PATCH 12/14] Marvell/Armada80x0McBin: DeviceTree: Use pci-host-generic driver Marcin Wojtas
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

This patch adds description of the PCIE controller in
ACPI tables of Armada 7040 DB board.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf       |   1 +
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h    |  25 +++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl  | 217 ++++++++++++++++++++
 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc |  47 +++++
 4 files changed, 290 insertions(+)
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h
 create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc

diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf
index 659c333..96bcdf0 100644
--- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf
@@ -25,6 +25,7 @@
 
 [Sources]
   Armada70x0Db/Dsdt.asl
+  Armada70x0Db/Mcfg.aslc
   Fadt.aslc
   Gtdt.aslc
   Madt.aslc
diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h
new file mode 100644
index 0000000..93631c2
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h
@@ -0,0 +1,25 @@
+/**
+
+  Copyright (C) 2019, Marvell International Ltd. and its affiliates.
+
+  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.
+
+**/
+
+#define PCI_BUS_MIN        0x0
+#define PCI_BUS_MAX        0x0
+#define PCI_BUS_COUNT      0x1
+#define PCI_MMIO32_BASE    0xC0000000
+#define PCI_MMIO32_SIZE    0x20000000
+#define PCI_MMIO64_BASE    0x800000000
+#define PCI_MMIO64_SIZE    0x100000000
+#define PCI_IO_BASE        0x0
+#define PCI_IO_SIZE        0x10000
+#define PCI_IO_TRANSLATION 0xEFF00000
+#define PCI_ECAM_BASE      0xE0008000
diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl
index 621b688..a23bd70 100644
--- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl
@@ -15,6 +15,7 @@
 
 **/
 
+#include "Armada70x0Db/Pcie.h"
 #include "IcuInterrupts.h"
 
 DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA7K", 3)
@@ -225,5 +226,221 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA7K", 3)
                 }
             })
         }
+
+        //
+        // PCIe Root Bus
+        //
+        Device (PCI0)
+        {
+            Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
+            Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
+            Name (_SEG, 0x00)  // _SEG: PCI Segment
+            Name (_BBN, 0x00)  // _BBN: BIOS Bus Number
+            Name (_CCA, 0x01)  // _CCA: Cache Coherency Attribute
+            Name (_PRT, Package ()  // _PRT: PCI Routing Table
+            {
+                Package () { 0xFFFF, 0x0, 0x0, 0x40 },
+                Package () { 0xFFFF, 0x1, 0x0, 0x40 },
+                Package () { 0xFFFF, 0x2, 0x0, 0x40 },
+                Package () { 0xFFFF, 0x3, 0x0, 0x40 }
+            })
+
+            Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings
+            {
+                Name (RBUF, ResourceTemplate ()
+                {
+                    WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+                        0x0000,                             // Granularity
+                        PCI_BUS_MIN,                        // Range Minimum
+                        PCI_BUS_MAX,                        // Range Maximum
+                        0x0000,                             // Translation Offset
+                        PCI_BUS_COUNT                       // Length
+                        )
+                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+                        0x00000000,                         // Granularity
+                        PCI_MMIO32_BASE,                    // Range Minimum
+                        0xDFFFFFFF,                         // Range Maximum
+                        0x00000000,                         // Translation Offset
+                        PCI_MMIO32_SIZE                     // Length
+                        )
+                    QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+                        0x0000000000000000,                 // Granularity
+                        PCI_MMIO64_BASE,                    // Range Minimum
+                        0x8FFFFFFFF,                        // Range Maximum
+                        0x00000000,                         // Translation Offset
+                        PCI_MMIO64_SIZE                     // Length
+                        )
+                    DWordIo (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                        0x00000000,                         // Granularity
+                        PCI_IO_BASE,                        // Range Minimum
+                        0x0000FFFF,                         // Range Maximum
+                        PCI_IO_TRANSLATION,                 // Translation Address
+                        PCI_IO_SIZE,                        // Length
+                        ,
+                        ,
+                        ,
+                        TypeTranslation
+                        )
+                })
+                Return (RBUF) /* \_SB_.PCI0._CRS.RBUF */
+            } // Method(_CRS)
+
+            Device (RES0)
+            {
+                Name (_HID, "PNP0C02")
+                Name (_CRS, ResourceTemplate ()
+                {
+                    Memory32Fixed (ReadWrite,
+                                   PCI_ECAM_BASE,
+                                   0x10000000
+                                   )
+                })
+            }
+            Name (SUPP, 0x00)
+            Name (CTRL, 0x00)
+            Method (_OSC, 4, NotSerialized)  // _OSC: Operating System Capabilities
+            {
+                CreateDWordField (Arg3, 0x00, CDW1)
+                If (LEqual (Arg0, ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") /* PCI Host Bridge Device */))
+                {
+                    CreateDWordField (Arg3, 0x04, CDW2)
+                    CreateDWordField (Arg3, 0x08, CDW3)
+                    Store (CDW2, SUPP) /* \_SB_.PCI0.SUPP */
+                    Store (CDW3, CTRL) /* \_SB_.PCI0.CTRL */
+                    If (LNotEqual (And (SUPP, 0x16), 0x16))
+                    {
+                        And (CTRL, 0x1E, CTRL) /* \_SB_.PCI0.CTRL */
+                    }
+
+                    And (CTRL, 0x1D, CTRL) /* \_SB_.PCI0.CTRL */
+                    If (LNotEqual (Arg1, One))
+                    {
+                        Or (CDW1, 0x08, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
+                    }
+
+                    If (LNotEqual (CDW3, CTRL))
+                    {
+                        Or (CDW1, 0x10, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
+                    }
+
+                    Store (CTRL, CDW3) /* \_SB_.PCI0._OSC.CDW3 */
+                    Return (Arg3)
+                }
+                Else
+                {
+                    Or (CDW1, 0x04, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
+                    Return (Arg3)
+                }
+            } // Method(_OSC)
+
+            //
+            // Device-Specific Methods
+            //
+            Method(_DSM, 0x4, NotSerialized) {
+              If (LEqual(Arg0, ToUUID("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
+                switch (ToInteger(Arg2)) {
+                  //
+                  // Function 0: Return supported functions
+                  //
+                  case(0) {
+                    Return (Buffer() {0xFF})
+                  }
+
+                  //
+                  // Function 1: Return PCIe Slot Information
+                  //
+                  case(1) {
+                    Return (Package(2) {
+                      One, // Success
+                      Package(3) {
+                        0x1,  // x1 PCIe link
+                        0x1,  // PCI express card slot
+                        0x1   // WAKE# signal supported
+                      }
+                    })
+                  }
+
+                  //
+                  // Function 2: Return PCIe Slot Number.
+                  //
+                  case(2) {
+                    Return (Package(1) {
+                      Package(4) {
+                        2,  // Source ID
+                        4,  // Token ID: ID refers to a slot
+                        0,  // Start bit of the field to use.
+                        7   // End bit of the field to use.
+                      }
+                    })
+                  }
+
+                  //
+                  // Function 4: Return PCI Bus Capabilities
+                  //
+                  case(4) {
+                    Return (Package(2) {
+                      One, // Success
+                      Buffer() {
+                        1,0,            // Version
+                        0,0,            // Status, 0:Success
+                        24,0,0,0,       // Length
+                        1,0,            // PCI
+                        16,0,           // Length
+                        0,              // Attributes
+                        0x0D,           // Current Speed/Mode
+                        0x3F,0,         // Supported Speeds/Modes
+                        0,              // Voltage
+                        0,0,0,0,0,0,0   // Reserved
+                      }
+                    })
+                  }
+
+                  //
+                  // Function 5: Return Ignore PCI Boot Configuration
+                  //
+                  case(5) {
+                    Return (Package(1) {1})
+                  }
+
+                  //
+                  // Function 6: Return LTR Maximum Latency
+                  //
+                  case(6) {
+                    Return (Package(4) {
+                      Package(1){0},  // Maximum Snoop Latency Scale
+                      Package(1){0},  // Maximum Snoop Latency Value
+                      Package(1){0},  // Maximum No-Snoop Latency Scale
+                      Package(1){0}   // Maximum No-Snoop Latency Value
+                    })
+                  }
+
+                  //
+                  // Function 7: Return PCI Express Naming
+                  //
+                  case(7) {
+                    Return (Package(2) {
+                      Package(1) {0},
+                      Package(1) {Unicode("PCI0")}
+                    })
+                  }
+
+                  //
+                  // Not supported
+                  //
+                  default {
+                  }
+                }
+              }
+              Return (Buffer(){0})
+            } // Method(_DSM)
+
+            //
+            // Root-Complex 0
+            //
+            Device (RP0)
+            {
+                Name (_ADR, PCI_ECAM_BASE)  // _ADR: Bus 0, Dev 0, Func 0
+            }
+        }
     }
 }
diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc
new file mode 100644
index 0000000..90bf163
--- /dev/null
+++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc
@@ -0,0 +1,47 @@
+/** @file
+
+  Memory mapped config space base address table (MCFG)
+
+  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+  Copyright (c) 2019, Marvell International Ltd. and its affiliates.<BR>
+
+  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 <Library/AcpiLib.h>
+
+#include "AcpiHeader.h"
+#include "Armada70x0Db/Pcie.h"
+
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+#pragma pack(1)
+typedef struct {
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE Structure;
+} ACPI_6_0_MCFG_STRUCTURE;
+#pragma pack()
+
+STATIC ACPI_6_0_MCFG_STRUCTURE Mcfg = {
+  {
+    __ACPI_HEADER (EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+                   ACPI_6_0_MCFG_STRUCTURE,
+                   EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION),
+    EFI_ACPI_RESERVED_QWORD
+  }, {
+    PCI_ECAM_BASE,                   // BaseAddress
+    0,                               // PciSegmentGroupNumber
+    PCI_BUS_MIN,                     // StartBusNumber
+    PCI_BUS_MAX,                     // EndBusNumber
+    EFI_ACPI_RESERVED_DWORD          // Reserved
+  }
+};
+
+VOID CONST * CONST ReferenceAcpiTable = &Mcfg;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 12/14] Marvell/Armada80x0McBin: DeviceTree: Use pci-host-generic driver
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (10 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 11/14] Marvell/Armada70x0Db: " Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-09  9:53 ` [edk2-platforms: PATCH 13/14] Marvell/Armada7k8k: Remove duplication in .dsc files Marcin Wojtas
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

Now as the OS clock configuration is inherited from the firmware,
and PCIE is also configured, switch safely MacchiatoBin board to
use the pci-host-generic driver.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Armada7k8k/DeviceTree/armada-8040-mcbin.dts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Silicon/Marvell/Armada7k8k/DeviceTree/armada-8040-mcbin.dts b/Silicon/Marvell/Armada7k8k/DeviceTree/armada-8040-mcbin.dts
index b86e27e..d9c9348 100644
--- a/Silicon/Marvell/Armada7k8k/DeviceTree/armada-8040-mcbin.dts
+++ b/Silicon/Marvell/Armada7k8k/DeviceTree/armada-8040-mcbin.dts
@@ -180,6 +180,9 @@
 };
 
 &cp0_pcie0 {
+        compatible = "marvell,armada8k-pcie-ecam", "snps,dw-pcie-ecam";
+        reg = <0 0xe0000000 0 0xff00000>;
+        bus-range = <0 0xfe>;
         pinctrl-names = "default";
         pinctrl-0 = <&cp0_pcie_pins>;
         num-lanes = <4>;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 13/14] Marvell/Armada7k8k: Remove duplication in .dsc files
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (11 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 12/14] Marvell/Armada80x0McBin: DeviceTree: Use pci-host-generic driver Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-09  9:53 ` [edk2-platforms: PATCH 14/14] Marvell/Armada7k8: Add 'acpiview' shell command to build Marcin Wojtas
  2019-05-10 15:58 ` [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Leif Lindholm
  14 siblings, 0 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

Mistakenly in all Marvell Armada7k8k .dsc files
'[LibraryClasses.common]' section was split.
Merge entries into one for each platform.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Platform/Marvell/Armada70x0Db/Armada70x0Db.dsc        | 4 +---
 Platform/Marvell/Armada80x0Db/Armada80x0Db.dsc        | 4 +---
 Platform/SolidRun/Armada80x0McBin/Armada80x0McBin.dsc | 4 +---
 3 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/Platform/Marvell/Armada70x0Db/Armada70x0Db.dsc b/Platform/Marvell/Armada70x0Db/Armada70x0Db.dsc
index 01532b4..9ceb872 100644
--- a/Platform/Marvell/Armada70x0Db/Armada70x0Db.dsc
+++ b/Platform/Marvell/Armada70x0Db/Armada70x0Db.dsc
@@ -48,9 +48,6 @@
 
 !include Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
 
-[LibraryClasses.common]
-  NonDiscoverableInitLib|Platform/Marvell/Armada70x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.inf
-
 [Components.common]
   Silicon/Marvell/Armada7k8k/DeviceTree/Armada70x0Db.inf
 
@@ -59,6 +56,7 @@
 
 [LibraryClasses.common]
   ArmadaBoardDescLib|Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.inf
+  NonDiscoverableInitLib|Platform/Marvell/Armada70x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.inf
 
 ################################################################################
 #
diff --git a/Platform/Marvell/Armada80x0Db/Armada80x0Db.dsc b/Platform/Marvell/Armada80x0Db/Armada80x0Db.dsc
index c6510bb..6487321 100644
--- a/Platform/Marvell/Armada80x0Db/Armada80x0Db.dsc
+++ b/Platform/Marvell/Armada80x0Db/Armada80x0Db.dsc
@@ -48,9 +48,6 @@
 
 !include Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
 
-[LibraryClasses.common]
-  NonDiscoverableInitLib|Platform/Marvell/Armada80x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.inf
-
 [Components.common]
   Silicon/Marvell/Armada7k8k/DeviceTree/Armada80x0Db.inf
 
@@ -59,6 +56,7 @@
 
 [LibraryClasses.common]
   ArmadaBoardDescLib|Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.inf
+  NonDiscoverableInitLib|Platform/Marvell/Armada80x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.inf
 
 ################################################################################
 #
diff --git a/Platform/SolidRun/Armada80x0McBin/Armada80x0McBin.dsc b/Platform/SolidRun/Armada80x0McBin/Armada80x0McBin.dsc
index d080136..cb41f4e 100644
--- a/Platform/SolidRun/Armada80x0McBin/Armada80x0McBin.dsc
+++ b/Platform/SolidRun/Armada80x0McBin/Armada80x0McBin.dsc
@@ -49,9 +49,6 @@
 
 !include Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
 
-[LibraryClasses.common]
-  NonDiscoverableInitLib|Platform/SolidRun/Armada80x0McBin/NonDiscoverableInitLib/NonDiscoverableInitLib.inf
-
 [Components.common]
   Silicon/Marvell/Armada7k8k/DeviceTree/Armada80x0McBin.inf
 
@@ -60,6 +57,7 @@
 
 [LibraryClasses.common]
   ArmadaBoardDescLib|Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.inf
+  NonDiscoverableInitLib|Platform/SolidRun/Armada80x0McBin/NonDiscoverableInitLib/NonDiscoverableInitLib.inf
 
 ################################################################################
 #
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-platforms: PATCH 14/14] Marvell/Armada7k8: Add 'acpiview' shell command to build
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (12 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 13/14] Marvell/Armada7k8k: Remove duplication in .dsc files Marcin Wojtas
@ 2019-05-09  9:53 ` Marcin Wojtas
  2019-05-10 15:58 ` [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Leif Lindholm
  14 siblings, 0 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09  9:53 UTC (permalink / raw)
  To: devel
  Cc: leif.lindholm, ard.biesheuvel, mw, jsd, jaz, kostap, Jici.Gao,
	rebecca, kettenis

To help diagnose ACPI related boot problems, include the 'acpiview'
builtin shell command to Armada7k8k build of the UEFI Shell.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
index f78a76b..af58ce9 100644
--- a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
+++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
@@ -592,6 +592,7 @@
   ShellPkg/Application/Shell/Shell.inf {
     <LibraryClasses>
       ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+      NULL|ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
       NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
       NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
       NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 04/14] Marvell/Armada7k8k: Extend board description libraries with PCIE
  2019-05-09  9:53 ` [edk2-platforms: PATCH 04/14] Marvell/Armada7k8k: Extend board description libraries with PCIE Marcin Wojtas
@ 2019-05-09 10:16   ` Marcin Wojtas
  0 siblings, 0 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-09 10:16 UTC (permalink / raw)
  To: edk2-devel-groups-io
  Cc: Leif Lindholm, Ard Biesheuvel, jsd@semihalf.com,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	Mark Kettenis

czw., 9 maj 2019 o 11:53 Marcin Wojtas <mw@semihalf.com> napisał(a):
>
> This patch extends ArmadaBoardDescLib libraries for all
> existing Armada7k8k-based platforms with PCIE.
> It introduces ArmadaBoardPcieControllerGet routine with
> per-board PCIE controllers description.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c           | 48 ++++++++++++++++++++
>  Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c           | 48 ++++++++++++++++++++
>  Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c | 48 ++++++++++++++++++++
>  3 files changed, 144 insertions(+)
>
> diff --git a/Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c b/Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c
> index f0133ec..cbd23cc 100644
> --- a/Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c
> +++ b/Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c
> @@ -46,6 +46,54 @@ ArmadaBoardGpioExpanderGet (
>  }
>
>  //
> +// PCIE
> +//
> +STATIC
> +MV_PCIE_CONTROLLER mPcieController[] = {
> +  { /* PCIE2 @0xF2640000 */
> +    .PcieBaseAddress       = 0xF2640000,
> +    .ConfigSpaceAddress    = 0xE0000000,
> +    .HaveResetGpio         = FALSE,
> +    .PcieResetGpio         = { 0 },
> +    .PcieBusMin            = 0,
> +    .PcieBusMax            = 0xFE,
> +    .PcieIoTranslation     = 0xEFF00000,
> +    .PcieIoWinBase         = 0x0,
> +    .PcieIoWinSize         = 0x10000,
> +    .PcieMmio32Translation = 0,
> +    .PcieMmio32WinBase     = 0xC0000000,
> +    .PcieMmio32WinSize     = 0x20000000,
> +    .PcieMmio64Translation = 0,
> +    .PcieMmio64WinBase     = 0x800000000,
> +    .PcieMmio64WinSize     = 0x100000000,
> +  }
> +};
> +
> +/**
> +  Return the number and description of PCIE controllers used on the platform.
> +
> +  @param[in out] **PcieControllers      Array containing PCIE controllers'
> +                                        description.
> +  @param[in out]  *PcieControllerCount  Amount of used PCIE controllers.
> +
> +  @retval EFI_SUCCESS                   The data were obtained successfully.
> +  @retval other                         Return error status.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArmadaBoardPcieControllerGet (
> +  IN OUT MV_PCIE_CONTROLLER **PcieControllers,
> +  IN OUT UINTN               *PcieControllerCount
> +  )
> +{
> +  *PcieControllers = mPcieController;
> +  *PcieControllerCount = ARRAY_SIZE (mPcieController);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +//
>  // Order of devices in SdMmcDescTemplate has to be in par with ArmadaSoCDescLib
>  //
>  STATIC
> diff --git a/Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c b/Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c
> index 61b6202..5781756 100644
> --- a/Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c
> +++ b/Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c
> @@ -52,6 +52,54 @@ ArmadaBoardGpioExpanderGet (
>  }
>
>  //
> +// PCIE
> +//
> +STATIC
> +MV_PCIE_CONTROLLER mPcieController[] = {
> +  { /* PCIE0 @0xF2600000 */
> +    .PcieBaseAddress       = 0xF2600000,
> +    .ConfigSpaceAddress    = 0xE0000000,
> +    .HaveResetGpio         = FALSE,
> +    .PcieResetGpio         = { 0 },
> +    .PcieBusMin            = 0,
> +    .PcieBusMax            = 0xFE,
> +    .PcieIoTranslation     = 0xEFF00000,
> +    .PcieIoWinBase         = 0x0,
> +    .PcieIoWinSize         = 0x10000,
> +    .PcieMmio32Translation = 0,
> +    .PcieMmio32WinBase     = 0xC0000000,
> +    .PcieMmio32WinSize     = 0x20000000,
> +    .PcieMmio64Translation = 0,
> +    .PcieMmio64WinBase     = 0x800000000,
> +    .PcieMmio64WinSize     = 0x100000000,
> +  }
> +};
> +
> +/**
> +  Return the number and description of PCIE controllers used on the platform.
> +
> +  @param[in out] **PcieControllers      Array containing PCIE controllers'
> +                                        description.
> +  @param[in out]  *PcieControllerCount  Amount of used PCIE controllers.
> +
> +  @retval EFI_SUCCESS                   The data were obtained successfully.
> +  @retval other                         Return error status.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArmadaBoardPcieControllerGet (
> +  IN OUT MV_PCIE_CONTROLLER **PcieControllers,
> +  IN OUT UINTN               *PcieControllerCount
> +  )
> +{
> +  *PcieControllers = mPcieController;
> +  *PcieControllerCount = ARRAY_SIZE (mPcieController);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +//
>  // Order of devices in SdMmcDescTemplate has to be in par with ArmadaSoCDescLib
>  //
>  STATIC
> diff --git a/Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c b/Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c
> index 32596ad..11a889b 100644
> --- a/Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c
> +++ b/Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c
> @@ -39,6 +39,54 @@ ArmadaBoardGpioExpanderGet (
>  }
>
>  //
> +// PCIE
> +//
> +STATIC
> +MV_PCIE_CONTROLLER mPcieController[] = {
> +  { /* PCIE0 @0xF2600000 */
> +    .PcieBaseAddress       = 0xF2600000,
> +    .ConfigSpaceAddress    = 0xE0000000,
> +    .HaveResetGpio         = FALSE,
> +    .PcieResetGpio         = { 0 },

Just after pushing the patches I noticed my mistake. The reset GPIO on
MacchiatoBin must be set and above fields should look like this:

-    .HaveResetGpio         = FALSE,
-    .PcieResetGpio         = { 0 },
+    .HaveResetGpio         = TRUE,
+    .PcieResetGpio         =
+     {
+       MV_GPIO_DRIVER_TYPE_SOC_CONTROLLER,
+       MV_GPIO_CP0_CONTROLLER1,
+       20,
+       FALSE
+     },

This will be sent in v2, however the binary pointed in the cover
letter is updated and performs the reset properly.

Best regards,
Marcin

> +    .PcieBusMin            = 0,
> +    .PcieBusMax            = 0xFE,
> +    .PcieIoTranslation     = 0xEFF00000,
> +    .PcieIoWinBase         = 0x0,
> +    .PcieIoWinSize         = 0x10000,
> +    .PcieMmio32Translation = 0,
> +    .PcieMmio32WinBase     = 0xC0000000,
> +    .PcieMmio32WinSize     = 0x20000000,
> +    .PcieMmio64Translation = 0,
> +    .PcieMmio64WinBase     = 0x800000000,
> +    .PcieMmio64WinSize     = 0x100000000,
> +  }
> +};
> +
> +/**
> +  Return the number and description of PCIE controllers used on the platform.
> +
> +  @param[in out] **PcieControllers      Array containing PCIE controllers'
> +                                        description.
> +  @param[in out]  *PcieControllerCount  Amount of used PCIE controllers.
> +
> +  @retval EFI_SUCCESS                   The data were obtained successfully.
> +  @retval other                         Return error status.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArmadaBoardPcieControllerGet (
> +  IN OUT MV_PCIE_CONTROLLER **PcieControllers,
> +  IN OUT UINTN               *PcieControllerCount
> +  )
> +{
> +  *PcieControllers = mPcieController;
> +  *PcieControllerCount = ARRAY_SIZE (mPcieController);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +//
>  // Order of devices in SdMmcDescTemplate has to be in par with ArmadaSoCDescLib
>  //
>  STATIC
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 02/14] Marvell/Library: ArmadaSoCDescLib: Add PCIE information
  2019-05-09  9:53 ` [edk2-platforms: PATCH 02/14] Marvell/Library: ArmadaSoCDescLib: Add PCIE information Marcin Wojtas
@ 2019-05-10 14:59   ` Leif Lindholm
  2019-05-10 15:03     ` Marcin Wojtas
  0 siblings, 1 reply; 36+ messages in thread
From: Leif Lindholm @ 2019-05-10 14:59 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: devel, ard.biesheuvel, jsd, jaz, kostap, Jici.Gao, rebecca,
	kettenis

On Thu, May 09, 2019 at 11:53:30AM +0200, Marcin Wojtas wrote:
> This patch introduces new library callback (ArmadaSoCPcieGet ()),
> which dynamically allocates and fills array with all available PCIE
> controllers' base addresses. It is needed for the configuration of PCIE,
> whose support will be added in the upcoming patches.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h |  6 +++
>  Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h                             | 20 +++++++++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c | 44 ++++++++++++++++++++
>  3 files changed, 70 insertions(+)
> 
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h
> index 8bbc5b0..e904222 100644
> --- a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h
> @@ -82,6 +82,12 @@
>  #define MV_SOC_MDIO_ID(Cp)               (Cp)
>  
>  //
> +// Platform description of PCIE
> +//
> +#define MV_SOC_PCIE_PER_CP_COUNT         3
> +#define MV_SOC_PCIE_BASE(Index)          (0x600000 + ((Index) * 0x20000))
> +
> +//
>  // Platform description of PP2 NIC
>  //
>  #define MV_SOC_PP2_BASE(Cp)              MV_SOC_CP_BASE (Cp)
> diff --git a/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h b/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h
> index fc17c3a..ff617e6 100644
> --- a/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h
> +++ b/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h
> @@ -191,6 +191,26 @@ ArmadaSoCDescXhciGet (
>    IN OUT UINTN              *DescCount
>    );
>  
> +/**
> +  This function returns the total number of PCIE controllers and an array
> +  with their base addresses.
> +
> +  @param[in out] **PcieBaseAddresses  Array containing PCIE controllers' base

Extra space before "Array" messes up alignment.
Either drop that or add one to the lines below.

/
    Leif

> +                                     adresses.
> +  @param[in out]  *Count             Total amount of available PCIE controllers.
> +
> +  @retval EFI_SUCCESS                The data were obtained successfully.
> +  @retval EFI_OUT_OF_RESOURCES       The request could not be completed due to a
> +                                     lack of resources.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArmadaSoCPcieGet (
> +  IN OUT EFI_PHYSICAL_ADDRESS  **PcieBaseAddresses,
> +  IN OUT UINTN                  *Count
> +  );
> +
>  //
>  // PP2 NIC devices SoC description
>  //
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c
> index 355be64..4f8a59a 100644
> --- a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c
> @@ -278,6 +278,50 @@ ArmadaSoCDescAhciGet (
>    return EFI_SUCCESS;
>  }
>  
> +/**
> +  This function returns the total number of PCIE controllers and an array
> +  with their base addresses.
> +
> +  @param[in out] **PcieBaseAddresses Array containing PCIE controllers' base
> +                                     adresses.
> +  @param[in out]  *Count             Total amount of available PCIE controllers.
> +
> +  @retval EFI_SUCCESS                The data were obtained successfully.
> +  @retval EFI_OUT_OF_RESOURCES       The request could not be completed due to a
> +                                     lack of resources.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArmadaSoCPcieGet (
> +  IN OUT EFI_PHYSICAL_ADDRESS  **PcieBaseAddresses,
> +  IN OUT UINTN                  *Count
> +  )
> +{
> +  UINTN CpCount, CpIndex, Index;
> +  EFI_PHYSICAL_ADDRESS *BaseAddress;
> +
> +  CpCount = FixedPcdGet8 (PcdMaxCpCount);
> +
> +  *Count = CpCount * MV_SOC_PCIE_PER_CP_COUNT;
> +  BaseAddress = AllocateZeroPool (*Count * sizeof (EFI_PHYSICAL_ADDRESS));
> +  if (BaseAddress == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  *PcieBaseAddresses = BaseAddress;
> +
> +  for (CpIndex = 0; CpIndex < CpCount; CpIndex++) {
> +    for (Index = 0; Index < MV_SOC_PCIE_PER_CP_COUNT; Index++) {
> +      *BaseAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_PCIE_BASE (Index);
> +      BaseAddress++;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
>  EFI_STATUS
>  EFIAPI
>  ArmadaSoCDescPp2Get (
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 02/14] Marvell/Library: ArmadaSoCDescLib: Add PCIE information
  2019-05-10 14:59   ` Leif Lindholm
@ 2019-05-10 15:03     ` Marcin Wojtas
  0 siblings, 0 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-10 15:03 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: edk2-devel-groups-io, Ard Biesheuvel, jsd@semihalf.com,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	Mark Kettenis

pt., 10 maj 2019 o 16:59 Leif Lindholm <leif.lindholm@linaro.org> napisał(a):
>
> On Thu, May 09, 2019 at 11:53:30AM +0200, Marcin Wojtas wrote:
> > This patch introduces new library callback (ArmadaSoCPcieGet ()),
> > which dynamically allocates and fills array with all available PCIE
> > controllers' base addresses. It is needed for the configuration of PCIE,
> > whose support will be added in the upcoming patches.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> > ---
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h |  6 +++
> >  Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h                             | 20 +++++++++
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c | 44 ++++++++++++++++++++
> >  3 files changed, 70 insertions(+)
> >
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h
> > index 8bbc5b0..e904222 100644
> > --- a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h
> > @@ -82,6 +82,12 @@
> >  #define MV_SOC_MDIO_ID(Cp)               (Cp)
> >
> >  //
> > +// Platform description of PCIE
> > +//
> > +#define MV_SOC_PCIE_PER_CP_COUNT         3
> > +#define MV_SOC_PCIE_BASE(Index)          (0x600000 + ((Index) * 0x20000))
> > +
> > +//
> >  // Platform description of PP2 NIC
> >  //
> >  #define MV_SOC_PP2_BASE(Cp)              MV_SOC_CP_BASE (Cp)
> > diff --git a/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h b/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h
> > index fc17c3a..ff617e6 100644
> > --- a/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h
> > +++ b/Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h
> > @@ -191,6 +191,26 @@ ArmadaSoCDescXhciGet (
> >    IN OUT UINTN              *DescCount
> >    );
> >
> > +/**
> > +  This function returns the total number of PCIE controllers and an array
> > +  with their base addresses.
> > +
> > +  @param[in out] **PcieBaseAddresses  Array containing PCIE controllers' base
>
> Extra space before "Array" messes up alignment.
> Either drop that or add one to the lines below.
>

That's an effect of :%s typo fixing... Will correct in v2.

Thanks,
Marcin

>
> > +                                     adresses.
> > +  @param[in out]  *Count             Total amount of available PCIE controllers.
> > +
> > +  @retval EFI_SUCCESS                The data were obtained successfully.
> > +  @retval EFI_OUT_OF_RESOURCES       The request could not be completed due to a
> > +                                     lack of resources.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +ArmadaSoCPcieGet (
> > +  IN OUT EFI_PHYSICAL_ADDRESS  **PcieBaseAddresses,
> > +  IN OUT UINTN                  *Count
> > +  );
> > +
> >  //
> >  // PP2 NIC devices SoC description
> >  //
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c
> > index 355be64..4f8a59a 100644
> > --- a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c
> > @@ -278,6 +278,50 @@ ArmadaSoCDescAhciGet (
> >    return EFI_SUCCESS;
> >  }
> >
> > +/**
> > +  This function returns the total number of PCIE controllers and an array
> > +  with their base addresses.
> > +
> > +  @param[in out] **PcieBaseAddresses Array containing PCIE controllers' base
> > +                                     adresses.
> > +  @param[in out]  *Count             Total amount of available PCIE controllers.
> > +
> > +  @retval EFI_SUCCESS                The data were obtained successfully.
> > +  @retval EFI_OUT_OF_RESOURCES       The request could not be completed due to a
> > +                                     lack of resources.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +ArmadaSoCPcieGet (
> > +  IN OUT EFI_PHYSICAL_ADDRESS  **PcieBaseAddresses,
> > +  IN OUT UINTN                  *Count
> > +  )
> > +{
> > +  UINTN CpCount, CpIndex, Index;
> > +  EFI_PHYSICAL_ADDRESS *BaseAddress;
> > +
> > +  CpCount = FixedPcdGet8 (PcdMaxCpCount);
> > +
> > +  *Count = CpCount * MV_SOC_PCIE_PER_CP_COUNT;
> > +  BaseAddress = AllocateZeroPool (*Count * sizeof (EFI_PHYSICAL_ADDRESS));
> > +  if (BaseAddress == NULL) {
> > +    DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__));
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  *PcieBaseAddresses = BaseAddress;
> > +
> > +  for (CpIndex = 0; CpIndex < CpCount; CpIndex++) {
> > +    for (Index = 0; Index < MV_SOC_PCIE_PER_CP_COUNT; Index++) {
> > +      *BaseAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_PCIE_BASE (Index);
> > +      BaseAddress++;
> > +    }
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> >  EFI_STATUS
> >  EFIAPI
> >  ArmadaSoCDescPp2Get (
> > --
> > 2.7.4
> >

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation
  2019-05-09  9:53 ` [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation Marcin Wojtas
@ 2019-05-10 15:25   ` Leif Lindholm
  2019-05-10 15:29     ` Marcin Wojtas
  2019-05-16 14:02   ` Ard Biesheuvel
  1 sibling, 1 reply; 36+ messages in thread
From: Leif Lindholm @ 2019-05-10 15:25 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: devel, ard.biesheuvel, jsd, jaz, kostap, Jici.Gao, rebecca,
	kettenis

On Thu, May 09, 2019 at 11:53:34AM +0200, Marcin Wojtas wrote:
> From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> 
> Implement a special version of PciExpressLib that takes the quirky
> nature of the Synopsys Designware PCIe IP into account. In particular,
> we need to ignores config space accesses to all devices on the first
> bus except device 0, because the broadcast nature of type 0 configuration
> cycles will result in whatever device is in the slot to appear at each
> of the 32 device positions.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf |   42 +
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c   | 1529 ++++++++++++++++++++
>  2 files changed, 1571 insertions(+)
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> 
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> new file mode 100644
> index 0000000..8f09820
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> @@ -0,0 +1,42 @@
> +## @file
> +#
> +#  Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
> +#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +#
> +#  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                    = 0x0001001B
> +  BASE_NAME                      = Armada7k8kPciExpressLib
> +  FILE_GUID                      = f0926204-3061-40ed-8261-2aeccc7914c9
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciExpressLib
> +
> +[Sources]
> +  PciExpressLib.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  DebugLib
> +  IoLib
> +  PcdLib
> +
> +[Pcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress  ## CONSUMES
> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdPciBusMin
> +  gArmTokenSpaceGuid.PcdPciBusMax
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> new file mode 100644
> index 0000000..8fa2eb6
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> @@ -0,0 +1,1529 @@
> +/** @file
> +
> +  Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>

If Ard is the author of this patch, should there not be Linaro
copyright here as well?

> +
> +  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 <Base.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciExpressLib.h>
> +
> +/**
> +  Assert the validity of a PCI address. A valid PCI address should contain 1's
> +  only in the low 28 bits.
> +
> +  @param  A The address to validate.
> +
> +**/
> +#define ASSERT_INVALID_PCI_ADDRESS(A) \
> +  ASSERT (((A) & ~0xfffffff) == 0)
> +
> +/**
> +  Registers a PCI device so PCI configuration registers may be accessed after
> +  SetVirtualAddressMap().
> +
> +  Registers the PCI device specified by Address so all the PCI configuration
> +  registers associated with that PCI device may be accessed after SetVirtualAddressMap()
> +  is called.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @retval RETURN_SUCCESS           The PCI device was registered for runtime access.
> +  @retval RETURN_UNSUPPORTED       An attempt was made to call this function
> +                                   after ExitBootServices().
> +  @retval RETURN_UNSUPPORTED       The resources required to access the PCI device
> +                                   at runtime could not be mapped.
> +  @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
> +                                   complete the registration.
> +
> +**/
> +RETURN_STATUS
> +EFIAPI
> +PciExpressRegisterForRuntimeAccess (
> +  IN UINTN  Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  return RETURN_UNSUPPORTED;
> +}
> +
> +#define ECAM_BUS_SIZE       SIZE_1MB
> +#define ECAM_DEV_SIZE       SIZE_32KB
> +
> +STATIC
> +BOOLEAN
> +IgnoreBusDeviceFunction (
> +  IN  UINTN   Address
> +  )
> +{
> +  ASSERT (Address >= FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE);
> +  ASSERT (Address < (FixedPcdGet32 (PcdPciBusMax) + 1) * ECAM_BUS_SIZE);
> +
> +  //
> +  // Type 0 configuration cycles don't contain a b/d/f specifier, and so it
> +  // is up to the bus that delivers them to ensure they only end up at the
> +  // correct device/function. Sadly, the Synopsys IP does not implement this,
> +  // and so we have to ignore config space accesses for all devices on the
> +  // first bus except device 0.
> +  //
> +  return (Address >= (FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE +
> +                      ECAM_DEV_SIZE) &&
> +          Address < (FixedPcdGet32 (PcdPciBusMin) + 1) * ECAM_BUS_SIZE);
> +}
> +
> +/**
> +  Gets the base address of PCI Express.
> +
> +  This internal functions retrieves PCI Express Base Address via a PCD entry
> +  PcdPciExpressBaseAddress.
> +
> +  @return The base address of PCI Express.
> +
> +**/
> +VOID*
> +GetPciExpressBaseAddress (
> +  VOID
> +  )
> +{
> +  return (VOID*)(UINTN) PcdGet64 (PcdPciExpressBaseAddress);

Drop space before PcdGet64.

> +}
> +
> +/**
> +  Reads an 8-bit PCI configuration register.
> +
> +  Reads and returns the 8-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @return The read value from the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressRead8 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;

Bikeshedding time: could/should we replace these with MAX_UINT8,
MAX_UINT16, MAX_UINT32?

> +  }
> +  return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);

Drop space after (UINTN).

> +}
> +
> +/**
> +  Writes an 8-bit PCI configuration register.
> +
> +  Writes the 8-bit PCI configuration register specified by Address with the
> +  value specified by Value. Value is returned. This function must guarantee
> +  that all PCI read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  Value   The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressWrite8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value);

Drop space after (UINTN).
(There are more below, please address throughout.)

> +}
> +
> +/**
> +  Performs a bitwise OR of an 8-bit PCI configuration register with
> +  an 8-bit value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 8-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> +  value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 8-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressAnd8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> +  value, followed a  bitwise OR with another 8-bit value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and
> +  the value specified by OrData, and writes the result to the 8-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressAndThenOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     AndData,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioAndThenOr8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in an 8-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to read.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldRead8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldRead8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit
> +           );
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  8-bit register is returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldWrite8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldWrite8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           Value
> +           );
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 8-bit port.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 8-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldOr8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 8-bit register.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 8-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldAnd8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldAnd8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  8-bit port.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 8-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +  @param  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldAndThenOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     AndData,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldAndThenOr8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a 16-bit PCI configuration register.
> +
> +  Reads and returns the 16-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @return The read value from the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressRead16 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
> +}
> +
> +/**
> +  Writes a 16-bit PCI configuration register.
> +
> +  Writes the 16-bit PCI configuration register specified by Address with the
> +  value specified by Value. Value is returned. This function must guarantee
> +  that all PCI read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  Value   The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressWrite16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of a 16-bit PCI configuration register with
> +  a 16-bit value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 16-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> +  value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 16-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressAnd16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> +  value, followed a  bitwise OR with another 16-bit value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and
> +  the value specified by OrData, and writes the result to the 16-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressAndThenOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioAndThenOr16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in a 16-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to read.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldRead16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldRead16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit
> +           );
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  16-bit register is returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldWrite16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldWrite16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           Value
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 16-bit port.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 16-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldOr16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 16-bit register.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 16-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldAnd16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldAnd16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  16-bit port.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 16-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +  @param  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldAndThenOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    AndData,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldAndThenOr16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a 32-bit PCI configuration register.
> +
> +  Reads and returns the 32-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @return The read value from the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressRead32 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address);
> +}
> +
> +/**
> +  Writes a 32-bit PCI configuration register.
> +
> +  Writes the 32-bit PCI configuration register specified by Address with the
> +  value specified by Value. Value is returned. This function must guarantee
> +  that all PCI read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  Value   The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressWrite32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of a 32-bit PCI configuration register with
> +  a 32-bit value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 32-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> +  value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 32-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressAnd32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> +  value, followed a  bitwise OR with another 32-bit value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and
> +  the value specified by OrData, and writes the result to the 32-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressAndThenOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioAndThenOr32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in a 32-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to read.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldRead32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldRead32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit
> +           );
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  32-bit register is returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldWrite32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldWrite32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           Value
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 32-bit port.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 32-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldOr32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 32-bit register.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 32-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldAnd32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldAnd32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  32-bit port.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 32-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +  @param  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldAndThenOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    AndData,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldAndThenOr32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a range of PCI configuration registers into a caller supplied buffer.
> +
> +  Reads the range of PCI configuration registers specified by StartAddress and
> +  Size into the buffer specified by Buffer. This function only allows the PCI
> +  configuration registers from a single PCI function to be read. Size is
> +  returned. When possible 32-bit PCI configuration read cycles are used to read
> +  from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit
> +  and 16-bit PCI configuration read cycles may be used at the beginning and the
> +  end of the range.
> +
> +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> +  If Size > 0 and Buffer is NULL, then ASSERT().
> +
> +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> +                        Function and Register.
> +  @param  Size          The size in bytes of the transfer.
> +  @param  Buffer        The pointer to a buffer receiving the data read.
> +
> +  @return Size read data from StartAddress.
> +
> +**/
> +UINTN
> +EFIAPI
> +PciExpressReadBuffer (
> +  IN      UINTN                     StartAddress,
> +  IN      UINTN                     Size,
> +  OUT     VOID                      *Buffer
> +  )
> +{
> +  UINTN   ReturnValue;
> +
> +  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
> +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> +
> +  if (Size == 0) {
> +    return Size;
> +  }
> +
> +  ASSERT (Buffer != NULL);
> +
> +  //
> +  // Save Size for return
> +  //
> +  ReturnValue = Size;
> +
> +  if ((StartAddress & 1) != 0) {
> +    //
> +    // Read a byte if StartAddress is byte aligned
> +    //
> +    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);

*eep*
Inline volatile casts?
Well, I guess inherited from the original.

We already have a dependency on IoLib (and include the header), can we
use MmioWrite8 instead?

> +    StartAddress += sizeof (UINT8);
> +    Size -= sizeof (UINT8);
> +    Buffer = (UINT8*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
> +    //
> +    // Read a word if StartAddress is word aligned
> +    //
> +    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
> +
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + 1;
> +  }
> +
> +  while (Size >= sizeof (UINT32)) {
> +    //
> +    // Read as many double words as possible
> +    //
> +    WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress));
> +
> +    StartAddress += sizeof (UINT32);
> +    Size -= sizeof (UINT32);
> +    Buffer = (UINT32*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16)) {
> +    //
> +    // Read the last remaining word if exist
> +    //
> +    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT8)) {
> +    //
> +    // Read the last remaining byte if exist
> +    //
> +    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);

Same again.

/
    Leif

> +  }
> +
> +  return ReturnValue;
> +}
> +
> +/**
> +  Copies the data in a caller supplied buffer to a specified range of PCI
> +  configuration space.
> +
> +  Writes the range of PCI configuration registers specified by StartAddress and
> +  Size from the buffer specified by Buffer. This function only allows the PCI
> +  configuration registers from a single PCI function to be written. Size is
> +  returned. When possible 32-bit PCI configuration write cycles are used to
> +  write from StartAddress to StartAddress + Size. Due to alignment restrictions,
> +  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
> +  and the end of the range.
> +
> +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> +  If Size > 0 and Buffer is NULL, then ASSERT().
> +
> +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> +                        Function and Register.
> +  @param  Size          The size in bytes of the transfer.
> +  @param  Buffer        The pointer to a buffer containing the data to write.
> +
> +  @return Size written to StartAddress.
> +
> +**/
> +UINTN
> +EFIAPI
> +PciExpressWriteBuffer (
> +  IN      UINTN                     StartAddress,
> +  IN      UINTN                     Size,
> +  IN      VOID                      *Buffer
> +  )
> +{
> +  UINTN                             ReturnValue;
> +
> +  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
> +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> +
> +  if (Size == 0) {
> +    return 0;
> +  }
> +
> +  ASSERT (Buffer != NULL);
> +
> +  //
> +  // Save Size for return
> +  //
> +  ReturnValue = Size;
> +
> +  if ((StartAddress & 1) != 0) {
> +    //
> +    // Write a byte if StartAddress is byte aligned
> +    //
> +    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
> +    StartAddress += sizeof (UINT8);
> +    Size -= sizeof (UINT8);
> +    Buffer = (UINT8*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
> +    //
> +    // Write a word if StartAddress is word aligned
> +    //
> +    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + 1;
> +  }
> +
> +  while (Size >= sizeof (UINT32)) {
> +    //
> +    // Write as many double words as possible
> +    //
> +    PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
> +    StartAddress += sizeof (UINT32);
> +    Size -= sizeof (UINT32);
> +    Buffer = (UINT32*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16)) {
> +    //
> +    // Write the last remaining word if exist
> +    //
> +    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT8)) {
> +    //
> +    // Write the last remaining byte if exist
> +    //
> +    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
> +  }
> +
> +  return ReturnValue;
> +}
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation
  2019-05-10 15:25   ` Leif Lindholm
@ 2019-05-10 15:29     ` Marcin Wojtas
  0 siblings, 0 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-10 15:29 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: edk2-devel-groups-io, Ard Biesheuvel, jsd@semihalf.com,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	Mark Kettenis

Hi Leif,

pt., 10 maj 2019 o 17:25 Leif Lindholm <leif.lindholm@linaro.org> napisał(a):
>
> On Thu, May 09, 2019 at 11:53:34AM +0200, Marcin Wojtas wrote:
> > From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >
> > Implement a special version of PciExpressLib that takes the quirky
> > nature of the Synopsys Designware PCIe IP into account. In particular,
> > we need to ignores config space accesses to all devices on the first
> > bus except device 0, because the broadcast nature of type 0 configuration
> > cycles will result in whatever device is in the slot to appear at each
> > of the 32 device positions.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> > ---
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf |   42 +
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c   | 1529 ++++++++++++++++++++
> >  2 files changed, 1571 insertions(+)
> >  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> >  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> >
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> > new file mode 100644
> > index 0000000..8f09820
> > --- /dev/null
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> > @@ -0,0 +1,42 @@
> > +## @file
> > +#
> > +#  Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
> > +#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> > +#
> > +#  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                    = 0x0001001B
> > +  BASE_NAME                      = Armada7k8kPciExpressLib
> > +  FILE_GUID                      = f0926204-3061-40ed-8261-2aeccc7914c9
> > +  MODULE_TYPE                    = BASE
> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = PciExpressLib
> > +
> > +[Sources]
> > +  PciExpressLib.c
> > +
> > +[Packages]
> > +  ArmPkg/ArmPkg.dec
> > +  MdePkg/MdePkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +  DebugLib
> > +  IoLib
> > +  PcdLib
> > +
> > +[Pcd]
> > +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress  ## CONSUMES
> > +
> > +[FixedPcd]
> > +  gArmTokenSpaceGuid.PcdPciBusMin
> > +  gArmTokenSpaceGuid.PcdPciBusMax
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> > new file mode 100644
> > index 0000000..8fa2eb6
> > --- /dev/null
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> > @@ -0,0 +1,1529 @@
> > +/** @file
> > +
> > +  Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
> > +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
>
> If Ard is the author of this patch, should there not be Linaro
> copyright here as well?
>
> > +
> > +  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 <Base.h>
> > +
> > +#include <Library/BaseLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/IoLib.h>
> > +#include <Library/PcdLib.h>
> > +#include <Library/PciExpressLib.h>
> > +
> > +/**
> > +  Assert the validity of a PCI address. A valid PCI address should contain 1's
> > +  only in the low 28 bits.
> > +
> > +  @param  A The address to validate.
> > +
> > +**/
> > +#define ASSERT_INVALID_PCI_ADDRESS(A) \
> > +  ASSERT (((A) & ~0xfffffff) == 0)
> > +
> > +/**
> > +  Registers a PCI device so PCI configuration registers may be accessed after
> > +  SetVirtualAddressMap().
> > +
> > +  Registers the PCI device specified by Address so all the PCI configuration
> > +  registers associated with that PCI device may be accessed after SetVirtualAddressMap()
> > +  is called.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +
> > +  @retval RETURN_SUCCESS           The PCI device was registered for runtime access.
> > +  @retval RETURN_UNSUPPORTED       An attempt was made to call this function
> > +                                   after ExitBootServices().
> > +  @retval RETURN_UNSUPPORTED       The resources required to access the PCI device
> > +                                   at runtime could not be mapped.
> > +  @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
> > +                                   complete the registration.
> > +
> > +**/
> > +RETURN_STATUS
> > +EFIAPI
> > +PciExpressRegisterForRuntimeAccess (
> > +  IN UINTN  Address
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  return RETURN_UNSUPPORTED;
> > +}
> > +
> > +#define ECAM_BUS_SIZE       SIZE_1MB
> > +#define ECAM_DEV_SIZE       SIZE_32KB
> > +
> > +STATIC
> > +BOOLEAN
> > +IgnoreBusDeviceFunction (
> > +  IN  UINTN   Address
> > +  )
> > +{
> > +  ASSERT (Address >= FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE);
> > +  ASSERT (Address < (FixedPcdGet32 (PcdPciBusMax) + 1) * ECAM_BUS_SIZE);
> > +
> > +  //
> > +  // Type 0 configuration cycles don't contain a b/d/f specifier, and so it
> > +  // is up to the bus that delivers them to ensure they only end up at the
> > +  // correct device/function. Sadly, the Synopsys IP does not implement this,
> > +  // and so we have to ignore config space accesses for all devices on the
> > +  // first bus except device 0.
> > +  //
> > +  return (Address >= (FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE +
> > +                      ECAM_DEV_SIZE) &&
> > +          Address < (FixedPcdGet32 (PcdPciBusMin) + 1) * ECAM_BUS_SIZE);
> > +}
> > +
> > +/**
> > +  Gets the base address of PCI Express.
> > +
> > +  This internal functions retrieves PCI Express Base Address via a PCD entry
> > +  PcdPciExpressBaseAddress.
> > +
> > +  @return The base address of PCI Express.
> > +
> > +**/
> > +VOID*
> > +GetPciExpressBaseAddress (
> > +  VOID
> > +  )
> > +{
> > +  return (VOID*)(UINTN) PcdGet64 (PcdPciExpressBaseAddress);
>
> Drop space before PcdGet64.
>
> > +}
> > +
> > +/**
> > +  Reads an 8-bit PCI configuration register.
> > +
> > +  Reads and returns the 8-bit PCI configuration register specified by Address.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +
> > +  @return The read value from the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressRead8 (
> > +  IN      UINTN                     Address
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
>
> Bikeshedding time: could/should we replace these with MAX_UINT8,
> MAX_UINT16, MAX_UINT32?
>
> > +  }
> > +  return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
>
> Drop space after (UINTN).
>
> > +}
> > +
> > +/**
> > +  Writes an 8-bit PCI configuration register.
> > +
> > +  Writes the 8-bit PCI configuration register specified by Address with the
> > +  value specified by Value. Value is returned. This function must guarantee
> > +  that all PCI read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  Value   The value to write.
> > +
> > +  @return The value written to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressWrite8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT8                     Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
>
> Drop space after (UINTN).
> (There are more below, please address throughout.)
>
> > +}
> > +
> > +/**
> > +  Performs a bitwise OR of an 8-bit PCI configuration register with
> > +  an 8-bit value.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 8-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  OrData  The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressOr8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT8                     OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> > +  value.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 8-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressAnd8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT8                     AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> > +  value, followed a  bitwise OR with another 8-bit value.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData,
> > +  performs a bitwise OR between the result of the AND operation and
> > +  the value specified by OrData, and writes the result to the 8-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressAndThenOr8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT8                     AndData,
> > +  IN      UINT8                     OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioAndThenOr8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field of a PCI configuration register.
> > +
> > +  Reads the bit field in an 8-bit PCI configuration register. The bit field is
> > +  specified by the StartBit and the EndBit. The value of the bit field is
> > +  returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to read.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +
> > +  @return The value of the bit field read from the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldRead8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldRead8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit
> > +           );
> > +}
> > +
> > +/**
> > +  Writes a bit field to a PCI configuration register.
> > +
> > +  Writes Value to the bit field of the PCI configuration register. The bit
> > +  field is specified by the StartBit and the EndBit. All other bits in the
> > +  destination PCI configuration register are preserved. The new value of the
> > +  8-bit register is returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  Value     The new value of the bit field.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldWrite8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT8                     Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldWrite8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           Value
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
> > +  writes the result back to the bit field in the 8-bit port.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 8-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized. Extra left bits in OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  OrData    The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldOr8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT8                     OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldOr8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
> > +  AND, and writes the result back to the bit field in the 8-bit register.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 8-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized. Extra left bits in AndData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldAnd8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT8                     AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldAnd8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
> > +  bitwise OR, and writes the result back to the bit field in the
> > +  8-bit port.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND followed by a bitwise OR between the read result and
> > +  the value specified by AndData, and writes the result to the 8-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized. Extra left bits in both AndData and
> > +  OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +  @param  OrData    The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldAndThenOr8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT8                     AndData,
> > +  IN      UINT8                     OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldAndThenOr8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a 16-bit PCI configuration register.
> > +
> > +  Reads and returns the 16-bit PCI configuration register specified by Address.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +
> > +  @return The read value from the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressRead16 (
> > +  IN      UINTN                     Address
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
> > +}
> > +
> > +/**
> > +  Writes a 16-bit PCI configuration register.
> > +
> > +  Writes the 16-bit PCI configuration register specified by Address with the
> > +  value specified by Value. Value is returned. This function must guarantee
> > +  that all PCI read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  Value   The value to write.
> > +
> > +  @return The value written to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressWrite16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> > +}
> > +
> > +/**
> > +  Performs a bitwise OR of a 16-bit PCI configuration register with
> > +  a 16-bit value.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 16-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  OrData  The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> > +  value.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 16-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressAnd16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> > +  value, followed a  bitwise OR with another 16-bit value.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData,
> > +  performs a bitwise OR between the result of the AND operation and
> > +  the value specified by OrData, and writes the result to the 16-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressAndThenOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    AndData,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioAndThenOr16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field of a PCI configuration register.
> > +
> > +  Reads the bit field in a 16-bit PCI configuration register. The bit field is
> > +  specified by the StartBit and the EndBit. The value of the bit field is
> > +  returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to read.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +
> > +  @return The value of the bit field read from the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldRead16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldRead16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit
> > +           );
> > +}
> > +
> > +/**
> > +  Writes a bit field to a PCI configuration register.
> > +
> > +  Writes Value to the bit field of the PCI configuration register. The bit
> > +  field is specified by the StartBit and the EndBit. All other bits in the
> > +  destination PCI configuration register are preserved. The new value of the
> > +  16-bit register is returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  Value     The new value of the bit field.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldWrite16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT16                    Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldWrite16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           Value
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
> > +  writes the result back to the bit field in the 16-bit port.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 16-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized. Extra left bits in OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  OrData    The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldOr16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
> > +  AND, and writes the result back to the bit field in the 16-bit register.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 16-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized. Extra left bits in AndData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldAnd16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT16                    AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldAnd16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
> > +  bitwise OR, and writes the result back to the bit field in the
> > +  16-bit port.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND followed by a bitwise OR between the read result and
> > +  the value specified by AndData, and writes the result to the 16-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized. Extra left bits in both AndData and
> > +  OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +  @param  OrData    The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldAndThenOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT16                    AndData,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldAndThenOr16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a 32-bit PCI configuration register.
> > +
> > +  Reads and returns the 32-bit PCI configuration register specified by Address.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +
> > +  @return The read value from the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressRead32 (
> > +  IN      UINTN                     Address
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address);
> > +}
> > +
> > +/**
> > +  Writes a 32-bit PCI configuration register.
> > +
> > +  Writes the 32-bit PCI configuration register specified by Address with the
> > +  value specified by Value. Value is returned. This function must guarantee
> > +  that all PCI read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  Value   The value to write.
> > +
> > +  @return The value written to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressWrite32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> > +}
> > +
> > +/**
> > +  Performs a bitwise OR of a 32-bit PCI configuration register with
> > +  a 32-bit value.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 32-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  OrData  The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> > +  value.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 32-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressAnd32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> > +  value, followed a  bitwise OR with another 32-bit value.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData,
> > +  performs a bitwise OR between the result of the AND operation and
> > +  the value specified by OrData, and writes the result to the 32-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressAndThenOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    AndData,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioAndThenOr32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field of a PCI configuration register.
> > +
> > +  Reads the bit field in a 32-bit PCI configuration register. The bit field is
> > +  specified by the StartBit and the EndBit. The value of the bit field is
> > +  returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to read.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +
> > +  @return The value of the bit field read from the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldRead32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldRead32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit
> > +           );
> > +}
> > +
> > +/**
> > +  Writes a bit field to a PCI configuration register.
> > +
> > +  Writes Value to the bit field of the PCI configuration register. The bit
> > +  field is specified by the StartBit and the EndBit. All other bits in the
> > +  destination PCI configuration register are preserved. The new value of the
> > +  32-bit register is returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  Value     The new value of the bit field.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldWrite32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT32                    Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldWrite32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           Value
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
> > +  writes the result back to the bit field in the 32-bit port.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 32-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized. Extra left bits in OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  OrData    The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldOr32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
> > +  AND, and writes the result back to the bit field in the 32-bit register.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 32-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized. Extra left bits in AndData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldAnd32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT32                    AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldAnd32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
> > +  bitwise OR, and writes the result back to the bit field in the
> > +  32-bit port.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND followed by a bitwise OR between the read result and
> > +  the value specified by AndData, and writes the result to the 32-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized. Extra left bits in both AndData and
> > +  OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +  @param  OrData    The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldAndThenOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT32                    AndData,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldAndThenOr32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a range of PCI configuration registers into a caller supplied buffer.
> > +
> > +  Reads the range of PCI configuration registers specified by StartAddress and
> > +  Size into the buffer specified by Buffer. This function only allows the PCI
> > +  configuration registers from a single PCI function to be read. Size is
> > +  returned. When possible 32-bit PCI configuration read cycles are used to read
> > +  from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit
> > +  and 16-bit PCI configuration read cycles may be used at the beginning and the
> > +  end of the range.
> > +
> > +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> > +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> > +  If Size > 0 and Buffer is NULL, then ASSERT().
> > +
> > +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> > +                        Function and Register.
> > +  @param  Size          The size in bytes of the transfer.
> > +  @param  Buffer        The pointer to a buffer receiving the data read.
> > +
> > +  @return Size read data from StartAddress.
> > +
> > +**/
> > +UINTN
> > +EFIAPI
> > +PciExpressReadBuffer (
> > +  IN      UINTN                     StartAddress,
> > +  IN      UINTN                     Size,
> > +  OUT     VOID                      *Buffer
> > +  )
> > +{
> > +  UINTN   ReturnValue;
> > +
> > +  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
> > +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> > +
> > +  if (Size == 0) {
> > +    return Size;
> > +  }
> > +
> > +  ASSERT (Buffer != NULL);
> > +
> > +  //
> > +  // Save Size for return
> > +  //
> > +  ReturnValue = Size;
> > +
> > +  if ((StartAddress & 1) != 0) {
> > +    //
> > +    // Read a byte if StartAddress is byte aligned
> > +    //
> > +    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
>
> *eep*
> Inline volatile casts?
> Well, I guess inherited from the original.
>
> We already have a dependency on IoLib (and include the header), can we
> use MmioWrite8 instead?
>
> > +    StartAddress += sizeof (UINT8);
> > +    Size -= sizeof (UINT8);
> > +    Buffer = (UINT8*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
> > +    //
> > +    // Read a word if StartAddress is word aligned
> > +    //
> > +    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
> > +
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + 1;
> > +  }
> > +
> > +  while (Size >= sizeof (UINT32)) {
> > +    //
> > +    // Read as many double words as possible
> > +    //
> > +    WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress));
> > +
> > +    StartAddress += sizeof (UINT32);
> > +    Size -= sizeof (UINT32);
> > +    Buffer = (UINT32*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16)) {
> > +    //
> > +    // Read the last remaining word if exist
> > +    //
> > +    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT8)) {
> > +    //
> > +    // Read the last remaining byte if exist
> > +    //
> > +    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
>
> Same again.
>

Yes, it's inherited. Will try MmioWrite8 instead.

Also ok to all remarks above.

Thanks,
Marcin

> /
>     Leif
>
> > +  }
> > +
> > +  return ReturnValue;
> > +}
> > +
> > +/**
> > +  Copies the data in a caller supplied buffer to a specified range of PCI
> > +  configuration space.
> > +
> > +  Writes the range of PCI configuration registers specified by StartAddress and
> > +  Size from the buffer specified by Buffer. This function only allows the PCI
> > +  configuration registers from a single PCI function to be written. Size is
> > +  returned. When possible 32-bit PCI configuration write cycles are used to
> > +  write from StartAddress to StartAddress + Size. Due to alignment restrictions,
> > +  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
> > +  and the end of the range.
> > +
> > +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> > +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> > +  If Size > 0 and Buffer is NULL, then ASSERT().
> > +
> > +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> > +                        Function and Register.
> > +  @param  Size          The size in bytes of the transfer.
> > +  @param  Buffer        The pointer to a buffer containing the data to write.
> > +
> > +  @return Size written to StartAddress.
> > +
> > +**/
> > +UINTN
> > +EFIAPI
> > +PciExpressWriteBuffer (
> > +  IN      UINTN                     StartAddress,
> > +  IN      UINTN                     Size,
> > +  IN      VOID                      *Buffer
> > +  )
> > +{
> > +  UINTN                             ReturnValue;
> > +
> > +  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
> > +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> > +
> > +  if (Size == 0) {
> > +    return 0;
> > +  }
> > +
> > +  ASSERT (Buffer != NULL);
> > +
> > +  //
> > +  // Save Size for return
> > +  //
> > +  ReturnValue = Size;
> > +
> > +  if ((StartAddress & 1) != 0) {
> > +    //
> > +    // Write a byte if StartAddress is byte aligned
> > +    //
> > +    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
> > +    StartAddress += sizeof (UINT8);
> > +    Size -= sizeof (UINT8);
> > +    Buffer = (UINT8*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
> > +    //
> > +    // Write a word if StartAddress is word aligned
> > +    //
> > +    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + 1;
> > +  }
> > +
> > +  while (Size >= sizeof (UINT32)) {
> > +    //
> > +    // Write as many double words as possible
> > +    //
> > +    PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
> > +    StartAddress += sizeof (UINT32);
> > +    Size -= sizeof (UINT32);
> > +    Buffer = (UINT32*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16)) {
> > +    //
> > +    // Write the last remaining word if exist
> > +    //
> > +    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT8)) {
> > +    //
> > +    // Write the last remaining byte if exist
> > +    //
> > +    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
> > +  }
> > +
> > +  return ReturnValue;
> > +}
> > --
> > 2.7.4
> >

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib
  2019-05-09  9:53 ` [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib Marcin Wojtas
@ 2019-05-10 15:50   ` Leif Lindholm
  2019-05-12 11:41     ` Marcin Wojtas
  2019-05-16 14:14   ` Ard Biesheuvel
  1 sibling, 1 reply; 36+ messages in thread
From: Leif Lindholm @ 2019-05-10 15:50 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: devel, ard.biesheuvel, jsd, jaz, kostap, Jici.Gao, rebecca,
	kettenis

On Thu, May 09, 2019 at 11:53:35AM +0200, Marcin Wojtas wrote:
> Add an implementation of the PciHostBridgeLib glue library that
> describes the PCIe RC on this SoC so that the generic PCI host bridge
> driver can attach to it.
> 
> This includes a constructor which performs the SoC specific init and
> training sequences.
> 
> This patch is based on work of Ard Biesheuvel <ard.biesheuvel@linaro.org>
> and Jing Hua <jinghua@marvell.com>/
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf          |  52 +++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h |  95 ++++++

Since you so helpfully gave me a link to your branch, I can tell that
Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
has incorrect line endings. If you could address for v2, that would be
most appreciated.

>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c            | 244 +++++++++++++++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c | 330 ++++++++++++++++++++
>  4 files changed, 721 insertions(+)
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> 
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> new file mode 100644
> index 0000000..e46f71d
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> @@ -0,0 +1,52 @@
> +## @file
> +#  PCI Host Bridge Library instance for Marvell Armada 7k/8k SOC
> +#
> +#  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +#
> +#  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                    = 0x0001001B
> +  BASE_NAME                      = Armada7k8kPciHostBridgeLib
> +  FILE_GUID                      = 7f989c9d-02a0-4348-8aeb-ab2e1566fb18
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciHostBridgeLib|DXE_DRIVER
> +  CONSTRUCTOR                    = Armada7k8kPciHostBridgeLibConstructor
> +
> +[Sources]
> +  PciHostBridgeLib.c
> +  PciHostBridgeLibConstructor.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Marvell/Marvell.dec
> +
> +[LibraryClasses]
> +  ArmLib
> +  ArmadaSoCDescLib
> +  DebugLib
> +  DevicePathLib
> +  MemoryAllocationLib
> +  MvGpioLib
> +  UefiBootServicesTableLib
> +
> +[Protocols]
> +  gEmbeddedGpioProtocolGuid
> +  gMarvellBoardDescProtocolGuid
> +
> +[Depex]
> +  gMarvellPlatformInitCompleteProtocolGuid
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> new file mode 100644
> index 0000000..ff9d919
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> @@ -0,0 +1,95 @@
> +/** @file
> +  PCI Host Bridge Library instance for Marvell 70x0/80x0
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  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 __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
> +#define __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
> +
> +#define IATU_VIEWPORT_OFF                                   0x900
> +#define IATU_VIEWPORT_INBOUND                               BIT31
> +#define IATU_VIEWPORT_OUTBOUND                              0
> +#define IATU_VIEWPORT_REGION_INDEX(Idx)                     ((Idx) & 7)
> +
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0                   0x904
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM          0x0
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO           0x2
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0         0x4
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1         0x5
> +
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0                   0x908
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN         BIT31
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE    BIT28
> +
> +#define IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0                   0x90C
> +#define IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0                 0x910
> +#define IATU_LIMIT_ADDR_OFF_OUTBOUND_0                      0x914
> +#define IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0                 0x918
> +#define IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0               0x91C
> +
> +#define PORT_LINK_CTRL_OFF                                  0x710
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x1                  (0x01 << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x2                  (0x03 << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4                  (0x07 << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x8                  (0x0f << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x16                 (0x1f << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK                (0x3f << 16)
> +
> +#define GEN2_CTRL_OFF                                       0x80c
> +#define GEN2_CTRL_OFF_NUM_OF_LANES(n)                       (((n) & 0x1f) << 8)
> +#define GEN2_CTRL_OFF_NUM_OF_LANES_MASK                     (0x1f << 8)
> +#define GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE                   BIT17
> +
> +#define PCIE_GLOBAL_CTRL_OFFSET                             0x8000
> +#define PCIE_GLOBAL_APP_LTSSM_EN                            BIT2
> +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC                     (0x4 << 4)
> +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK                   (0xF << 4)
> +
> +#define PCIE_GLOBAL_STATUS_REG                              0x8008
> +#define PCIE_GLOBAL_STATUS_RDLH_LINK_UP                     BIT1
> +#define PCIE_GLOBAL_STATUS_PHY_LINK_UP                      BIT9
> +
> +#define PCIE_PM_STATUS                                      0x8014
> +#define PCIE_PM_LTSSM_STAT_MASK                             (0x3f << 3)
> +
> +#define PCIE_GLOBAL_INT_MASK1_REG                           0x8020
> +#define PCIE_INT_A_ASSERT_MASK                              BIT9
> +#define PCIE_INT_B_ASSERT_MASK                              BIT10
> +#define PCIE_INT_C_ASSERT_MASK                              BIT11
> +#define PCIE_INT_D_ASSERT_MASK                              BIT12
> +
> +#define PCIE_ARCACHE_TRC_REG                                0x8050
> +#define PCIE_AWCACHE_TRC_REG                                0x8054
> +#define PCIE_ARUSER_REG                                     0x805C
> +#define PCIE_AWUSER_REG                                     0x8060
> +
> +#define ARCACHE_DEFAULT_VALUE                               0x3511
> +#define AWCACHE_DEFAULT_VALUE                               0x5311
> +
> +#define AX_USER_DOMAIN_INNER_SHAREABLE                      (0x1 << 4)
> +#define AX_USER_DOMAIN_OUTER_SHAREABLE                      (0x2 << 4)
> +#define AX_USER_DOMAIN_MASK                                 (0x3 << 4)
> +
> +#define PCIE_LINK_CAPABILITY                                0x7C
> +#define PCIE_LINK_CTL_2                                     0xA0
> +#define TARGET_LINK_SPEED_MASK                              0xF
> +#define LINK_SPEED_GEN_1                                    0x1
> +#define LINK_SPEED_GEN_2                                    0x2
> +#define LINK_SPEED_GEN_3                                    0x3
> +
> +#define PCIE_GEN3_EQU_CTRL                                  0x8A8
> +#define GEN3_EQU_EVAL_2MS_DISABLE                           BIT5
> +
> +#define PCIE_LINK_UP_TIMEOUT_US                             40000
> +
> +#endif
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
> new file mode 100644
> index 0000000..ff6288c
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
> @@ -0,0 +1,244 @@
> +/** @file
> +  PCI Host Bridge Library instance for Marvell Armada 70x0/80x0
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  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 <PiDxe.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/BoardDesc.h>
> +#include <Protocol/PciHostBridgeResourceAllocation.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +
> +#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 = {
> +  {
> +    {
> +      ACPI_DEVICE_PATH,
> +      ACPI_DP,
> +      {
> +        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
> +        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)

Drop space after (UINT8), x2.

> +      }
> +    },
> +    EISA_PNP_ID(0x0A08), // PCI Express

Space before (.

> +    0
> +  },
> +
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      END_DEVICE_PATH_LENGTH,
> +      0
> +    }
> +  }
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> +  L"Mem", L"I/O", L"Bus"
> +};
> +
> +/**
> +  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
> +  )
> +{
> +  MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol;
> +  MV_BOARD_PCIE_DESCRIPTION   *BoardPcieDescription;
> +  MV_PCIE_CONTROLLER          *PcieController;
> +  PCI_ROOT_BRIDGE             *PciRootBridges;
> +  PCI_ROOT_BRIDGE             *RootBridge;
> +  EFI_STATUS                   Status;
> +  UINTN                        Index;
> +
> +  *Count = 0;
> +
> +  /* Obtain list of available controllers */
> +  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
> +                  NULL,
> +                  (VOID **)&BoardDescriptionProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot locate BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  Status = BoardDescriptionProtocol->PcieDescriptionGet (
> +                                       BoardDescriptionProtocol,
> +                                       &BoardPcieDescription);
> +  if (Status == EFI_NOT_FOUND) {
> +    /* No controllers used on the platform, exit silently */
> +    return NULL;
> +  } else if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot get Pcie board desc from BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  /* Assign return values */
> +  PciRootBridges = AllocateZeroPool (BoardPcieDescription->PcieControllerCount *
> +                                     sizeof (PCI_ROOT_BRIDGE));
> +  if (PciRootBridges == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate resources\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  *Count = BoardPcieDescription->PcieControllerCount;
> +  RootBridge = PciRootBridges;
> +
> +  /* Fill information of all root bridge instances */
> +  for (Index = 0; Index < *Count; Index++, RootBridge++) {
> +
> +    PcieController = &(BoardPcieDescription->PcieControllers[Index]);
> +
> +    RootBridge->Segment   = 0;
> +    RootBridge->Supports  = 0;
> +    RootBridge->Attributes  = RootBridge->Supports;
> +
> +    RootBridge->DmaAbove4G  = FALSE;
> +
> +    RootBridge->AllocationAttributes  = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |
> +                                        EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
> +
> +    RootBridge->Bus.Base = PcieController->PcieBusMin;
> +    RootBridge->Bus.Limit = PcieController->PcieBusMax;
> +    RootBridge->Io.Base = PcieController->PcieIoWinBase;
> +    RootBridge->Io.Limit = PcieController->PcieIoWinBase +
> +                           PcieController->PcieIoWinSize - 1;
> +    RootBridge->Mem.Base = PcieController->PcieMmio32WinBase;
> +    RootBridge->Mem.Limit = PcieController->PcieMmio32WinBase +
> +                            PcieController->PcieMmio32WinSize - 1;
> +    RootBridge->MemAbove4G.Base = PcieController->PcieMmio64WinBase;
> +    RootBridge->MemAbove4G.Limit = PcieController->PcieMmio64WinBase +
> +                                   PcieController->PcieMmio64WinSize - 1;
> +
> +    /* No separate ranges for prefetchable and non-prefetchable BARs */
> +    RootBridge->PMem.Base           = MAX_UINT64;
> +    RootBridge->PMem.Limit          = 0;
> +    RootBridge->PMemAbove4G.Base    = MAX_UINT64;
> +    RootBridge->PMemAbove4G.Limit   = 0;
> +
> +    ASSERT (PcieController->PcieMmio64Translation == 0);
> +    ASSERT (PcieController->PcieMmio32Translation == 0);
> +
> +    RootBridge->NoExtendedConfigSpace = FALSE;
> +
> +    RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath;
> +  }
> +
> +  return PciRootBridges;
> +}
> +
> +/**
> +  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
> +  )
> +{
> +  FreePool (Bridges);
> +}
> +
> +/**
> +  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;
> +  UINTN                              RootBridgeIndex;
> +
> +  DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
> +
> +  RootBridgeIndex = 0;
> +  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;

Drop space after "*)".

> +
> +  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> +
> +    DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
> +
> +    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""));

This ternary is quite an effort to parse. I think a temporary
variable for the retult of the & operation would improve this
substantially.

Alternatively, the wrapping and indentation used in
Silicon/Socionext/SynQuacer/Library/SynQuacerPciHostBridgeLib/SynQuacerPciHostBridgeLib.c
is a lot easier to read.

> +      }
> +    }
> +    /* 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);
> +  }
> +}
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> new file mode 100644
> index 0000000..ced2c12
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> @@ -0,0 +1,330 @@
> +/** @file
> +  PCI Host Bridge Library instance for Marvell 70x0/80x0
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  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 <PiDxe.h>
> +
> +#include <IndustryStandard/Pci22.h>
> +
> +#include <Library/ArmLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MvGpioLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/BoardDesc.h>
> +
> +#include "PciHostBridgeLibConstructor.h"
> +
> +/**
> +  This function configures PCIE controllers IATU windows.
> +
> +  @param [in] PcieBaseAddress PCIE controller base address.
> +  @param [in] Index           IATU window index.
> +  @param [in] CpuBase         Address from the CPU perspective.
> +  @param [in] PciBase         Target PCIE address.
> +  @param [in] Size            IATU window size.
> +  @param [in] Type            IATU window type.
> +  @param [in] EnableFlags     Extra configuration flags.
> +
> +  @retval none
> +
> +**/
> +STATIC
> +VOID
> +ConfigureWindow (
> +  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress,
> +  IN UINTN                Index,
> +  IN UINT64               CpuBase,
> +  IN UINT64               PciBase,
> +  IN UINT64               Size,
> +  IN UINTN                Type,
> +  IN UINTN                EnableFlags
> +  )
> +{
> +  ArmDataMemoryBarrier ();
> +
> +  MmioWrite32 (PcieBaseAddress + IATU_VIEWPORT_OFF,
> +    IATU_VIEWPORT_OUTBOUND | IATU_VIEWPORT_REGION_INDEX (Index));
> +
> +  ArmDataMemoryBarrier ();
> +
> +  MmioWrite32 (PcieBaseAddress + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(CpuBase & 0xFFFFFFFF));
> +  MmioWrite32 (PcieBaseAddress + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(CpuBase >> 32));
> +  MmioWrite32 (PcieBaseAddress + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(CpuBase + Size - 1));
> +  MmioWrite32 (PcieBaseAddress + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(PciBase & 0xFFFFFFFF));
> +  MmioWrite32 (PcieBaseAddress + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(PciBase >> 32));
> +  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
> +    Type);
> +  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> +    IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN | EnableFlags);
> +}
> +
> +/**
> +  Perform PCIE slot reset using external GPIO pin.
> +
> +  @param [in] PcieBaseAddress  PCIE controller base address.
> +
> +  @retval none
> +
> +**/
> +STATIC
> +VOID
> +WaitForLink (
> +  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress
> +  )
> +{
> +  UINT32 Mask;
> +  UINT32 Status;
> +  UINT32 Timeout;
> +
> +  if (!(MmioRead32 (PcieBaseAddress + PCIE_PM_STATUS) & PCIE_PM_LTSSM_STAT_MASK)) {
> +    DEBUG ((DEBUG_INIT, "%a: no PCIE device detected\n", __FUNCTION__));
> +    return;
> +  }
> +
> +  /* Wait for the link to establish itself */
> +  DEBUG ((DEBUG_INIT, "%a: waiting for PCIE link\n", __FUNCTION__));
> +
> +  Mask = PCIE_GLOBAL_STATUS_RDLH_LINK_UP | PCIE_GLOBAL_STATUS_PHY_LINK_UP;
> +  Timeout = PCIE_LINK_UP_TIMEOUT_US / 10;
> +  do {
> +    Status = MmioRead32 (PcieBaseAddress + PCIE_GLOBAL_STATUS_REG);
> +    if ((Status & Mask) == Mask) {
> +      DEBUG ((DEBUG_ERROR, "pcie@0x%x link UP\n", PcieBaseAddress));
> +      break;
> +    }
> +    gBS->Stall (10);

Why this Stall?
Do we need a MemoryFence ()?

> +  } while (Timeout--);
> +}
> +
> +/**
> +  Perform PCIE slot reset using external GPIO pin.
> +
> +  @param [in] *PcieResetGpio  GPIO pin description.
> +
> +  @retval EFI_SUCEESS         PCIE slot reset succeeded.
> +  @retval Other               Return error status.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +ResetPcieSlot (
> +  IN MV_GPIO_PIN *PcieResetGpio
> +  )
> +{
> +  EMBEDDED_GPIO_MODE   Mode;
> +  EMBEDDED_GPIO_PIN    GpioPin;
> +  EMBEDDED_GPIO       *GpioProtocol;
> +  EFI_STATUS           Status;
> +
> +  /* Get GPIO protocol */
> +  Status = MvGpioGetProtocol (PcieResetGpio->ControllerType, &GpioProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Unable to find GPIO protocol\n", __FUNCTION__));
> +    return Status;
> +  }
> +
> +  GpioPin = GPIO (PcieResetGpio->ControllerId, PcieResetGpio->PinNumber),
> +
> +  /* Reset the slot by toggling the GPIO pin */
> +  Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_1 : GPIO_MODE_OUTPUT_0;
> +  Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode);
> +  gBS->Stall (10 * 1000);

Why this Stall?
Do we need a MemoryFence ()?

> +
> +  Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_0 : GPIO_MODE_OUTPUT_1;
> +  Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode);
> +  gBS->Stall (20 * 1000);

Why this Stall?
Do we need a MemoryFence ()?

/
    Leif

> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Obtain resources and perform a low-level PCIE controllers
> +  configuration.
> +
> +  @param [in]  ImageHandle  The image handle.
> +  @param [in] *SystemTable  The system table.
> +
> +  @retval EFI_SUCEESS       PCIE configuration successful.
> +  @retval Other             Return error status.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Armada7k8kPciHostBridgeLibConstructor (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol;
> +  MV_BOARD_PCIE_DESCRIPTION   *BoardPcieDescription;
> +  MV_PCIE_CONTROLLER          *PcieController;
> +  EFI_PHYSICAL_ADDRESS         PcieBaseAddress;
> +  EFI_STATUS                   Status;
> +  UINTN                        Index;
> +
> +  /* Obtain list of available controllers */
> +  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
> +                  NULL,
> +                  (VOID **)&BoardDescriptionProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot locate BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  Status = BoardDescriptionProtocol->PcieDescriptionGet (
> +                                       BoardDescriptionProtocol,
> +                                       &BoardPcieDescription);
> +  if (Status == EFI_NOT_FOUND) {
> +    /* No controllers used on the platform, exit silently */
> +    return EFI_SUCCESS;
> +  } else if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot get Pcie board desc from BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  for (Index = 0; Index < BoardPcieDescription->PcieControllerCount; Index++) {
> +
> +    PcieController = &(BoardPcieDescription->PcieControllers[Index]);
> +
> +    ASSERT (PcieController->PcieBusMin == 0);
> +    ASSERT (PcieController->ConfigSpaceAddress % SIZE_256MB == 0);
> +
> +    if (PcieController->HaveResetGpio == TRUE) {
> +      /* Reset PCIE slot */
> +      Status = ResetPcieSlot (&PcieController->PcieResetGpio);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR,
> +          "%a: Cannot reset Pcie Slot\n",
> +          __FUNCTION__));
> +        return EFI_DEVICE_ERROR;
> +      }
> +    }
> +
> +    /* Low level PCIE controller configuration */
> +    PcieBaseAddress = PcieController->PcieBaseAddress;
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PORT_LINK_CTRL_OFF,
> +      ~PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK,
> +      PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + GEN2_CTRL_OFF,
> +      ~GEN2_CTRL_OFF_NUM_OF_LANES_MASK,
> +      GEN2_CTRL_OFF_NUM_OF_LANES(4) | GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET,
> +      ~(PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK | PCIE_GLOBAL_APP_LTSSM_EN),
> +      PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC);
> +
> +    MmioWrite32 (PcieBaseAddress + PCIE_ARCACHE_TRC_REG,
> +      ARCACHE_DEFAULT_VALUE);
> +
> +    MmioWrite32 (PcieBaseAddress + PCIE_AWCACHE_TRC_REG,
> +      AWCACHE_DEFAULT_VALUE);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_ARUSER_REG,
> +      ~AX_USER_DOMAIN_MASK,
> +      AX_USER_DOMAIN_OUTER_SHAREABLE);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_AWUSER_REG,
> +      ~AX_USER_DOMAIN_MASK,
> +      AX_USER_DOMAIN_OUTER_SHAREABLE);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CTL_2,
> +      ~TARGET_LINK_SPEED_MASK,
> +      LINK_SPEED_GEN_3);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CAPABILITY,
> +      ~TARGET_LINK_SPEED_MASK,
> +      LINK_SPEED_GEN_3);
> +
> +    MmioOr32 (PcieBaseAddress + PCIE_GEN3_EQU_CTRL,
> +      GEN3_EQU_EVAL_2MS_DISABLE);
> +
> +    MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET,
> +      PCIE_GLOBAL_APP_LTSSM_EN);
> +
> +    /* Region 0: MMIO32 range */
> +    ConfigureWindow (PcieBaseAddress,
> +      0,
> +      PcieController->PcieMmio32WinBase,
> +      PcieController->PcieMmio32WinBase,
> +      PcieController->PcieMmio32WinSize,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> +      0);
> +
> +    /* Region 1: Type 0 config space */
> +    ConfigureWindow (PcieBaseAddress,
> +      1,
> +      PcieController->ConfigSpaceAddress,
> +      0x0,
> +      SIZE_64KB,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0,
> +      IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
> +
> +    /* Region 2: Type 1 config space */
> +    ConfigureWindow (PcieBaseAddress,
> +      2,
> +      PcieController->ConfigSpaceAddress + SIZE_64KB,
> +      0x0,
> +      PcieController->PcieBusMax * SIZE_1MB,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1,
> +      IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
> +
> +    /* Region 3: port I/O range */
> +    ConfigureWindow (PcieBaseAddress,
> +      3,
> +      PcieController->PcieIoTranslation,
> +      PcieController->PcieIoWinBase,
> +      PcieController->PcieIoWinSize,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO,
> +      0);
> +
> +    /* Region 4: MMIO64 range */
> +    ConfigureWindow (PcieBaseAddress,
> +      4,
> +      PcieController->PcieMmio64WinBase,
> +      PcieController->PcieMmio64WinBase,
> +      PcieController->PcieMmio64WinSize,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> +      0);
> +
> +    MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_INT_MASK1_REG,
> +      PCIE_INT_A_ASSERT_MASK |
> +      PCIE_INT_B_ASSERT_MASK |
> +      PCIE_INT_C_ASSERT_MASK |
> +      PCIE_INT_D_ASSERT_MASK);
> +
> +    WaitForLink (PcieBaseAddress);
> +
> +    /* Enable the RC */
> +    MmioOr32 (PcieBaseAddress + PCI_COMMAND_OFFSET,
> +      EFI_PCI_COMMAND_IO_SPACE |
> +      EFI_PCI_COMMAND_MEMORY_SPACE |
> +      EFI_PCI_COMMAND_BUS_MASTER);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 09/14] Marvell/Armada80x0McBin: Enable ACPI PCIE support
  2019-05-09  9:53 ` [edk2-platforms: PATCH 09/14] Marvell/Armada80x0McBin: Enable ACPI " Marcin Wojtas
@ 2019-05-10 15:54   ` Leif Lindholm
  2019-05-16 14:23   ` Ard Biesheuvel
  1 sibling, 0 replies; 36+ messages in thread
From: Leif Lindholm @ 2019-05-10 15:54 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: devel, ard.biesheuvel, jsd, jaz, kostap, Jici.Gao, rebecca,
	kettenis

On Thu, May 09, 2019 at 11:53:37AM +0200, Marcin Wojtas wrote:
> This patch adds description of the PCIE controller in
> ACPI tables of MacchiatoBin community board.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf       |   1 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h    |  25 +++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl  | 217 ++++++++++++++++++++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc |  47 +++++
>  4 files changed, 290 insertions(+)
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc
> 
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf
> index 9e52281..e627932 100644
> --- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf
> @@ -25,6 +25,7 @@
>  
>  [Sources]
>    Armada80x0McBin/Dsdt.asl
> +  Armada80x0McBin/Mcfg.aslc
>    Fadt.aslc
>    Gtdt.aslc
>    Madt.aslc
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
> new file mode 100644
> index 0000000..93631c2
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h

This file also has wrong line endings in your branch.

/
    Leif

> @@ -0,0 +1,25 @@
> +/**
> +
> +  Copyright (C) 2019, Marvell International Ltd. and its affiliates.
> +
> +  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.
> +
> +**/
> +
> +#define PCI_BUS_MIN        0x0
> +#define PCI_BUS_MAX        0x0
> +#define PCI_BUS_COUNT      0x1
> +#define PCI_MMIO32_BASE    0xC0000000
> +#define PCI_MMIO32_SIZE    0x20000000
> +#define PCI_MMIO64_BASE    0x800000000
> +#define PCI_MMIO64_SIZE    0x100000000
> +#define PCI_IO_BASE        0x0
> +#define PCI_IO_SIZE        0x10000
> +#define PCI_IO_TRANSLATION 0xEFF00000
> +#define PCI_ECAM_BASE      0xE0008000
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl
> index 87cb93a..caf5cb9 100644
> --- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl
> @@ -14,6 +14,7 @@
>  
>  **/
>  
> +#include "Armada80x0McBin/Pcie.h"
>  #include "IcuInterrupts.h"
>  
>  DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
> @@ -306,5 +307,221 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
>                  }
>              })
>          }
> +
> +        //
> +        // PCIe Root Bus
> +        //
> +        Device (PCI0)
> +        {
> +            Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
> +            Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
> +            Name (_SEG, 0x00)  // _SEG: PCI Segment
> +            Name (_BBN, 0x00)  // _BBN: BIOS Bus Number
> +            Name (_CCA, 0x01)  // _CCA: Cache Coherency Attribute
> +            Name (_PRT, Package ()  // _PRT: PCI Routing Table
> +            {
> +                Package () { 0xFFFF, 0x0, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x1, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x2, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x3, 0x0, 0x40 }
> +            })
> +
> +            Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings
> +            {
> +                Name (RBUF, ResourceTemplate ()
> +                {
> +                    WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
> +                        0x0000,                             // Granularity
> +                        PCI_BUS_MIN,                        // Range Minimum
> +                        PCI_BUS_MAX,                        // Range Maximum
> +                        0x0000,                             // Translation Offset
> +                        PCI_BUS_COUNT                       // Length
> +                        )
> +                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
> +                        0x00000000,                         // Granularity
> +                        PCI_MMIO32_BASE,                    // Range Minimum
> +                        0xDFFFFFFF,                         // Range Maximum
> +                        0x00000000,                         // Translation Offset
> +                        PCI_MMIO32_SIZE                     // Length
> +                        )
> +                    QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
> +                        0x0000000000000000,                 // Granularity
> +                        PCI_MMIO64_BASE,                    // Range Minimum
> +                        0x8FFFFFFFF,                        // Range Maximum
> +                        0x00000000,                         // Translation Offset
> +                        PCI_MMIO64_SIZE                     // Length
> +                        )
> +                    DWordIo (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
> +                        0x00000000,                         // Granularity
> +                        PCI_IO_BASE,                        // Range Minimum
> +                        0x0000FFFF,                         // Range Maximum
> +                        PCI_IO_TRANSLATION,                 // Translation Address
> +                        PCI_IO_SIZE,                        // Length
> +                        ,
> +                        ,
> +                        ,
> +                        TypeTranslation
> +                        )
> +                })
> +                Return (RBUF) /* \_SB_.PCI0._CRS.RBUF */
> +            } // Method(_CRS)
> +
> +            Device (RES0)
> +            {
> +                Name (_HID, "PNP0C02")
> +                Name (_CRS, ResourceTemplate ()
> +                {
> +                    Memory32Fixed (ReadWrite,
> +                                   PCI_ECAM_BASE,
> +                                   0x10000000
> +                                   )
> +                })
> +            }
> +            Name (SUPP, 0x00)
> +            Name (CTRL, 0x00)
> +            Method (_OSC, 4, NotSerialized)  // _OSC: Operating System Capabilities
> +            {
> +                CreateDWordField (Arg3, 0x00, CDW1)
> +                If (LEqual (Arg0, ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") /* PCI Host Bridge Device */))
> +                {
> +                    CreateDWordField (Arg3, 0x04, CDW2)
> +                    CreateDWordField (Arg3, 0x08, CDW3)
> +                    Store (CDW2, SUPP) /* \_SB_.PCI0.SUPP */
> +                    Store (CDW3, CTRL) /* \_SB_.PCI0.CTRL */
> +                    If (LNotEqual (And (SUPP, 0x16), 0x16))
> +                    {
> +                        And (CTRL, 0x1E, CTRL) /* \_SB_.PCI0.CTRL */
> +                    }
> +
> +                    And (CTRL, 0x1D, CTRL) /* \_SB_.PCI0.CTRL */
> +                    If (LNotEqual (Arg1, One))
> +                    {
> +                        Or (CDW1, 0x08, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    }
> +
> +                    If (LNotEqual (CDW3, CTRL))
> +                    {
> +                        Or (CDW1, 0x10, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    }
> +
> +                    Store (CTRL, CDW3) /* \_SB_.PCI0._OSC.CDW3 */
> +                    Return (Arg3)
> +                }
> +                Else
> +                {
> +                    Or (CDW1, 0x04, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    Return (Arg3)
> +                }
> +            } // Method(_OSC)
> +
> +            //
> +            // Device-Specific Methods
> +            //
> +            Method(_DSM, 0x4, NotSerialized) {
> +              If (LEqual(Arg0, ToUUID("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
> +                switch (ToInteger(Arg2)) {
> +                  //
> +                  // Function 0: Return supported functions
> +                  //
> +                  case(0) {
> +                    Return (Buffer() {0xFF})
> +                  }
> +
> +                  //
> +                  // Function 1: Return PCIe Slot Information
> +                  //
> +                  case(1) {
> +                    Return (Package(2) {
> +                      One, // Success
> +                      Package(3) {
> +                        0x1,  // x1 PCIe link
> +                        0x1,  // PCI express card slot
> +                        0x1   // WAKE# signal supported
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 2: Return PCIe Slot Number.
> +                  //
> +                  case(2) {
> +                    Return (Package(1) {
> +                      Package(4) {
> +                        2,  // Source ID
> +                        4,  // Token ID: ID refers to a slot
> +                        0,  // Start bit of the field to use.
> +                        7   // End bit of the field to use.
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 4: Return PCI Bus Capabilities
> +                  //
> +                  case(4) {
> +                    Return (Package(2) {
> +                      One, // Success
> +                      Buffer() {
> +                        1,0,            // Version
> +                        0,0,            // Status, 0:Success
> +                        24,0,0,0,       // Length
> +                        1,0,            // PCI
> +                        16,0,           // Length
> +                        0,              // Attributes
> +                        0x0D,           // Current Speed/Mode
> +                        0x3F,0,         // Supported Speeds/Modes
> +                        0,              // Voltage
> +                        0,0,0,0,0,0,0   // Reserved
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 5: Return Ignore PCI Boot Configuration
> +                  //
> +                  case(5) {
> +                    Return (Package(1) {1})
> +                  }
> +
> +                  //
> +                  // Function 6: Return LTR Maximum Latency
> +                  //
> +                  case(6) {
> +                    Return (Package(4) {
> +                      Package(1){0},  // Maximum Snoop Latency Scale
> +                      Package(1){0},  // Maximum Snoop Latency Value
> +                      Package(1){0},  // Maximum No-Snoop Latency Scale
> +                      Package(1){0}   // Maximum No-Snoop Latency Value
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 7: Return PCI Express Naming
> +                  //
> +                  case(7) {
> +                    Return (Package(2) {
> +                      Package(1) {0},
> +                      Package(1) {Unicode("PCI0")}
> +                    })
> +                  }
> +
> +                  //
> +                  // Not supported
> +                  //
> +                  default {
> +                  }
> +                }
> +              }
> +              Return (Buffer(){0})
> +            } // Method(_DSM)
> +
> +            //
> +            // Root-Complex 0
> +            //
> +            Device (RP0)
> +            {
> +                Name (_ADR, PCI_ECAM_BASE)  // _ADR: Bus 0, Dev 0, Func 0
> +            }
> +        }
>      }
>  }
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc
> new file mode 100644
> index 0000000..bda5800
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc
> @@ -0,0 +1,47 @@
> +/** @file
> +
> +  Memory mapped config space base address table (MCFG)
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019, Marvell International Ltd. and its affiliates.<BR>
> +
> +  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 <Library/AcpiLib.h>
> +
> +#include "AcpiHeader.h"
> +#include "Armada80x0McBin/Pcie.h"
> +
> +#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +
> +#pragma pack(1)
> +typedef struct {
> +  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
> +  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE Structure;
> +} ACPI_6_0_MCFG_STRUCTURE;
> +#pragma pack()
> +
> +STATIC ACPI_6_0_MCFG_STRUCTURE Mcfg = {
> +  {
> +    __ACPI_HEADER (EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +                   ACPI_6_0_MCFG_STRUCTURE,
> +                   EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION),
> +    EFI_ACPI_RESERVED_QWORD
> +  }, {
> +    PCI_ECAM_BASE,                   // BaseAddress
> +    0,                               // PciSegmentGroupNumber
> +    PCI_BUS_MIN,                     // StartBusNumber
> +    PCI_BUS_MAX,                     // EndBusNumber
> +    EFI_ACPI_RESERVED_DWORD          // Reserved
> +  }
> +};
> +
> +VOID CONST * CONST ReferenceAcpiTable = &Mcfg;
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support
  2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
                   ` (13 preceding siblings ...)
  2019-05-09  9:53 ` [edk2-platforms: PATCH 14/14] Marvell/Armada7k8: Add 'acpiview' shell command to build Marcin Wojtas
@ 2019-05-10 15:58 ` Leif Lindholm
  14 siblings, 0 replies; 36+ messages in thread
From: Leif Lindholm @ 2019-05-10 15:58 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: devel, ard.biesheuvel, jsd, jaz, kostap, Jici.Gao, rebecca,
	kettenis

On Thu, May 09, 2019 at 11:53:28AM +0200, Marcin Wojtas wrote:
> Hi,
> 
> Hereby I submit Armada7k8k PCIE support. The commits
> allow to use single controller on each of currently
> supported boards (MacchiatoBin, A7040/A8040-DB) both in
> firmware and in OS with ACPI boot. Multiple slots,
> using custom PciSegmentLib, will be added later.

Thanks, Marcin.

As you have seen, I had only really minor comments on this
set. (Patches I have not commented on look fine to me.)
But I think we need Ard to give this a skim as well before pushing it,
so I don't think we need a v2 until that has happened.

Best Regards,

Leif

> Current patchset can be grouped following way:
> 1. Preparation patches for Armada platforms (SoC and
>    Board description libraries and protocol)
> 
> 2. Implement PciHostBridgeLib/PciExpressLib and
>    enable compilation.
> 
> 3. ACPI support for each board + switch to pci-host-generic
>    in MacchiatoBin DT.
> 
> 4. Additional 2 small patches.
> 
> Thank to these commits (and all previously merged support), we can
> now use mainline ARM-TF + EDK2 with DT and ACPI distributions and
> operating systems. Example logs:
> * McBin DT boot with pci-host-generic driver https://pastebin.com/5dRVCjRR
> * McBin + Centos AltArch7 https://pastebin.com/BGx3Q6w0
> * ACPI boot on Armada7040Db with USB over PCIE https://pastebin.com/kMMUnEr8
> 
> In case anyone wishes to try, for your convenience, I uploaded
> the McBin binary built from the PCIE branch on top of the
> latest edk2/edk2-platforms with today's ARM-TF:
> https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/wiki/files/flash-image-mcbin-mainline-r20190509.bin
> 
> The patches are available in the github:
> https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/pcie-upstream-r20190509
> 
> I'm looking forward to your comments or remarks.
> 
> Best regards,
> Marcin
> 
> Ard Biesheuvel (1):
>   Marvell/Armada7k8k: Add PciExpressLib implementation
> 
> Marcin Wojtas (13):
>   Marvell/Library: MvGpioLib: Extend GPIO pin description
>   Marvell/Library: ArmadaSoCDescLib: Add PCIE information
>   Marvell/Library: ArmadaBoardDescLib: Add PCIE information
>   Marvell/Armada7k8k: Extend board description libraries with PCIE
>   Marvell/Armada7k8k: MvBoardDesc: Extend protocol with PCIE support
>   Marvell/Armada7k8k: Implement PciHostBridgeLib
>   Marvell/Armada7k8k: Enable PCIE support
>   Marvell/Armada80x0McBin: Enable ACPI PCIE support
>   Marvell/Armada80x0Db: Enable ACPI PCIE support
>   Marvell/Armada70x0Db: Enable ACPI PCIE support
>   Marvell/Armada80x0McBin: DeviceTree: Use pci-host-generic driver
>   Marvell/Armada7k8k: Remove duplication in .dsc files
>   Marvell/Armada7k8: Add 'acpiview' shell command to build
> 
>  Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc                                               |   18 +-
>  Platform/Marvell/Armada70x0Db/Armada70x0Db.dsc                                              |    4 +-
>  Platform/Marvell/Armada80x0Db/Armada80x0Db.dsc                                              |    4 +-
>  Platform/SolidRun/Armada80x0McBin/Armada80x0McBin.dsc                                       |    4 +-
>  Silicon/Marvell/Armada7k8k/Armada7k8k.fdf                                                   |    5 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf                                      |    1 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf                                      |    1 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf                                   |    1 +
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf                |   42 +
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf          |   52 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h                                   |   25 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h                                   |   25 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h                                |   25 +
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h |   95 ++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.h              |    6 +
>  Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h                                        |   46 +
>  Silicon/Marvell/Include/Library/ArmadaSoCDescLib.h                                          |   20 +
>  Silicon/Marvell/Include/Library/MvGpioLib.h                                                 |    1 +
>  Silicon/Marvell/Include/Protocol/BoardDesc.h                                                |   22 +
>  Platform/Marvell/Armada70x0Db/Armada70x0DbBoardDescLib/Armada70x0DbBoardDescLib.c           |   48 +
>  Platform/Marvell/Armada70x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c               |    4 +
>  Platform/Marvell/Armada80x0Db/Armada80x0DbBoardDescLib/Armada80x0DbBoardDescLib.c           |   48 +
>  Platform/Marvell/Armada80x0Db/NonDiscoverableInitLib/NonDiscoverableInitLib.c               |    6 +
>  Platform/SolidRun/Armada80x0McBin/Armada80x0McBinBoardDescLib/Armada80x0McBinBoardDescLib.c |   48 +
>  Platform/SolidRun/Armada80x0McBin/NonDiscoverableInitLib/NonDiscoverableInitLib.c           |    1 +
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c                  | 1529 ++++++++++++++++++++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c            |  244 ++++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c |  330 +++++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kSoCDescLib/Armada7k8kSoCDescLib.c              |   44 +
>  Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c                                          |   86 ++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl                                 |  217 +++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc                                |   47 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl                                 |  217 +++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc                                |   47 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl                              |  217 +++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc                             |   47 +
>  Silicon/Marvell/Armada7k8k/DeviceTree/armada-8040-mcbin.dts                                 |    3 +
>  37 files changed, 3569 insertions(+), 11 deletions(-)
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc
> 
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib
  2019-05-10 15:50   ` Leif Lindholm
@ 2019-05-12 11:41     ` Marcin Wojtas
  0 siblings, 0 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-12 11:41 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: edk2-devel-groups-io, Ard Biesheuvel, jsd@semihalf.com,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	Mark Kettenis

Hi Leif,

pt., 10 maj 2019 o 17:50 Leif Lindholm <leif.lindholm@linaro.org> napisał(a):
>
> On Thu, May 09, 2019 at 11:53:35AM +0200, Marcin Wojtas wrote:
> > Add an implementation of the PciHostBridgeLib glue library that
> > describes the PCIe RC on this SoC so that the generic PCI host bridge
> > driver can attach to it.
> >
> > This includes a constructor which performs the SoC specific init and
> > training sequences.
> >
> > This patch is based on work of Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > and Jing Hua <jinghua@marvell.com>/
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> > ---
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf          |  52 +++
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h |  95 ++++++
>
> Since you so helpfully gave me a link to your branch, I can tell that
> Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> has incorrect line endings. If you could address for v2, that would be
> most appreciated.
>
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c            | 244 +++++++++++++++
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c | 330 ++++++++++++++++++++
> >  4 files changed, 721 insertions(+)
> >  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> >  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> >  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
> >  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> >
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> > new file mode 100644
> > index 0000000..e46f71d
> > --- /dev/null
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> > @@ -0,0 +1,52 @@
> > +## @file
> > +#  PCI Host Bridge Library instance for Marvell Armada 7k/8k SOC
> > +#
> > +#  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> > +#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> > +#
> > +#  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                    = 0x0001001B
> > +  BASE_NAME                      = Armada7k8kPciHostBridgeLib
> > +  FILE_GUID                      = 7f989c9d-02a0-4348-8aeb-ab2e1566fb18
> > +  MODULE_TYPE                    = DXE_DRIVER
> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = PciHostBridgeLib|DXE_DRIVER
> > +  CONSTRUCTOR                    = Armada7k8kPciHostBridgeLibConstructor
> > +
> > +[Sources]
> > +  PciHostBridgeLib.c
> > +  PciHostBridgeLibConstructor.c
> > +
> > +[Packages]
> > +  ArmPkg/ArmPkg.dec
> > +  EmbeddedPkg/EmbeddedPkg.dec
> > +  MdeModulePkg/MdeModulePkg.dec
> > +  MdePkg/MdePkg.dec
> > +  Silicon/Marvell/Marvell.dec
> > +
> > +[LibraryClasses]
> > +  ArmLib
> > +  ArmadaSoCDescLib
> > +  DebugLib
> > +  DevicePathLib
> > +  MemoryAllocationLib
> > +  MvGpioLib
> > +  UefiBootServicesTableLib
> > +
> > +[Protocols]
> > +  gEmbeddedGpioProtocolGuid
> > +  gMarvellBoardDescProtocolGuid
> > +
> > +[Depex]
> > +  gMarvellPlatformInitCompleteProtocolGuid
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> > new file mode 100644
> > index 0000000..ff9d919
> > --- /dev/null
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> > @@ -0,0 +1,95 @@
> > +/** @file
> > +  PCI Host Bridge Library instance for Marvell 70x0/80x0
> > +
> > +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> > +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> > +
> > +  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 __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
> > +#define __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
> > +
> > +#define IATU_VIEWPORT_OFF                                   0x900
> > +#define IATU_VIEWPORT_INBOUND                               BIT31
> > +#define IATU_VIEWPORT_OUTBOUND                              0
> > +#define IATU_VIEWPORT_REGION_INDEX(Idx)                     ((Idx) & 7)
> > +
> > +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0                   0x904
> > +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM          0x0
> > +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO           0x2
> > +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0         0x4
> > +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1         0x5
> > +
> > +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0                   0x908
> > +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN         BIT31
> > +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE    BIT28
> > +
> > +#define IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0                   0x90C
> > +#define IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0                 0x910
> > +#define IATU_LIMIT_ADDR_OFF_OUTBOUND_0                      0x914
> > +#define IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0                 0x918
> > +#define IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0               0x91C
> > +
> > +#define PORT_LINK_CTRL_OFF                                  0x710
> > +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x1                  (0x01 << 16)
> > +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x2                  (0x03 << 16)
> > +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4                  (0x07 << 16)
> > +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x8                  (0x0f << 16)
> > +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x16                 (0x1f << 16)
> > +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK                (0x3f << 16)
> > +
> > +#define GEN2_CTRL_OFF                                       0x80c
> > +#define GEN2_CTRL_OFF_NUM_OF_LANES(n)                       (((n) & 0x1f) << 8)
> > +#define GEN2_CTRL_OFF_NUM_OF_LANES_MASK                     (0x1f << 8)
> > +#define GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE                   BIT17
> > +
> > +#define PCIE_GLOBAL_CTRL_OFFSET                             0x8000
> > +#define PCIE_GLOBAL_APP_LTSSM_EN                            BIT2
> > +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC                     (0x4 << 4)
> > +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK                   (0xF << 4)
> > +
> > +#define PCIE_GLOBAL_STATUS_REG                              0x8008
> > +#define PCIE_GLOBAL_STATUS_RDLH_LINK_UP                     BIT1
> > +#define PCIE_GLOBAL_STATUS_PHY_LINK_UP                      BIT9
> > +
> > +#define PCIE_PM_STATUS                                      0x8014
> > +#define PCIE_PM_LTSSM_STAT_MASK                             (0x3f << 3)
> > +
> > +#define PCIE_GLOBAL_INT_MASK1_REG                           0x8020
> > +#define PCIE_INT_A_ASSERT_MASK                              BIT9
> > +#define PCIE_INT_B_ASSERT_MASK                              BIT10
> > +#define PCIE_INT_C_ASSERT_MASK                              BIT11
> > +#define PCIE_INT_D_ASSERT_MASK                              BIT12
> > +
> > +#define PCIE_ARCACHE_TRC_REG                                0x8050
> > +#define PCIE_AWCACHE_TRC_REG                                0x8054
> > +#define PCIE_ARUSER_REG                                     0x805C
> > +#define PCIE_AWUSER_REG                                     0x8060
> > +
> > +#define ARCACHE_DEFAULT_VALUE                               0x3511
> > +#define AWCACHE_DEFAULT_VALUE                               0x5311
> > +
> > +#define AX_USER_DOMAIN_INNER_SHAREABLE                      (0x1 << 4)
> > +#define AX_USER_DOMAIN_OUTER_SHAREABLE                      (0x2 << 4)
> > +#define AX_USER_DOMAIN_MASK                                 (0x3 << 4)
> > +
> > +#define PCIE_LINK_CAPABILITY                                0x7C
> > +#define PCIE_LINK_CTL_2                                     0xA0
> > +#define TARGET_LINK_SPEED_MASK                              0xF
> > +#define LINK_SPEED_GEN_1                                    0x1
> > +#define LINK_SPEED_GEN_2                                    0x2
> > +#define LINK_SPEED_GEN_3                                    0x3
> > +
> > +#define PCIE_GEN3_EQU_CTRL                                  0x8A8
> > +#define GEN3_EQU_EVAL_2MS_DISABLE                           BIT5
> > +
> > +#define PCIE_LINK_UP_TIMEOUT_US                             40000
> > +
> > +#endif
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
> > new file mode 100644
> > index 0000000..ff6288c
> > --- /dev/null
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
> > @@ -0,0 +1,244 @@
> > +/** @file
> > +  PCI Host Bridge Library instance for Marvell Armada 70x0/80x0
> > +
> > +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> > +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> > +
> > +  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 <PiDxe.h>
> > +
> > +#include <Library/DebugLib.h>
> > +#include <Library/DevicePathLib.h>
> > +#include <Library/MemoryAllocationLib.h>
> > +#include <Library/PcdLib.h>
> > +#include <Library/PciHostBridgeLib.h>
> > +#include <Library/UefiBootServicesTableLib.h>
> > +
> > +#include <Protocol/BoardDesc.h>
> > +#include <Protocol/PciHostBridgeResourceAllocation.h>
> > +#include <Protocol/PciRootBridgeIo.h>
> > +
> > +#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 = {
> > +  {
> > +    {
> > +      ACPI_DEVICE_PATH,
> > +      ACPI_DP,
> > +      {
> > +        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
> > +        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
>
> Drop space after (UINT8), x2.
>
> > +      }
> > +    },
> > +    EISA_PNP_ID(0x0A08), // PCI Express
>
> Space before (.
>
> > +    0
> > +  },
> > +
> > +  {
> > +    END_DEVICE_PATH_TYPE,
> > +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> > +    {
> > +      END_DEVICE_PATH_LENGTH,
> > +      0
> > +    }
> > +  }
> > +};
> > +
> > +GLOBAL_REMOVE_IF_UNREFERENCED
> > +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> > +  L"Mem", L"I/O", L"Bus"
> > +};
> > +
> > +/**
> > +  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
> > +  )
> > +{
> > +  MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol;
> > +  MV_BOARD_PCIE_DESCRIPTION   *BoardPcieDescription;
> > +  MV_PCIE_CONTROLLER          *PcieController;
> > +  PCI_ROOT_BRIDGE             *PciRootBridges;
> > +  PCI_ROOT_BRIDGE             *RootBridge;
> > +  EFI_STATUS                   Status;
> > +  UINTN                        Index;
> > +
> > +  *Count = 0;
> > +
> > +  /* Obtain list of available controllers */
> > +  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
> > +                  NULL,
> > +                  (VOID **)&BoardDescriptionProtocol);
> > +  if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR,
> > +      "%a: Cannot locate BoardDesc protocol\n",
> > +      __FUNCTION__));
> > +    return NULL;
> > +  }
> > +
> > +  Status = BoardDescriptionProtocol->PcieDescriptionGet (
> > +                                       BoardDescriptionProtocol,
> > +                                       &BoardPcieDescription);
> > +  if (Status == EFI_NOT_FOUND) {
> > +    /* No controllers used on the platform, exit silently */
> > +    return NULL;
> > +  } else if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR,
> > +      "%a: Cannot get Pcie board desc from BoardDesc protocol\n",
> > +      __FUNCTION__));
> > +    return NULL;
> > +  }
> > +
> > +  /* Assign return values */
> > +  PciRootBridges = AllocateZeroPool (BoardPcieDescription->PcieControllerCount *
> > +                                     sizeof (PCI_ROOT_BRIDGE));
> > +  if (PciRootBridges == NULL) {
> > +    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate resources\n", __FUNCTION__));
> > +    return NULL;
> > +  }
> > +
> > +  *Count = BoardPcieDescription->PcieControllerCount;
> > +  RootBridge = PciRootBridges;
> > +
> > +  /* Fill information of all root bridge instances */
> > +  for (Index = 0; Index < *Count; Index++, RootBridge++) {
> > +
> > +    PcieController = &(BoardPcieDescription->PcieControllers[Index]);
> > +
> > +    RootBridge->Segment   = 0;
> > +    RootBridge->Supports  = 0;
> > +    RootBridge->Attributes  = RootBridge->Supports;
> > +
> > +    RootBridge->DmaAbove4G  = FALSE;
> > +
> > +    RootBridge->AllocationAttributes  = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |
> > +                                        EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
> > +
> > +    RootBridge->Bus.Base = PcieController->PcieBusMin;
> > +    RootBridge->Bus.Limit = PcieController->PcieBusMax;
> > +    RootBridge->Io.Base = PcieController->PcieIoWinBase;
> > +    RootBridge->Io.Limit = PcieController->PcieIoWinBase +
> > +                           PcieController->PcieIoWinSize - 1;
> > +    RootBridge->Mem.Base = PcieController->PcieMmio32WinBase;
> > +    RootBridge->Mem.Limit = PcieController->PcieMmio32WinBase +
> > +                            PcieController->PcieMmio32WinSize - 1;
> > +    RootBridge->MemAbove4G.Base = PcieController->PcieMmio64WinBase;
> > +    RootBridge->MemAbove4G.Limit = PcieController->PcieMmio64WinBase +
> > +                                   PcieController->PcieMmio64WinSize - 1;
> > +
> > +    /* No separate ranges for prefetchable and non-prefetchable BARs */
> > +    RootBridge->PMem.Base           = MAX_UINT64;
> > +    RootBridge->PMem.Limit          = 0;
> > +    RootBridge->PMemAbove4G.Base    = MAX_UINT64;
> > +    RootBridge->PMemAbove4G.Limit   = 0;
> > +
> > +    ASSERT (PcieController->PcieMmio64Translation == 0);
> > +    ASSERT (PcieController->PcieMmio32Translation == 0);
> > +
> > +    RootBridge->NoExtendedConfigSpace = FALSE;
> > +
> > +    RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath;
> > +  }
> > +
> > +  return PciRootBridges;
> > +}
> > +
> > +/**
> > +  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
> > +  )
> > +{
> > +  FreePool (Bridges);
> > +}
> > +
> > +/**
> > +  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;
> > +  UINTN                              RootBridgeIndex;
> > +
> > +  DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
> > +
> > +  RootBridgeIndex = 0;
> > +  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
>
> Drop space after "*)".
>
> > +
> > +  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> > +
> > +    DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
> > +
> > +    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""));
>
> This ternary is quite an effort to parse. I think a temporary
> variable for the retult of the & operation would improve this
> substantially.
>
> Alternatively, the wrapping and indentation used in
> Silicon/Socionext/SynQuacer/Library/SynQuacerPciHostBridgeLib/SynQuacerPciHostBridgeLib.c
> is a lot easier to read.
>
> > +      }
> > +    }
> > +    /* 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);
> > +  }
> > +}
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> > new file mode 100644
> > index 0000000..ced2c12
> > --- /dev/null
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> > @@ -0,0 +1,330 @@
> > +/** @file
> > +  PCI Host Bridge Library instance for Marvell 70x0/80x0
> > +
> > +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> > +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> > +
> > +  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 <PiDxe.h>
> > +
> > +#include <IndustryStandard/Pci22.h>
> > +
> > +#include <Library/ArmLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/IoLib.h>
> > +#include <Library/MvGpioLib.h>
> > +#include <Library/UefiBootServicesTableLib.h>
> > +
> > +#include <Protocol/BoardDesc.h>
> > +
> > +#include "PciHostBridgeLibConstructor.h"
> > +
> > +/**
> > +  This function configures PCIE controllers IATU windows.
> > +
> > +  @param [in] PcieBaseAddress PCIE controller base address.
> > +  @param [in] Index           IATU window index.
> > +  @param [in] CpuBase         Address from the CPU perspective.
> > +  @param [in] PciBase         Target PCIE address.
> > +  @param [in] Size            IATU window size.
> > +  @param [in] Type            IATU window type.
> > +  @param [in] EnableFlags     Extra configuration flags.
> > +
> > +  @retval none
> > +
> > +**/
> > +STATIC
> > +VOID
> > +ConfigureWindow (
> > +  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress,
> > +  IN UINTN                Index,
> > +  IN UINT64               CpuBase,
> > +  IN UINT64               PciBase,
> > +  IN UINT64               Size,
> > +  IN UINTN                Type,
> > +  IN UINTN                EnableFlags
> > +  )
> > +{
> > +  ArmDataMemoryBarrier ();
> > +
> > +  MmioWrite32 (PcieBaseAddress + IATU_VIEWPORT_OFF,
> > +    IATU_VIEWPORT_OUTBOUND | IATU_VIEWPORT_REGION_INDEX (Index));
> > +
> > +  ArmDataMemoryBarrier ();
> > +
> > +  MmioWrite32 (PcieBaseAddress + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
> > +    (UINT32)(CpuBase & 0xFFFFFFFF));
> > +  MmioWrite32 (PcieBaseAddress + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
> > +    (UINT32)(CpuBase >> 32));
> > +  MmioWrite32 (PcieBaseAddress + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
> > +    (UINT32)(CpuBase + Size - 1));
> > +  MmioWrite32 (PcieBaseAddress + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> > +    (UINT32)(PciBase & 0xFFFFFFFF));
> > +  MmioWrite32 (PcieBaseAddress + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
> > +    (UINT32)(PciBase >> 32));
> > +  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
> > +    Type);
> > +  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> > +    IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN | EnableFlags);
> > +}
> > +
> > +/**
> > +  Perform PCIE slot reset using external GPIO pin.
> > +
> > +  @param [in] PcieBaseAddress  PCIE controller base address.
> > +
> > +  @retval none
> > +
> > +**/
> > +STATIC
> > +VOID
> > +WaitForLink (
> > +  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress
> > +  )
> > +{
> > +  UINT32 Mask;
> > +  UINT32 Status;
> > +  UINT32 Timeout;
> > +
> > +  if (!(MmioRead32 (PcieBaseAddress + PCIE_PM_STATUS) & PCIE_PM_LTSSM_STAT_MASK)) {
> > +    DEBUG ((DEBUG_INIT, "%a: no PCIE device detected\n", __FUNCTION__));
> > +    return;
> > +  }
> > +
> > +  /* Wait for the link to establish itself */
> > +  DEBUG ((DEBUG_INIT, "%a: waiting for PCIE link\n", __FUNCTION__));
> > +
> > +  Mask = PCIE_GLOBAL_STATUS_RDLH_LINK_UP | PCIE_GLOBAL_STATUS_PHY_LINK_UP;
> > +  Timeout = PCIE_LINK_UP_TIMEOUT_US / 10;
> > +  do {
> > +    Status = MmioRead32 (PcieBaseAddress + PCIE_GLOBAL_STATUS_REG);
> > +    if ((Status & Mask) == Mask) {
> > +      DEBUG ((DEBUG_ERROR, "pcie@0x%x link UP\n", PcieBaseAddress));
> > +      break;
> > +    }
> > +    gBS->Stall (10);
>
> Why this Stall?
> Do we need a MemoryFence ()?

The stall is added in order to not to poll the link status too often
in the loop. I will add a comment.

>
> > +  } while (Timeout--);
> > +}
> > +
> > +/**
> > +  Perform PCIE slot reset using external GPIO pin.
> > +
> > +  @param [in] *PcieResetGpio  GPIO pin description.
> > +
> > +  @retval EFI_SUCEESS         PCIE slot reset succeeded.
> > +  @retval Other               Return error status.
> > +
> > +**/
> > +STATIC
> > +EFI_STATUS
> > +ResetPcieSlot (
> > +  IN MV_GPIO_PIN *PcieResetGpio
> > +  )
> > +{
> > +  EMBEDDED_GPIO_MODE   Mode;
> > +  EMBEDDED_GPIO_PIN    GpioPin;
> > +  EMBEDDED_GPIO       *GpioProtocol;
> > +  EFI_STATUS           Status;
> > +
> > +  /* Get GPIO protocol */
> > +  Status = MvGpioGetProtocol (PcieResetGpio->ControllerType, &GpioProtocol);
> > +  if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR, "%a: Unable to find GPIO protocol\n", __FUNCTION__));
> > +    return Status;
> > +  }
> > +
> > +  GpioPin = GPIO (PcieResetGpio->ControllerId, PcieResetGpio->PinNumber),
> > +
> > +  /* Reset the slot by toggling the GPIO pin */
> > +  Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_1 : GPIO_MODE_OUTPUT_0;
> > +  Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode);
> > +  gBS->Stall (10 * 1000);
>
> Why this Stall?
> Do we need a MemoryFence ()?
>
> > +
> > +  Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_0 : GPIO_MODE_OUTPUT_1;
> > +  Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode);
> > +  gBS->Stall (20 * 1000);
>
> Why this Stall?
> Do we need a MemoryFence ()?
>

I will add memory fence and add comments around stalls for justification.

Best regards,
Marcin

> /
>     Leif
>
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Obtain resources and perform a low-level PCIE controllers
> > +  configuration.
> > +
> > +  @param [in]  ImageHandle  The image handle.
> > +  @param [in] *SystemTable  The system table.
> > +
> > +  @retval EFI_SUCEESS       PCIE configuration successful.
> > +  @retval Other             Return error status.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +Armada7k8kPciHostBridgeLibConstructor (
> > +  IN EFI_HANDLE       ImageHandle,
> > +  IN EFI_SYSTEM_TABLE *SystemTable
> > +  )
> > +{
> > +  MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol;
> > +  MV_BOARD_PCIE_DESCRIPTION   *BoardPcieDescription;
> > +  MV_PCIE_CONTROLLER          *PcieController;
> > +  EFI_PHYSICAL_ADDRESS         PcieBaseAddress;
> > +  EFI_STATUS                   Status;
> > +  UINTN                        Index;
> > +
> > +  /* Obtain list of available controllers */
> > +  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
> > +                  NULL,
> > +                  (VOID **)&BoardDescriptionProtocol);
> > +  if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR,
> > +      "%a: Cannot locate BoardDesc protocol\n",
> > +      __FUNCTION__));
> > +    return EFI_DEVICE_ERROR;
> > +  }
> > +
> > +  Status = BoardDescriptionProtocol->PcieDescriptionGet (
> > +                                       BoardDescriptionProtocol,
> > +                                       &BoardPcieDescription);
> > +  if (Status == EFI_NOT_FOUND) {
> > +    /* No controllers used on the platform, exit silently */
> > +    return EFI_SUCCESS;
> > +  } else if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR,
> > +      "%a: Cannot get Pcie board desc from BoardDesc protocol\n",
> > +      __FUNCTION__));
> > +    return EFI_DEVICE_ERROR;
> > +  }
> > +
> > +  for (Index = 0; Index < BoardPcieDescription->PcieControllerCount; Index++) {
> > +
> > +    PcieController = &(BoardPcieDescription->PcieControllers[Index]);
> > +
> > +    ASSERT (PcieController->PcieBusMin == 0);
> > +    ASSERT (PcieController->ConfigSpaceAddress % SIZE_256MB == 0);
> > +
> > +    if (PcieController->HaveResetGpio == TRUE) {
> > +      /* Reset PCIE slot */
> > +      Status = ResetPcieSlot (&PcieController->PcieResetGpio);
> > +      if (EFI_ERROR (Status)) {
> > +        DEBUG ((DEBUG_ERROR,
> > +          "%a: Cannot reset Pcie Slot\n",
> > +          __FUNCTION__));
> > +        return EFI_DEVICE_ERROR;
> > +      }
> > +    }
> > +
> > +    /* Low level PCIE controller configuration */
> > +    PcieBaseAddress = PcieController->PcieBaseAddress;
> > +
> > +    MmioAndThenOr32 (PcieBaseAddress + PORT_LINK_CTRL_OFF,
> > +      ~PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK,
> > +      PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4);
> > +
> > +    MmioAndThenOr32 (PcieBaseAddress + GEN2_CTRL_OFF,
> > +      ~GEN2_CTRL_OFF_NUM_OF_LANES_MASK,
> > +      GEN2_CTRL_OFF_NUM_OF_LANES(4) | GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE);
> > +
> > +    MmioAndThenOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET,
> > +      ~(PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK | PCIE_GLOBAL_APP_LTSSM_EN),
> > +      PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC);
> > +
> > +    MmioWrite32 (PcieBaseAddress + PCIE_ARCACHE_TRC_REG,
> > +      ARCACHE_DEFAULT_VALUE);
> > +
> > +    MmioWrite32 (PcieBaseAddress + PCIE_AWCACHE_TRC_REG,
> > +      AWCACHE_DEFAULT_VALUE);
> > +
> > +    MmioAndThenOr32 (PcieBaseAddress + PCIE_ARUSER_REG,
> > +      ~AX_USER_DOMAIN_MASK,
> > +      AX_USER_DOMAIN_OUTER_SHAREABLE);
> > +
> > +    MmioAndThenOr32 (PcieBaseAddress + PCIE_AWUSER_REG,
> > +      ~AX_USER_DOMAIN_MASK,
> > +      AX_USER_DOMAIN_OUTER_SHAREABLE);
> > +
> > +    MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CTL_2,
> > +      ~TARGET_LINK_SPEED_MASK,
> > +      LINK_SPEED_GEN_3);
> > +
> > +    MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CAPABILITY,
> > +      ~TARGET_LINK_SPEED_MASK,
> > +      LINK_SPEED_GEN_3);
> > +
> > +    MmioOr32 (PcieBaseAddress + PCIE_GEN3_EQU_CTRL,
> > +      GEN3_EQU_EVAL_2MS_DISABLE);
> > +
> > +    MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET,
> > +      PCIE_GLOBAL_APP_LTSSM_EN);
> > +
> > +    /* Region 0: MMIO32 range */
> > +    ConfigureWindow (PcieBaseAddress,
> > +      0,
> > +      PcieController->PcieMmio32WinBase,
> > +      PcieController->PcieMmio32WinBase,
> > +      PcieController->PcieMmio32WinSize,
> > +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> > +      0);
> > +
> > +    /* Region 1: Type 0 config space */
> > +    ConfigureWindow (PcieBaseAddress,
> > +      1,
> > +      PcieController->ConfigSpaceAddress,
> > +      0x0,
> > +      SIZE_64KB,
> > +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0,
> > +      IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
> > +
> > +    /* Region 2: Type 1 config space */
> > +    ConfigureWindow (PcieBaseAddress,
> > +      2,
> > +      PcieController->ConfigSpaceAddress + SIZE_64KB,
> > +      0x0,
> > +      PcieController->PcieBusMax * SIZE_1MB,
> > +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1,
> > +      IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
> > +
> > +    /* Region 3: port I/O range */
> > +    ConfigureWindow (PcieBaseAddress,
> > +      3,
> > +      PcieController->PcieIoTranslation,
> > +      PcieController->PcieIoWinBase,
> > +      PcieController->PcieIoWinSize,
> > +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO,
> > +      0);
> > +
> > +    /* Region 4: MMIO64 range */
> > +    ConfigureWindow (PcieBaseAddress,
> > +      4,
> > +      PcieController->PcieMmio64WinBase,
> > +      PcieController->PcieMmio64WinBase,
> > +      PcieController->PcieMmio64WinSize,
> > +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> > +      0);
> > +
> > +    MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_INT_MASK1_REG,
> > +      PCIE_INT_A_ASSERT_MASK |
> > +      PCIE_INT_B_ASSERT_MASK |
> > +      PCIE_INT_C_ASSERT_MASK |
> > +      PCIE_INT_D_ASSERT_MASK);
> > +
> > +    WaitForLink (PcieBaseAddress);
> > +
> > +    /* Enable the RC */
> > +    MmioOr32 (PcieBaseAddress + PCI_COMMAND_OFFSET,
> > +      EFI_PCI_COMMAND_IO_SPACE |
> > +      EFI_PCI_COMMAND_MEMORY_SPACE |
> > +      EFI_PCI_COMMAND_BUS_MASTER);
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > --
> > 2.7.4
> >

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 05/14] Marvell/Armada7k8k: MvBoardDesc: Extend protocol with PCIE support
  2019-05-09  9:53 ` [edk2-platforms: PATCH 05/14] Marvell/Armada7k8k: MvBoardDesc: Extend protocol with PCIE support Marcin Wojtas
@ 2019-05-16 13:53   ` Ard Biesheuvel
  0 siblings, 0 replies; 36+ messages in thread
From: Ard Biesheuvel @ 2019-05-16 13:53 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: edk2-devel-groups-io, Leif Lindholm, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	kettenis

On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
>
> Introduce new callback that can provide information about PCIE
> controllers, which are used on the platform. According ArmadaSoCDescLib
> ArmadaBoardDescLib routines are used for obtaining required data.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Include/Protocol/BoardDesc.h       | 22 +++++
>  Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c | 86 ++++++++++++++++++++
>  2 files changed, 108 insertions(+)
>
> diff --git a/Silicon/Marvell/Include/Protocol/BoardDesc.h b/Silicon/Marvell/Include/Protocol/BoardDesc.h
> index 02905ea..c38ad86 100644
> --- a/Silicon/Marvell/Include/Protocol/BoardDesc.h
> +++ b/Silicon/Marvell/Include/Protocol/BoardDesc.h
> @@ -90,6 +90,27 @@ EFI_STATUS
>    IN OUT MV_BOARD_XHCI_DESC      **XhciDesc
>    );
>
> +/**
> +  Return the description of PCIE controllers used on the platform.
> +
> +  @param[in out]  *This                 Pointer to board description protocol.
> +  @param[in out] **PcieDescription      Array containing PCIE controllers'
> +                                        description.
> +
> +  @retval EFI_SUCCESS                   The data were obtained successfully.
> +  @retval EFI_NOT_FOUND                 None of the controllers is used.
> +  @retval EFI_INVALID_PARAMETER         Description wrongly defined.
> +  @retval EFI_OUT_OF_RESOURCES          Lack of resources.
> +  @retval Other                         Return error status.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *MV_BOARD_PCIE_DESCRIPTION_GET) (
> +  IN MARVELL_BOARD_DESC_PROTOCOL     *This,
> +  IN OUT MV_BOARD_PCIE_DESCRIPTION  **PcieDescription
> +  );
> +
>  typedef
>  EFI_STATUS
>  (EFIAPI *MV_BOARD_DESC_PP2_GET) (
> @@ -121,6 +142,7 @@ struct _MARVELL_BOARD_DESC_PROTOCOL {
>    MV_BOARD_DESC_XHCI_GET         BoardDescXhciGet;
>    MV_BOARD_DESC_FREE             BoardDescFree;
>    MV_BOARD_GPIO_DESCRIPTION_GET  GpioDescriptionGet;
> +  MV_BOARD_PCIE_DESCRIPTION_GET  PcieDescriptionGet;
>  };
>
>  #endif // __MARVELL_BOARD_DESC_PROTOCOL_H__
> diff --git a/Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c b/Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c
> index 973c362..9cd95bd 100644
> --- a/Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c
> +++ b/Silicon/Marvell/Drivers/BoardDesc/MvBoardDescDxe.c
> @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>  MV_BOARD_DESC *mBoardDescInstance;
>
>  STATIC MV_BOARD_GPIO_DESCRIPTION *mGpioDescription;
> +STATIC MV_BOARD_PCIE_DESCRIPTION *mPcieDescription;
>
>  STATIC
>  EFI_STATUS
> @@ -444,6 +445,90 @@ MvBoardDescXhciGet (
>    return EFI_SUCCESS;
>  }
>
> +/**
> +  Return the description of PCIE controllers used on the platform.
> +
> +  @param[in out]  *This                 Pointer to board description protocol.
> +  @param[in out] **PcieDescription      Array containing PCIE controllers'
> +                                        description.
> +
> +  @retval EFI_SUCCESS                   The data were obtained successfully.
> +  @retval EFI_NOT_FOUND                 None of the controllers is used.
> +  @retval EFI_INVALID_PARAMETER         Description wrongly defined.
> +  @retval EFI_OUT_OF_RESOURCES          Lack of resources.
> +  @retval Other                         Return error status.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +MvBoardPcieDescriptionGet (
> +  IN MARVELL_BOARD_DESC_PROTOCOL    *This,
> +  IN OUT MV_BOARD_PCIE_DESCRIPTION **PcieDescription
> +  )
> +{
> +  UINTN SoCPcieControllerCount, BoardPcieControllerCount, SoCIndex, BoardIndex;
> +  EFI_PHYSICAL_ADDRESS *PcieBaseAddresses;
> +  MV_PCIE_CONTROLLER *PcieControllers;
> +  EFI_STATUS Status;
> +
> +  /* Use existing structure if already created. */
> +  if (mPcieDescription != NULL) {
> +    *PcieDescription = mPcieDescription;

Since you are returning a cached copy here, I'd prefer it if the
prototype of the OUT parameter was MV_BOARD_PCIE_DESCRIPTION CONST**
rather than MV_BOARD_PCIE_DESCRIPTION**, since now, you are returning
a pointer to internal state of this driver.
(I guess this might apply to other methods as well)

> +    return EFI_SUCCESS;
> +  }
> +
> +  /* Get SoC data about all available PCIE controllers. */
> +  Status = ArmadaSoCPcieGet (&PcieBaseAddresses, &SoCPcieControllerCount);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  /* Get per-board information about all used PCIE controllers. */
> +  Status = ArmadaBoardPcieControllerGet (&PcieControllers,
> +             &BoardPcieControllerCount);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  /* Sanity check of the board description. */
> +  if (BoardPcieControllerCount > SoCPcieControllerCount) {
> +    DEBUG ((DEBUG_ERROR, "%a: Too many controllers described\n", __FUNCTION__));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  for (BoardIndex = 0; BoardIndex < BoardPcieControllerCount; BoardIndex++) {
> +    for (SoCIndex = 0; SoCIndex < SoCPcieControllerCount; SoCIndex++) {
> +      if (PcieControllers[BoardIndex].PcieBaseAddress ==
> +          PcieBaseAddresses[SoCIndex]) {
> +          /* Match found */
> +          break;
> +      }
> +    }
> +    if (SoCIndex == SoCPcieControllerCount) {
> +      DEBUG ((DEBUG_ERROR,
> +        "%a: Controller #%d base address invalid: 0x%x\n",
> +        __FUNCTION__,
> +        BoardIndex,
> +        PcieControllers[BoardIndex].PcieBaseAddress));
> +      return EFI_INVALID_PARAMETER;
> +    }
> +  }
> +
> +  /* Allocate and fill board description. */
> +  mPcieDescription = AllocateZeroPool (sizeof (MV_BOARD_PCIE_DESCRIPTION));
> +  if (mPcieDescription == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  mPcieDescription->PcieControllers = PcieControllers;
> +  mPcieDescription->PcieControllerCount = BoardPcieControllerCount;
> +
> +  *PcieDescription = mPcieDescription;
> +
> +  return EFI_SUCCESS;
> +}
> +
>  STATIC
>  EFI_STATUS
>  MvBoardDescPp2Get (
> @@ -621,6 +706,7 @@ MvBoardDescInitProtocol (
>    BoardDescProtocol->BoardDescXhciGet = MvBoardDescXhciGet;
>    BoardDescProtocol->BoardDescFree = MvBoardDescFree;
>    BoardDescProtocol->GpioDescriptionGet = MvBoardGpioDescriptionGet;
> +  BoardDescProtocol->PcieDescriptionGet = MvBoardPcieDescriptionGet;
>
>    return EFI_SUCCESS;
>  }
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 03/14] Marvell/Library: ArmadaBoardDescLib: Add PCIE information
  2019-05-09  9:53 ` [edk2-platforms: PATCH 03/14] Marvell/Library: ArmadaBoardDescLib: " Marcin Wojtas
@ 2019-05-16 13:57   ` Ard Biesheuvel
  0 siblings, 0 replies; 36+ messages in thread
From: Ard Biesheuvel @ 2019-05-16 13:57 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: edk2-devel-groups-io, Leif Lindholm, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	kettenis

On Thu, 9 May 2019 at 11:53, Marcin Wojtas <mw@semihalf.com> wrote:
>
> Introduce new callback that can provide information
> about PCIE controller per-board description.
> A new structure is defined containing base addresses,
> windows/bus configuration and reset GPIO usage indication.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h | 46 ++++++++++++++++++++
>  1 file changed, 46 insertions(+)
>
> diff --git a/Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h b/Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h
> index 6ec5ace..530a2ba 100644
> --- a/Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h
> +++ b/Silicon/Marvell/Include/Library/ArmadaBoardDescLib.h
> @@ -15,6 +15,7 @@
>  #define __ARMADA_BOARD_DESC_LIB_H__
>
>  #include <Library/ArmadaSoCDescLib.h>
> +#include <Library/MvGpioLib.h>
>
>  //
>  // COMPHY controllers per-board description
> @@ -111,6 +112,51 @@ typedef struct {
>  } MV_BOARD_XHCI_DESC;
>
>  //
> +// PCIE controllers description
> +//
> +typedef struct {
> +  EFI_PHYSICAL_ADDRESS PcieBaseAddress;
> +  EFI_PHYSICAL_ADDRESS ConfigSpaceAddress;

In EDK2, the PCIe base address is usually the ECAM base address, not
the address of the DBI interface (which is not standardized by PCIe).
So you can either avoid 'base' entirely, and use Dbi and Ecam/Config,
or you can use 'base' for the latter, but not for the former.

> +  BOOLEAN HaveResetGpio;
> +  MV_GPIO_PIN PcieResetGpio;
> +  UINT64 PcieBusMin;
> +  UINT64 PcieBusMax;
> +  UINT64 PcieIoTranslation;
> +  UINT64 PcieIoWinBase;
> +  UINT64 PcieIoWinSize;
> +  UINT64 PcieMmio32Translation;
> +  UINT64 PcieMmio32WinBase;
> +  UINT64 PcieMmio32WinSize;
> +  UINT64 PcieMmio64Translation;
> +  UINT64 PcieMmio64WinBase;
> +  UINT64 PcieMmio64WinSize;
> +} MV_PCIE_CONTROLLER;
> +
> +typedef struct {
> +  MV_PCIE_CONTROLLER *PcieControllers;
> +  UINTN               PcieControllerCount;
> +} MV_BOARD_PCIE_DESCRIPTION;
> +
> +/**
> +  Return the number and description of PCIE controllers used on the platform.
> +
> +  @param[in out] **PcieControllers      Array containing PCIE controllers'
> +                                        description.
> +  @param[in out]  *PcieControllerCount  Amount of used PCIE controllers.
> +
> +  @retval EFI_SUCCESS                   The data were obtained successfully.
> +  @retval EFI_NOT_FOUND                 None of the controllers is used.
> +  @retval other                         Return error status.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArmadaBoardPcieControllerGet (
> +  IN OUT MV_PCIE_CONTROLLER **PcieControllers,

Make this MV_PCIE_CONTROLLER CONST** if you can.

> +  IN OUT UINTN               *PcieControllerCount
> +  );
> +
> +//
>  // PP2 NIC devices per-board description
>  //
>  typedef struct {
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation
  2019-05-09  9:53 ` [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation Marcin Wojtas
  2019-05-10 15:25   ` Leif Lindholm
@ 2019-05-16 14:02   ` Ard Biesheuvel
  2019-05-16 14:26     ` Marcin Wojtas
  1 sibling, 1 reply; 36+ messages in thread
From: Ard Biesheuvel @ 2019-05-16 14:02 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: edk2-devel-groups-io, Leif Lindholm, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	kettenis

On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
>
> From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>
> Implement a special version of PciExpressLib that takes the quirky
> nature of the Synopsys Designware PCIe IP into account. In particular,
> we need to ignores config space accesses to all devices on the first

ignore


> bus except device 0, because the broadcast nature of type 0 configuration
> cycles will result in whatever device is in the slot to appear at each
> of the 32 device positions.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf |   42 +
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c   | 1529 ++++++++++++++++++++
>  2 files changed, 1571 insertions(+)
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
>
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> new file mode 100644
> index 0000000..8f09820
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> @@ -0,0 +1,42 @@
> +## @file
> +#
> +#  Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
> +#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +#
> +#  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                    = 0x0001001B
> +  BASE_NAME                      = Armada7k8kPciExpressLib
> +  FILE_GUID                      = f0926204-3061-40ed-8261-2aeccc7914c9
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciExpressLib
> +
> +[Sources]
> +  PciExpressLib.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  DebugLib
> +  IoLib
> +  PcdLib
> +
> +[Pcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress  ## CONSUMES
> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdPciBusMin
> +  gArmTokenSpaceGuid.PcdPciBusMax
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> new file mode 100644
> index 0000000..8fa2eb6
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> @@ -0,0 +1,1529 @@
> +/** @file
> +
> +  Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  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 <Base.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciExpressLib.h>
> +
> +/**
> +  Assert the validity of a PCI address. A valid PCI address should contain 1's
> +  only in the low 28 bits.
> +
> +  @param  A The address to validate.
> +
> +**/
> +#define ASSERT_INVALID_PCI_ADDRESS(A) \
> +  ASSERT (((A) & ~0xfffffff) == 0)
> +
> +/**
> +  Registers a PCI device so PCI configuration registers may be accessed after
> +  SetVirtualAddressMap().
> +
> +  Registers the PCI device specified by Address so all the PCI configuration
> +  registers associated with that PCI device may be accessed after SetVirtualAddressMap()
> +  is called.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @retval RETURN_SUCCESS           The PCI device was registered for runtime access.
> +  @retval RETURN_UNSUPPORTED       An attempt was made to call this function
> +                                   after ExitBootServices().
> +  @retval RETURN_UNSUPPORTED       The resources required to access the PCI device
> +                                   at runtime could not be mapped.
> +  @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
> +                                   complete the registration.
> +
> +**/
> +RETURN_STATUS
> +EFIAPI
> +PciExpressRegisterForRuntimeAccess (
> +  IN UINTN  Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  return RETURN_UNSUPPORTED;
> +}
> +
> +#define ECAM_BUS_SIZE       SIZE_1MB
> +#define ECAM_DEV_SIZE       SIZE_32KB
> +
> +STATIC
> +BOOLEAN
> +IgnoreBusDeviceFunction (
> +  IN  UINTN   Address
> +  )
> +{
> +  ASSERT (Address >= FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE);
> +  ASSERT (Address < (FixedPcdGet32 (PcdPciBusMax) + 1) * ECAM_BUS_SIZE);
> +
> +  //
> +  // Type 0 configuration cycles don't contain a b/d/f specifier, and so it
> +  // is up to the bus that delivers them to ensure they only end up at the
> +  // correct device/function. Sadly, the Synopsys IP does not implement this,
> +  // and so we have to ignore config space accesses for all devices on the
> +  // first bus except device 0.
> +  //

This is not entirely true. Type 0 PCIe config TLPs (as opposed to
legacy PCI bus cycles) do contain b/d/f specifiers, but the endpoint
doesn't know its own device number, and so it responds to all of them.

> +  return (Address >= (FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE +
> +                      ECAM_DEV_SIZE) &&
> +          Address < (FixedPcdGet32 (PcdPciBusMin) + 1) * ECAM_BUS_SIZE);
> +}
> +
> +/**
> +  Gets the base address of PCI Express.
> +
> +  This internal functions retrieves PCI Express Base Address via a PCD entry
> +  PcdPciExpressBaseAddress.
> +
> +  @return The base address of PCI Express.
> +
> +**/
> +VOID*
> +GetPciExpressBaseAddress (
> +  VOID
> +  )
> +{
> +  return (VOID*)(UINTN) PcdGet64 (PcdPciExpressBaseAddress);
> +}
> +
> +/**
> +  Reads an 8-bit PCI configuration register.
> +
> +  Reads and returns the 8-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @return The read value from the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressRead8 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
> +}
> +
> +/**
> +  Writes an 8-bit PCI configuration register.
> +
> +  Writes the 8-bit PCI configuration register specified by Address with the
> +  value specified by Value. Value is returned. This function must guarantee
> +  that all PCI read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  Value   The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressWrite8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of an 8-bit PCI configuration register with
> +  an 8-bit value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 8-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> +  value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 8-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressAnd8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> +  value, followed a  bitwise OR with another 8-bit value.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and
> +  the value specified by OrData, and writes the result to the 8-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressAndThenOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINT8                     AndData,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioAndThenOr8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in an 8-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to read.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldRead8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldRead8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit
> +           );
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  8-bit register is returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldWrite8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldWrite8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           Value
> +           );
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 8-bit port.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 8-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldOr8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 8-bit register.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 8-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldAnd8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldAnd8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  8-bit port.
> +
> +  Reads the 8-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 8-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If StartBit is greater than 7, then ASSERT().
> +  If EndBit is greater than 7, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..7.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..7.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +  @param  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT8
> +EFIAPI
> +PciExpressBitFieldAndThenOr8 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT8                     AndData,
> +  IN      UINT8                     OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xff;
> +  }
> +  return MmioBitFieldAndThenOr8 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a 16-bit PCI configuration register.
> +
> +  Reads and returns the 16-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @return The read value from the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressRead16 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
> +}
> +
> +/**
> +  Writes a 16-bit PCI configuration register.
> +
> +  Writes the 16-bit PCI configuration register specified by Address with the
> +  value specified by Value. Value is returned. This function must guarantee
> +  that all PCI read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  Value   The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressWrite16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of a 16-bit PCI configuration register with
> +  a 16-bit value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 16-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> +  value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 16-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressAnd16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> +  value, followed a  bitwise OR with another 16-bit value.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and
> +  the value specified by OrData, and writes the result to the 16-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressAndThenOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioAndThenOr16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in a 16-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to read.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldRead16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldRead16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit
> +           );
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  16-bit register is returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldWrite16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldWrite16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           Value
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 16-bit port.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 16-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldOr16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 16-bit register.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 16-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldAnd16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldAnd16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  16-bit port.
> +
> +  Reads the 16-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 16-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +  If StartBit is greater than 15, then ASSERT().
> +  If EndBit is greater than 15, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..15.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..15.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +  @param  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT16
> +EFIAPI
> +PciExpressBitFieldAndThenOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT16                    AndData,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffff;
> +  }
> +  return MmioBitFieldAndThenOr16 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a 32-bit PCI configuration register.
> +
> +  Reads and returns the 32-bit PCI configuration register specified by Address.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +
> +  @return The read value from the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressRead32 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address);
> +}
> +
> +/**
> +  Writes a 32-bit PCI configuration register.
> +
> +  Writes the 32-bit PCI configuration register specified by Address with the
> +  value specified by Value. Value is returned. This function must guarantee
> +  that all PCI read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  Value   The value to write.
> +
> +  @return The value written to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressWrite32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> +}
> +
> +/**
> +  Performs a bitwise OR of a 32-bit PCI configuration register with
> +  a 32-bit value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 32-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  OrData  The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> +  value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 32-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressAnd32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> +}
> +
> +/**
> +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> +  value, followed a  bitwise OR with another 32-bit value.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData,
> +  performs a bitwise OR between the result of the AND operation and
> +  the value specified by OrData, and writes the result to the 32-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The address that encodes the PCI Bus, Device, Function and
> +                  Register.
> +  @param  AndData The value to AND with the PCI configuration register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressAndThenOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioAndThenOr32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field of a PCI configuration register.
> +
> +  Reads the bit field in a 32-bit PCI configuration register. The bit field is
> +  specified by the StartBit and the EndBit. The value of the bit field is
> +  returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to read.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +
> +  @return The value of the bit field read from the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldRead32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldRead32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit
> +           );
> +}
> +
> +/**
> +  Writes a bit field to a PCI configuration register.
> +
> +  Writes Value to the bit field of the PCI configuration register. The bit
> +  field is specified by the StartBit and the EndBit. All other bits in the
> +  destination PCI configuration register are preserved. The new value of the
> +  32-bit register is returned.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  Value     The new value of the bit field.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldWrite32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    Value
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldWrite32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           Value
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
> +  writes the result back to the bit field in the 32-bit port.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise OR between the read result and the value specified by
> +  OrData, and writes the result to the 32-bit PCI configuration register
> +  specified by Address. The value written to the PCI configuration register is
> +  returned. This function must guarantee that all PCI read and write operations
> +  are serialized. Extra left bits in OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  OrData    The value to OR with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldOr32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
> +  AND, and writes the result back to the bit field in the 32-bit register.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND between the read result and the value specified by AndData, and
> +  writes the result to the 32-bit PCI configuration register specified by
> +  Address. The value written to the PCI configuration register is returned.
> +  This function must guarantee that all PCI read and write operations are
> +  serialized. Extra left bits in AndData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldAnd32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    AndData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldAnd32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData
> +           );
> +}
> +
> +/**
> +  Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
> +  bitwise OR, and writes the result back to the bit field in the
> +  32-bit port.
> +
> +  Reads the 32-bit PCI configuration register specified by Address, performs a
> +  bitwise AND followed by a bitwise OR between the read result and
> +  the value specified by AndData, and writes the result to the 32-bit PCI
> +  configuration register specified by Address. The value written to the PCI
> +  configuration register is returned. This function must guarantee that all PCI
> +  read and write operations are serialized. Extra left bits in both AndData and
> +  OrData are stripped.
> +
> +  If Address > 0x0FFFFFFF, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +  If StartBit is greater than 31, then ASSERT().
> +  If EndBit is greater than 31, then ASSERT().
> +  If EndBit is less than StartBit, then ASSERT().
> +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> +
> +  @param  Address   The PCI configuration register to write.
> +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> +                    Range 0..31.
> +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> +                    Range 0..31.
> +  @param  AndData   The value to AND with the PCI configuration register.
> +  @param  OrData    The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the PCI configuration register.
> +
> +**/
> +UINT32
> +EFIAPI
> +PciExpressBitFieldAndThenOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINTN                     StartBit,
> +  IN      UINTN                     EndBit,
> +  IN      UINT32                    AndData,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  ASSERT_INVALID_PCI_ADDRESS (Address);
> +  if (IgnoreBusDeviceFunction (Address)) {
> +    return 0xffffffff;
> +  }
> +  return MmioBitFieldAndThenOr32 (
> +           (UINTN) GetPciExpressBaseAddress () + Address,
> +           StartBit,
> +           EndBit,
> +           AndData,
> +           OrData
> +           );
> +}
> +
> +/**
> +  Reads a range of PCI configuration registers into a caller supplied buffer.
> +
> +  Reads the range of PCI configuration registers specified by StartAddress and
> +  Size into the buffer specified by Buffer. This function only allows the PCI
> +  configuration registers from a single PCI function to be read. Size is
> +  returned. When possible 32-bit PCI configuration read cycles are used to read
> +  from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit
> +  and 16-bit PCI configuration read cycles may be used at the beginning and the
> +  end of the range.
> +
> +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> +  If Size > 0 and Buffer is NULL, then ASSERT().
> +
> +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> +                        Function and Register.
> +  @param  Size          The size in bytes of the transfer.
> +  @param  Buffer        The pointer to a buffer receiving the data read.
> +
> +  @return Size read data from StartAddress.
> +
> +**/
> +UINTN
> +EFIAPI
> +PciExpressReadBuffer (
> +  IN      UINTN                     StartAddress,
> +  IN      UINTN                     Size,
> +  OUT     VOID                      *Buffer
> +  )
> +{
> +  UINTN   ReturnValue;
> +
> +  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
> +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> +
> +  if (Size == 0) {
> +    return Size;
> +  }
> +
> +  ASSERT (Buffer != NULL);
> +
> +  //
> +  // Save Size for return
> +  //
> +  ReturnValue = Size;
> +
> +  if ((StartAddress & 1) != 0) {
> +    //
> +    // Read a byte if StartAddress is byte aligned
> +    //
> +    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
> +    StartAddress += sizeof (UINT8);
> +    Size -= sizeof (UINT8);
> +    Buffer = (UINT8*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
> +    //
> +    // Read a word if StartAddress is word aligned
> +    //
> +    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
> +
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + 1;
> +  }
> +
> +  while (Size >= sizeof (UINT32)) {
> +    //
> +    // Read as many double words as possible
> +    //
> +    WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress));
> +
> +    StartAddress += sizeof (UINT32);
> +    Size -= sizeof (UINT32);
> +    Buffer = (UINT32*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16)) {
> +    //
> +    // Read the last remaining word if exist
> +    //
> +    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT8)) {
> +    //
> +    // Read the last remaining byte if exist
> +    //
> +    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
> +  }
> +
> +  return ReturnValue;
> +}
> +
> +/**
> +  Copies the data in a caller supplied buffer to a specified range of PCI
> +  configuration space.
> +
> +  Writes the range of PCI configuration registers specified by StartAddress and
> +  Size from the buffer specified by Buffer. This function only allows the PCI
> +  configuration registers from a single PCI function to be written. Size is
> +  returned. When possible 32-bit PCI configuration write cycles are used to
> +  write from StartAddress to StartAddress + Size. Due to alignment restrictions,
> +  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
> +  and the end of the range.
> +
> +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> +  If Size > 0 and Buffer is NULL, then ASSERT().
> +
> +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> +                        Function and Register.
> +  @param  Size          The size in bytes of the transfer.
> +  @param  Buffer        The pointer to a buffer containing the data to write.
> +
> +  @return Size written to StartAddress.
> +
> +**/
> +UINTN
> +EFIAPI
> +PciExpressWriteBuffer (
> +  IN      UINTN                     StartAddress,
> +  IN      UINTN                     Size,
> +  IN      VOID                      *Buffer
> +  )
> +{
> +  UINTN                             ReturnValue;
> +
> +  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
> +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> +
> +  if (Size == 0) {
> +    return 0;
> +  }
> +
> +  ASSERT (Buffer != NULL);
> +
> +  //
> +  // Save Size for return
> +  //
> +  ReturnValue = Size;
> +
> +  if ((StartAddress & 1) != 0) {
> +    //
> +    // Write a byte if StartAddress is byte aligned
> +    //
> +    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
> +    StartAddress += sizeof (UINT8);
> +    Size -= sizeof (UINT8);
> +    Buffer = (UINT8*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
> +    //
> +    // Write a word if StartAddress is word aligned
> +    //
> +    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + 1;
> +  }
> +
> +  while (Size >= sizeof (UINT32)) {
> +    //
> +    // Write as many double words as possible
> +    //
> +    PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
> +    StartAddress += sizeof (UINT32);
> +    Size -= sizeof (UINT32);
> +    Buffer = (UINT32*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT16)) {
> +    //
> +    // Write the last remaining word if exist
> +    //
> +    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + 1;
> +  }
> +
> +  if (Size >= sizeof (UINT8)) {
> +    //
> +    // Write the last remaining byte if exist
> +    //
> +    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
> +  }
> +
> +  return ReturnValue;
> +}
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib
  2019-05-09  9:53 ` [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib Marcin Wojtas
  2019-05-10 15:50   ` Leif Lindholm
@ 2019-05-16 14:14   ` Ard Biesheuvel
  1 sibling, 0 replies; 36+ messages in thread
From: Ard Biesheuvel @ 2019-05-16 14:14 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: edk2-devel-groups-io, Leif Lindholm, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	kettenis

On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
>
> Add an implementation of the PciHostBridgeLib glue library that
> describes the PCIe RC on this SoC so that the generic PCI host bridge
> driver can attach to it.
>
> This includes a constructor which performs the SoC specific init and
> training sequences.
>
> This patch is based on work of Ard Biesheuvel <ard.biesheuvel@linaro.org>
> and Jing Hua <jinghua@marvell.com>/
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf          |  52 +++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h |  95 ++++++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c            | 244 +++++++++++++++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c | 330 ++++++++++++++++++++
>  4 files changed, 721 insertions(+)
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
>
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> new file mode 100644
> index 0000000..e46f71d
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> @@ -0,0 +1,52 @@
> +## @file
> +#  PCI Host Bridge Library instance for Marvell Armada 7k/8k SOC
> +#
> +#  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +#
> +#  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                    = 0x0001001B
> +  BASE_NAME                      = Armada7k8kPciHostBridgeLib
> +  FILE_GUID                      = 7f989c9d-02a0-4348-8aeb-ab2e1566fb18
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciHostBridgeLib|DXE_DRIVER
> +  CONSTRUCTOR                    = Armada7k8kPciHostBridgeLibConstructor
> +
> +[Sources]
> +  PciHostBridgeLib.c
> +  PciHostBridgeLibConstructor.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Marvell/Marvell.dec
> +
> +[LibraryClasses]
> +  ArmLib
> +  ArmadaSoCDescLib
> +  DebugLib
> +  DevicePathLib
> +  MemoryAllocationLib
> +  MvGpioLib
> +  UefiBootServicesTableLib
> +
> +[Protocols]
> +  gEmbeddedGpioProtocolGuid
> +  gMarvellBoardDescProtocolGuid
> +
> +[Depex]
> +  gMarvellPlatformInitCompleteProtocolGuid
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> new file mode 100644
> index 0000000..ff9d919
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> @@ -0,0 +1,95 @@
> +/** @file
> +  PCI Host Bridge Library instance for Marvell 70x0/80x0
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  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 __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
> +#define __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
> +
> +#define IATU_VIEWPORT_OFF                                   0x900
> +#define IATU_VIEWPORT_INBOUND                               BIT31
> +#define IATU_VIEWPORT_OUTBOUND                              0
> +#define IATU_VIEWPORT_REGION_INDEX(Idx)                     ((Idx) & 7)
> +
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0                   0x904
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM          0x0
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO           0x2
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0         0x4
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1         0x5
> +
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0                   0x908
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN         BIT31
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE    BIT28
> +
> +#define IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0                   0x90C
> +#define IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0                 0x910
> +#define IATU_LIMIT_ADDR_OFF_OUTBOUND_0                      0x914
> +#define IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0                 0x918
> +#define IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0               0x91C
> +
> +#define PORT_LINK_CTRL_OFF                                  0x710
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x1                  (0x01 << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x2                  (0x03 << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4                  (0x07 << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x8                  (0x0f << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x16                 (0x1f << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK                (0x3f << 16)
> +
> +#define GEN2_CTRL_OFF                                       0x80c
> +#define GEN2_CTRL_OFF_NUM_OF_LANES(n)                       (((n) & 0x1f) << 8)
> +#define GEN2_CTRL_OFF_NUM_OF_LANES_MASK                     (0x1f << 8)
> +#define GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE                   BIT17
> +
> +#define PCIE_GLOBAL_CTRL_OFFSET                             0x8000
> +#define PCIE_GLOBAL_APP_LTSSM_EN                            BIT2
> +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC                     (0x4 << 4)
> +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK                   (0xF << 4)
> +
> +#define PCIE_GLOBAL_STATUS_REG                              0x8008
> +#define PCIE_GLOBAL_STATUS_RDLH_LINK_UP                     BIT1
> +#define PCIE_GLOBAL_STATUS_PHY_LINK_UP                      BIT9
> +
> +#define PCIE_PM_STATUS                                      0x8014
> +#define PCIE_PM_LTSSM_STAT_MASK                             (0x3f << 3)
> +
> +#define PCIE_GLOBAL_INT_MASK1_REG                           0x8020
> +#define PCIE_INT_A_ASSERT_MASK                              BIT9
> +#define PCIE_INT_B_ASSERT_MASK                              BIT10
> +#define PCIE_INT_C_ASSERT_MASK                              BIT11
> +#define PCIE_INT_D_ASSERT_MASK                              BIT12
> +
> +#define PCIE_ARCACHE_TRC_REG                                0x8050
> +#define PCIE_AWCACHE_TRC_REG                                0x8054
> +#define PCIE_ARUSER_REG                                     0x805C
> +#define PCIE_AWUSER_REG                                     0x8060
> +
> +#define ARCACHE_DEFAULT_VALUE                               0x3511
> +#define AWCACHE_DEFAULT_VALUE                               0x5311
> +
> +#define AX_USER_DOMAIN_INNER_SHAREABLE                      (0x1 << 4)
> +#define AX_USER_DOMAIN_OUTER_SHAREABLE                      (0x2 << 4)
> +#define AX_USER_DOMAIN_MASK                                 (0x3 << 4)
> +
> +#define PCIE_LINK_CAPABILITY                                0x7C
> +#define PCIE_LINK_CTL_2                                     0xA0
> +#define TARGET_LINK_SPEED_MASK                              0xF
> +#define LINK_SPEED_GEN_1                                    0x1
> +#define LINK_SPEED_GEN_2                                    0x2
> +#define LINK_SPEED_GEN_3                                    0x3
> +
> +#define PCIE_GEN3_EQU_CTRL                                  0x8A8
> +#define GEN3_EQU_EVAL_2MS_DISABLE                           BIT5
> +
> +#define PCIE_LINK_UP_TIMEOUT_US                             40000
> +
> +#endif
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
> new file mode 100644
> index 0000000..ff6288c
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
> @@ -0,0 +1,244 @@
> +/** @file
> +  PCI Host Bridge Library instance for Marvell Armada 70x0/80x0
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  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 <PiDxe.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/BoardDesc.h>
> +#include <Protocol/PciHostBridgeResourceAllocation.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +
> +#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 = {
> +  {
> +    {
> +      ACPI_DEVICE_PATH,
> +      ACPI_DP,
> +      {
> +        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
> +        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
> +      }
> +    },
> +    EISA_PNP_ID(0x0A08), // PCI Express
> +    0
> +  },
> +
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      END_DEVICE_PATH_LENGTH,
> +      0
> +    }
> +  }
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> +  L"Mem", L"I/O", L"Bus"
> +};
> +
> +/**
> +  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
> +  )
> +{
> +  MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol;
> +  MV_BOARD_PCIE_DESCRIPTION   *BoardPcieDescription;
> +  MV_PCIE_CONTROLLER          *PcieController;
> +  PCI_ROOT_BRIDGE             *PciRootBridges;
> +  PCI_ROOT_BRIDGE             *RootBridge;
> +  EFI_STATUS                   Status;
> +  UINTN                        Index;
> +
> +  *Count = 0;
> +
> +  /* Obtain list of available controllers */
> +  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
> +                  NULL,
> +                  (VOID **)&BoardDescriptionProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot locate BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  Status = BoardDescriptionProtocol->PcieDescriptionGet (
> +                                       BoardDescriptionProtocol,
> +                                       &BoardPcieDescription);
> +  if (Status == EFI_NOT_FOUND) {
> +    /* No controllers used on the platform, exit silently */
> +    return NULL;
> +  } else if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot get Pcie board desc from BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  /* Assign return values */
> +  PciRootBridges = AllocateZeroPool (BoardPcieDescription->PcieControllerCount *
> +                                     sizeof (PCI_ROOT_BRIDGE));
> +  if (PciRootBridges == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate resources\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  *Count = BoardPcieDescription->PcieControllerCount;
> +  RootBridge = PciRootBridges;
> +
> +  /* Fill information of all root bridge instances */
> +  for (Index = 0; Index < *Count; Index++, RootBridge++) {
> +
> +    PcieController = &(BoardPcieDescription->PcieControllers[Index]);
> +
> +    RootBridge->Segment   = 0;
> +    RootBridge->Supports  = 0;
> +    RootBridge->Attributes  = RootBridge->Supports;
> +
> +    RootBridge->DmaAbove4G  = FALSE;
> +
> +    RootBridge->AllocationAttributes  = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |
> +                                        EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
> +

IIRC you merged the 32-bit support for these platforms? If so, please
look at SynQuacer how to deal with PCIe support on 32-bit, since this
will break it otherwise. (TL;DR get rid of the 64-bit MMIO window when
building in ARM mode)

> +    RootBridge->Bus.Base = PcieController->PcieBusMin;
> +    RootBridge->Bus.Limit = PcieController->PcieBusMax;
> +    RootBridge->Io.Base = PcieController->PcieIoWinBase;
> +    RootBridge->Io.Limit = PcieController->PcieIoWinBase +
> +                           PcieController->PcieIoWinSize - 1;
> +    RootBridge->Mem.Base = PcieController->PcieMmio32WinBase;
> +    RootBridge->Mem.Limit = PcieController->PcieMmio32WinBase +
> +                            PcieController->PcieMmio32WinSize - 1;
> +    RootBridge->MemAbove4G.Base = PcieController->PcieMmio64WinBase;
> +    RootBridge->MemAbove4G.Limit = PcieController->PcieMmio64WinBase +
> +                                   PcieController->PcieMmio64WinSize - 1;
> +
> +    /* No separate ranges for prefetchable and non-prefetchable BARs */
> +    RootBridge->PMem.Base           = MAX_UINT64;
> +    RootBridge->PMem.Limit          = 0;
> +    RootBridge->PMemAbove4G.Base    = MAX_UINT64;
> +    RootBridge->PMemAbove4G.Limit   = 0;
> +
> +    ASSERT (PcieController->PcieMmio64Translation == 0);
> +    ASSERT (PcieController->PcieMmio32Translation == 0);

PciHostBridgeDxe now supports MMIO translation so instead of these
asserts, you might want to assign the translation fields instead.

> +
> +    RootBridge->NoExtendedConfigSpace = FALSE;
> +
> +    RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath;
> +  }
> +
> +  return PciRootBridges;
> +}
> +
> +/**
> +  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
> +  )
> +{
> +  FreePool (Bridges);
> +}
> +
> +/**
> +  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;
> +  UINTN                              RootBridgeIndex;
> +
> +  DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
> +
> +  RootBridgeIndex = 0;
> +  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
> +
> +  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> +
> +    DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
> +
> +    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);
> +  }
> +}
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> new file mode 100644
> index 0000000..ced2c12
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> @@ -0,0 +1,330 @@
> +/** @file
> +  PCI Host Bridge Library instance for Marvell 70x0/80x0
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  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 <PiDxe.h>
> +
> +#include <IndustryStandard/Pci22.h>
> +
> +#include <Library/ArmLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MvGpioLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/BoardDesc.h>
> +
> +#include "PciHostBridgeLibConstructor.h"
> +
> +/**
> +  This function configures PCIE controllers IATU windows.
> +
> +  @param [in] PcieBaseAddress PCIE controller base address.
> +  @param [in] Index           IATU window index.
> +  @param [in] CpuBase         Address from the CPU perspective.
> +  @param [in] PciBase         Target PCIE address.
> +  @param [in] Size            IATU window size.
> +  @param [in] Type            IATU window type.
> +  @param [in] EnableFlags     Extra configuration flags.
> +
> +  @retval none
> +
> +**/
> +STATIC
> +VOID
> +ConfigureWindow (
> +  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress,

If this is the DBI address, please rename the parameter accordingly.
Base address means something else for PCIe in EDK2.

> +  IN UINTN                Index,
> +  IN UINT64               CpuBase,
> +  IN UINT64               PciBase,
> +  IN UINT64               Size,
> +  IN UINTN                Type,
> +  IN UINTN                EnableFlags
> +  )
> +{
> +  ArmDataMemoryBarrier ();
> +
> +  MmioWrite32 (PcieBaseAddress + IATU_VIEWPORT_OFF,
> +    IATU_VIEWPORT_OUTBOUND | IATU_VIEWPORT_REGION_INDEX (Index));
> +
> +  ArmDataMemoryBarrier ();
> +
> +  MmioWrite32 (PcieBaseAddress + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(CpuBase & 0xFFFFFFFF));
> +  MmioWrite32 (PcieBaseAddress + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(CpuBase >> 32));
> +  MmioWrite32 (PcieBaseAddress + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(CpuBase + Size - 1));
> +  MmioWrite32 (PcieBaseAddress + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(PciBase & 0xFFFFFFFF));
> +  MmioWrite32 (PcieBaseAddress + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(PciBase >> 32));
> +  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
> +    Type);
> +  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> +    IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN | EnableFlags);
> +}
> +
> +/**
> +  Perform PCIE slot reset using external GPIO pin.
> +
> +  @param [in] PcieBaseAddress  PCIE controller base address.
> +
> +  @retval none
> +
> +**/
> +STATIC
> +VOID
> +WaitForLink (
> +  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress
> +  )
> +{
> +  UINT32 Mask;
> +  UINT32 Status;
> +  UINT32 Timeout;
> +
> +  if (!(MmioRead32 (PcieBaseAddress + PCIE_PM_STATUS) & PCIE_PM_LTSSM_STAT_MASK)) {
> +    DEBUG ((DEBUG_INIT, "%a: no PCIE device detected\n", __FUNCTION__));
> +    return;
> +  }
> +
> +  /* Wait for the link to establish itself */
> +  DEBUG ((DEBUG_INIT, "%a: waiting for PCIE link\n", __FUNCTION__));
> +
> +  Mask = PCIE_GLOBAL_STATUS_RDLH_LINK_UP | PCIE_GLOBAL_STATUS_PHY_LINK_UP;
> +  Timeout = PCIE_LINK_UP_TIMEOUT_US / 10;
> +  do {
> +    Status = MmioRead32 (PcieBaseAddress + PCIE_GLOBAL_STATUS_REG);
> +    if ((Status & Mask) == Mask) {
> +      DEBUG ((DEBUG_ERROR, "pcie@0x%x link UP\n", PcieBaseAddress));
> +      break;
> +    }
> +    gBS->Stall (10);
> +  } while (Timeout--);
> +}
> +
> +/**
> +  Perform PCIE slot reset using external GPIO pin.
> +
> +  @param [in] *PcieResetGpio  GPIO pin description.
> +
> +  @retval EFI_SUCEESS         PCIE slot reset succeeded.
> +  @retval Other               Return error status.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +ResetPcieSlot (
> +  IN MV_GPIO_PIN *PcieResetGpio
> +  )
> +{
> +  EMBEDDED_GPIO_MODE   Mode;
> +  EMBEDDED_GPIO_PIN    GpioPin;
> +  EMBEDDED_GPIO       *GpioProtocol;
> +  EFI_STATUS           Status;
> +
> +  /* Get GPIO protocol */
> +  Status = MvGpioGetProtocol (PcieResetGpio->ControllerType, &GpioProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Unable to find GPIO protocol\n", __FUNCTION__));
> +    return Status;
> +  }
> +
> +  GpioPin = GPIO (PcieResetGpio->ControllerId, PcieResetGpio->PinNumber),
> +
> +  /* Reset the slot by toggling the GPIO pin */
> +  Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_1 : GPIO_MODE_OUTPUT_0;
> +  Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode);
> +  gBS->Stall (10 * 1000);

This seems a bit short for a PCIe reset, no? We use 150ms on
SynQuacer, just to be squarely on the safe side of the minimum 100ms
mandated by the spec (IIRC)

> +
> +  Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_0 : GPIO_MODE_OUTPUT_1;
> +  Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode);
> +  gBS->Stall (20 * 1000);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Obtain resources and perform a low-level PCIE controllers
> +  configuration.
> +
> +  @param [in]  ImageHandle  The image handle.
> +  @param [in] *SystemTable  The system table.
> +
> +  @retval EFI_SUCEESS       PCIE configuration successful.
> +  @retval Other             Return error status.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +Armada7k8kPciHostBridgeLibConstructor (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol;
> +  MV_BOARD_PCIE_DESCRIPTION   *BoardPcieDescription;
> +  MV_PCIE_CONTROLLER          *PcieController;
> +  EFI_PHYSICAL_ADDRESS         PcieBaseAddress;
> +  EFI_STATUS                   Status;
> +  UINTN                        Index;
> +
> +  /* Obtain list of available controllers */
> +  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
> +                  NULL,
> +                  (VOID **)&BoardDescriptionProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot locate BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  Status = BoardDescriptionProtocol->PcieDescriptionGet (
> +                                       BoardDescriptionProtocol,
> +                                       &BoardPcieDescription);
> +  if (Status == EFI_NOT_FOUND) {
> +    /* No controllers used on the platform, exit silently */
> +    return EFI_SUCCESS;
> +  } else if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot get Pcie board desc from BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  for (Index = 0; Index < BoardPcieDescription->PcieControllerCount; Index++) {
> +
> +    PcieController = &(BoardPcieDescription->PcieControllers[Index]);
> +
> +    ASSERT (PcieController->PcieBusMin == 0);
> +    ASSERT (PcieController->ConfigSpaceAddress % SIZE_256MB == 0);
> +
> +    if (PcieController->HaveResetGpio == TRUE) {
> +      /* Reset PCIE slot */
> +      Status = ResetPcieSlot (&PcieController->PcieResetGpio);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR,
> +          "%a: Cannot reset Pcie Slot\n",
> +          __FUNCTION__));
> +        return EFI_DEVICE_ERROR;
> +      }
> +    }
> +
> +    /* Low level PCIE controller configuration */
> +    PcieBaseAddress = PcieController->PcieBaseAddress;
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PORT_LINK_CTRL_OFF,
> +      ~PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK,
> +      PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + GEN2_CTRL_OFF,
> +      ~GEN2_CTRL_OFF_NUM_OF_LANES_MASK,
> +      GEN2_CTRL_OFF_NUM_OF_LANES(4) | GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET,
> +      ~(PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK | PCIE_GLOBAL_APP_LTSSM_EN),
> +      PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC);
> +
> +    MmioWrite32 (PcieBaseAddress + PCIE_ARCACHE_TRC_REG,
> +      ARCACHE_DEFAULT_VALUE);
> +
> +    MmioWrite32 (PcieBaseAddress + PCIE_AWCACHE_TRC_REG,
> +      AWCACHE_DEFAULT_VALUE);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_ARUSER_REG,
> +      ~AX_USER_DOMAIN_MASK,
> +      AX_USER_DOMAIN_OUTER_SHAREABLE);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_AWUSER_REG,
> +      ~AX_USER_DOMAIN_MASK,
> +      AX_USER_DOMAIN_OUTER_SHAREABLE);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CTL_2,
> +      ~TARGET_LINK_SPEED_MASK,
> +      LINK_SPEED_GEN_3);
> +
> +    MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CAPABILITY,
> +      ~TARGET_LINK_SPEED_MASK,
> +      LINK_SPEED_GEN_3);
> +
> +    MmioOr32 (PcieBaseAddress + PCIE_GEN3_EQU_CTRL,
> +      GEN3_EQU_EVAL_2MS_DISABLE);
> +
> +    MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET,
> +      PCIE_GLOBAL_APP_LTSSM_EN);
> +
> +    /* Region 0: MMIO32 range */
> +    ConfigureWindow (PcieBaseAddress,
> +      0,
> +      PcieController->PcieMmio32WinBase,
> +      PcieController->PcieMmio32WinBase,
> +      PcieController->PcieMmio32WinSize,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> +      0);
> +
> +    /* Region 1: Type 0 config space */
> +    ConfigureWindow (PcieBaseAddress,
> +      1,
> +      PcieController->ConfigSpaceAddress,
> +      0x0,
> +      SIZE_64KB,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0,
> +      IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
> +
> +    /* Region 2: Type 1 config space */
> +    ConfigureWindow (PcieBaseAddress,
> +      2,
> +      PcieController->ConfigSpaceAddress + SIZE_64KB,
> +      0x0,
> +      PcieController->PcieBusMax * SIZE_1MB,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1,
> +      IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
> +
> +    /* Region 3: port I/O range */
> +    ConfigureWindow (PcieBaseAddress,
> +      3,
> +      PcieController->PcieIoTranslation,
> +      PcieController->PcieIoWinBase,
> +      PcieController->PcieIoWinSize,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO,
> +      0);
> +
> +    /* Region 4: MMIO64 range */
> +    ConfigureWindow (PcieBaseAddress,
> +      4,
> +      PcieController->PcieMmio64WinBase,
> +      PcieController->PcieMmio64WinBase,
> +      PcieController->PcieMmio64WinSize,
> +      IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> +      0);
> +
> +    MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_INT_MASK1_REG,
> +      PCIE_INT_A_ASSERT_MASK |
> +      PCIE_INT_B_ASSERT_MASK |
> +      PCIE_INT_C_ASSERT_MASK |
> +      PCIE_INT_D_ASSERT_MASK);
> +
> +    WaitForLink (PcieBaseAddress);
> +
> +    /* Enable the RC */
> +    MmioOr32 (PcieBaseAddress + PCI_COMMAND_OFFSET,
> +      EFI_PCI_COMMAND_IO_SPACE |
> +      EFI_PCI_COMMAND_MEMORY_SPACE |
> +      EFI_PCI_COMMAND_BUS_MASTER);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 08/14] Marvell/Armada7k8k: Enable PCIE support
  2019-05-09  9:53 ` [edk2-platforms: PATCH 08/14] Marvell/Armada7k8k: Enable PCIE support Marcin Wojtas
@ 2019-05-16 14:16   ` Ard Biesheuvel
  2019-05-16 14:22     ` Marcin Wojtas
  0 siblings, 1 reply; 36+ messages in thread
From: Ard Biesheuvel @ 2019-05-16 14:16 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: edk2-devel-groups-io, Leif Lindholm, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	kettenis

On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
>
> Wire up the platform libraries to the generic drivers so that we can use
> PCI devices and UEFI, and leave the controller initialized so that the
> OS can boot it using a generic driver of its own.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc | 17 +++++++++++++++--
>  Silicon/Marvell/Armada7k8k/Armada7k8k.fdf     |  5 +++++
>  2 files changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
> index 545b369..f78a76b 100644
> --- a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
> +++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
> @@ -70,8 +70,10 @@
>    IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
>    UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
>    CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
> -  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
> -  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
> +  PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
> +  PciHostBridgeLib|Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> +  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
> +  PciExpressLib|Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
>
>  # Basic UEFI services libraries
>    UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
> @@ -407,6 +409,12 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x00010000
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x00010000
>
> +  # PCIE
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000
> +
> +  # SoC Configuration Space
> +  gMarvellTokenSpaceGuid.PcdConfigSpaceBaseAddress|0xE0000000
> +
>  !if $(CAPSULE_ENABLE)
>  [PcdsDynamicExDefault.common.DEFAULT]
>    gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
> @@ -520,6 +528,11 @@
>    MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
>    Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf
>
> +  # PCI
> +  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf

This driver requires gArmTokenSpaceGuid.PcdPciIoTranslation to be set
to a sane value. Are you sure this is the case for your platforms?

> +  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> +  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> +
>    # Console packages
>    MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
>    MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf b/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf
> index 3a320ba..e22f514 100644
> --- a/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf
> +++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf
> @@ -174,6 +174,11 @@ FvNameGuid         = 5eda4200-2c5f-43cb-9da3-0baf74b1b30c
>    INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
>    INF Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf
>
> +  # PCI
> +  INF ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
> +  INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> +  INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> +
>    # Multiple Console IO support
>    INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
>    INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 08/14] Marvell/Armada7k8k: Enable PCIE support
  2019-05-16 14:16   ` Ard Biesheuvel
@ 2019-05-16 14:22     ` Marcin Wojtas
  2019-05-16 14:25       ` Ard Biesheuvel
  0 siblings, 1 reply; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-16 14:22 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: edk2-devel-groups-io, Leif Lindholm, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	Mark Kettenis

Hi Ard,

czw., 16 maj 2019 o 16:16 Ard Biesheuvel <ard.biesheuvel@linaro.org> napisał(a):
>
> On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
> >
> > Wire up the platform libraries to the generic drivers so that we can use
> > PCI devices and UEFI, and leave the controller initialized so that the
> > OS can boot it using a generic driver of its own.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> > ---
> >  Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc | 17 +++++++++++++++--
> >  Silicon/Marvell/Armada7k8k/Armada7k8k.fdf     |  5 +++++
> >  2 files changed, 20 insertions(+), 2 deletions(-)
> >
> > diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
> > index 545b369..f78a76b 100644
> > --- a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
> > +++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
> > @@ -70,8 +70,10 @@
> >    IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
> >    UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
> >    CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
> > -  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
> > -  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
> > +  PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
> > +  PciHostBridgeLib|Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> > +  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
> > +  PciExpressLib|Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> >
> >  # Basic UEFI services libraries
> >    UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
> > @@ -407,6 +409,12 @@
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x00010000
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x00010000
> >
> > +  # PCIE
> > +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000
> > +
> > +  # SoC Configuration Space
> > +  gMarvellTokenSpaceGuid.PcdConfigSpaceBaseAddress|0xE0000000
> > +
> >  !if $(CAPSULE_ENABLE)
> >  [PcdsDynamicExDefault.common.DEFAULT]
> >    gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
> > @@ -520,6 +528,11 @@
> >    MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
> >    Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf
> >
> > +  # PCI
> > +  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
>
> This driver requires gArmTokenSpaceGuid.PcdPciIoTranslation to be set
> to a sane value. Are you sure this is the case for your platforms?
>

Do you mean the IO space for the controller? If yes, I'll set the PCD
to according value I use in board description. I don't have an old
enough endpoint that requires IO space to test :)

Best regards,
Marcin

> > +  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > +  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > +
> >    # Console packages
> >    MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
> >    MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> > diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf b/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf
> > index 3a320ba..e22f514 100644
> > --- a/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf
> > +++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf
> > @@ -174,6 +174,11 @@ FvNameGuid         = 5eda4200-2c5f-43cb-9da3-0baf74b1b30c
> >    INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
> >    INF Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf
> >
> > +  # PCI
> > +  INF ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
> > +  INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> > +  INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > +
> >    # Multiple Console IO support
> >    INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
> >    INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> > --
> > 2.7.4
> >

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 09/14] Marvell/Armada80x0McBin: Enable ACPI PCIE support
  2019-05-09  9:53 ` [edk2-platforms: PATCH 09/14] Marvell/Armada80x0McBin: Enable ACPI " Marcin Wojtas
  2019-05-10 15:54   ` Leif Lindholm
@ 2019-05-16 14:23   ` Ard Biesheuvel
  1 sibling, 0 replies; 36+ messages in thread
From: Ard Biesheuvel @ 2019-05-16 14:23 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: edk2-devel-groups-io, Leif Lindholm, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	kettenis

On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
>
> This patch adds description of the PCIE controller in
> ACPI tables of MacchiatoBin community board.
>

It might be good to mention you are using my god awful hack to shift
the ECAM base by 32 KB (and reduce the bus range to 1) to get rid of
the device aliases.

Some comments below - in general, there is some cargo culting here
(some of which I may be responsible for). It makes sense to trim this
down to what we really need rather than carry obscure ACPI AML junk
that nobody remembers where it came from


> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf       |   1 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h    |  25 +++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl  | 217 ++++++++++++++++++++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc |  47 +++++
>  4 files changed, 290 insertions(+)
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc
>
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf
> index 9e52281..e627932 100644
> --- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin.inf
> @@ -25,6 +25,7 @@
>
>  [Sources]
>    Armada80x0McBin/Dsdt.asl
> +  Armada80x0McBin/Mcfg.aslc
>    Fadt.aslc
>    Gtdt.aslc
>    Madt.aslc
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
> new file mode 100644
> index 0000000..93631c2
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Pcie.h
> @@ -0,0 +1,25 @@
> +/**
> +
> +  Copyright (C) 2019, Marvell International Ltd. and its affiliates.
> +
> +  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.
> +
> +**/
> +
> +#define PCI_BUS_MIN        0x0
> +#define PCI_BUS_MAX        0x0
> +#define PCI_BUS_COUNT      0x1
> +#define PCI_MMIO32_BASE    0xC0000000
> +#define PCI_MMIO32_SIZE    0x20000000
> +#define PCI_MMIO64_BASE    0x800000000
> +#define PCI_MMIO64_SIZE    0x100000000
> +#define PCI_IO_BASE        0x0
> +#define PCI_IO_SIZE        0x10000
> +#define PCI_IO_TRANSLATION 0xEFF00000
> +#define PCI_ECAM_BASE      0xE0008000
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl
> index 87cb93a..caf5cb9 100644
> --- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Dsdt.asl
> @@ -14,6 +14,7 @@
>
>  **/
>
> +#include "Armada80x0McBin/Pcie.h"
>  #include "IcuInterrupts.h"
>
>  DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
> @@ -306,5 +307,221 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
>                  }
>              })
>          }
> +
> +        //
> +        // PCIe Root Bus
> +        //
> +        Device (PCI0)
> +        {
> +            Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
> +            Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
> +            Name (_SEG, 0x00)  // _SEG: PCI Segment
> +            Name (_BBN, 0x00)  // _BBN: BIOS Bus Number
> +            Name (_CCA, 0x01)  // _CCA: Cache Coherency Attribute
> +            Name (_PRT, Package ()  // _PRT: PCI Routing Table
> +            {
> +                Package () { 0xFFFF, 0x0, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x1, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x2, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x3, 0x0, 0x40 }
> +            })
> +
> +            Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings
> +            {
> +                Name (RBUF, ResourceTemplate ()
> +                {
> +                    WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
> +                        0x0000,                             // Granularity
> +                        PCI_BUS_MIN,                        // Range Minimum
> +                        PCI_BUS_MAX,                        // Range Maximum
> +                        0x0000,                             // Translation Offset
> +                        PCI_BUS_COUNT                       // Length
> +                        )
> +                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
> +                        0x00000000,                         // Granularity
> +                        PCI_MMIO32_BASE,                    // Range Minimum
> +                        0xDFFFFFFF,                         // Range Maximum
> +                        0x00000000,                         // Translation Offset
> +                        PCI_MMIO32_SIZE                     // Length
> +                        )
> +                    QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
> +                        0x0000000000000000,                 // Granularity
> +                        PCI_MMIO64_BASE,                    // Range Minimum
> +                        0x8FFFFFFFF,                        // Range Maximum
> +                        0x00000000,                         // Translation Offset
> +                        PCI_MMIO64_SIZE                     // Length
> +                        )
> +                    DWordIo (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
> +                        0x00000000,                         // Granularity
> +                        PCI_IO_BASE,                        // Range Minimum
> +                        0x0000FFFF,                         // Range Maximum
> +                        PCI_IO_TRANSLATION,                 // Translation Address
> +                        PCI_IO_SIZE,                        // Length
> +                        ,
> +                        ,
> +                        ,
> +                        TypeTranslation
> +                        )
> +                })
> +                Return (RBUF) /* \_SB_.PCI0._CRS.RBUF */
> +            } // Method(_CRS)
> +
> +            Device (RES0)
> +            {
> +                Name (_HID, "PNP0C02")
> +                Name (_CRS, ResourceTemplate ()
> +                {
> +                    Memory32Fixed (ReadWrite,
> +                                   PCI_ECAM_BASE,
> +                                   0x10000000
> +                                   )
> +                })
> +            }
> +            Name (SUPP, 0x00)
> +            Name (CTRL, 0x00)
> +            Method (_OSC, 4, NotSerialized)  // _OSC: Operating System Capabilities
> +            {
> +                CreateDWordField (Arg3, 0x00, CDW1)
> +                If (LEqual (Arg0, ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") /* PCI Host Bridge Device */))
> +                {
> +                    CreateDWordField (Arg3, 0x04, CDW2)
> +                    CreateDWordField (Arg3, 0x08, CDW3)
> +                    Store (CDW2, SUPP) /* \_SB_.PCI0.SUPP */
> +                    Store (CDW3, CTRL) /* \_SB_.PCI0.CTRL */
> +                    If (LNotEqual (And (SUPP, 0x16), 0x16))
> +                    {
> +                        And (CTRL, 0x1E, CTRL) /* \_SB_.PCI0.CTRL */
> +                    }
> +
> +                    And (CTRL, 0x1D, CTRL) /* \_SB_.PCI0.CTRL */
> +                    If (LNotEqual (Arg1, One))
> +                    {
> +                        Or (CDW1, 0x08, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    }
> +
> +                    If (LNotEqual (CDW3, CTRL))
> +                    {
> +                        Or (CDW1, 0x10, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    }
> +
> +                    Store (CTRL, CDW3) /* \_SB_.PCI0._OSC.CDW3 */
> +                    Return (Arg3)
> +                }
> +                Else
> +                {
> +                    Or (CDW1, 0x04, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    Return (Arg3)
> +                }
> +            } // Method(_OSC)
> +
> +            //
> +            // Device-Specific Methods
> +            //
> +            Method(_DSM, 0x4, NotSerialized) {

Please drop this

> +              If (LEqual(Arg0, ToUUID("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
> +                switch (ToInteger(Arg2)) {
> +                  //
> +                  // Function 0: Return supported functions
> +                  //
> +                  case(0) {
> +                    Return (Buffer() {0xFF})
> +                  }
> +
> +                  //
> +                  // Function 1: Return PCIe Slot Information
> +                  //
> +                  case(1) {
> +                    Return (Package(2) {
> +                      One, // Success
> +                      Package(3) {
> +                        0x1,  // x1 PCIe link
> +                        0x1,  // PCI express card slot
> +                        0x1   // WAKE# signal supported
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 2: Return PCIe Slot Number.
> +                  //
> +                  case(2) {
> +                    Return (Package(1) {
> +                      Package(4) {
> +                        2,  // Source ID
> +                        4,  // Token ID: ID refers to a slot
> +                        0,  // Start bit of the field to use.
> +                        7   // End bit of the field to use.
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 4: Return PCI Bus Capabilities
> +                  //
> +                  case(4) {
> +                    Return (Package(2) {
> +                      One, // Success
> +                      Buffer() {
> +                        1,0,            // Version
> +                        0,0,            // Status, 0:Success
> +                        24,0,0,0,       // Length
> +                        1,0,            // PCI
> +                        16,0,           // Length
> +                        0,              // Attributes
> +                        0x0D,           // Current Speed/Mode
> +                        0x3F,0,         // Supported Speeds/Modes
> +                        0,              // Voltage
> +                        0,0,0,0,0,0,0   // Reserved
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 5: Return Ignore PCI Boot Configuration
> +                  //
> +                  case(5) {
> +                    Return (Package(1) {1})
> +                  }
> +
> +                  //
> +                  // Function 6: Return LTR Maximum Latency
> +                  //
> +                  case(6) {
> +                    Return (Package(4) {
> +                      Package(1){0},  // Maximum Snoop Latency Scale
> +                      Package(1){0},  // Maximum Snoop Latency Value
> +                      Package(1){0},  // Maximum No-Snoop Latency Scale
> +                      Package(1){0}   // Maximum No-Snoop Latency Value
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 7: Return PCI Express Naming
> +                  //
> +                  case(7) {
> +                    Return (Package(2) {
> +                      Package(1) {0},
> +                      Package(1) {Unicode("PCI0")}
> +                    })
> +                  }
> +
> +                  //
> +                  // Not supported
> +                  //
> +                  default {
> +                  }
> +                }
> +              }
> +              Return (Buffer(){0})
> +            } // Method(_DSM)
> +
> +            //
> +            // Root-Complex 0
> +            //
> +            Device (RP0)

Please drop this

> +            {
> +                Name (_ADR, PCI_ECAM_BASE)  // _ADR: Bus 0, Dev 0, Func 0
> +            }
> +        }
>      }
>  }
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc
> new file mode 100644
> index 0000000..bda5800
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0McBin/Mcfg.aslc
> @@ -0,0 +1,47 @@
> +/** @file
> +
> +  Memory mapped config space base address table (MCFG)
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019, Marvell International Ltd. and its affiliates.<BR>
> +
> +  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 <Library/AcpiLib.h>
> +
> +#include "AcpiHeader.h"
> +#include "Armada80x0McBin/Pcie.h"
> +
> +#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +
> +#pragma pack(1)
> +typedef struct {
> +  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
> +  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE Structure;
> +} ACPI_6_0_MCFG_STRUCTURE;
> +#pragma pack()
> +
> +STATIC ACPI_6_0_MCFG_STRUCTURE Mcfg = {
> +  {
> +    __ACPI_HEADER (EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +                   ACPI_6_0_MCFG_STRUCTURE,
> +                   EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION),
> +    EFI_ACPI_RESERVED_QWORD
> +  }, {
> +    PCI_ECAM_BASE,                   // BaseAddress
> +    0,                               // PciSegmentGroupNumber
> +    PCI_BUS_MIN,                     // StartBusNumber
> +    PCI_BUS_MAX,                     // EndBusNumber
> +    EFI_ACPI_RESERVED_DWORD          // Reserved
> +  }
> +};
> +
> +VOID CONST * CONST ReferenceAcpiTable = &Mcfg;
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 08/14] Marvell/Armada7k8k: Enable PCIE support
  2019-05-16 14:22     ` Marcin Wojtas
@ 2019-05-16 14:25       ` Ard Biesheuvel
  2019-05-16 14:32         ` Leif Lindholm
  0 siblings, 1 reply; 36+ messages in thread
From: Ard Biesheuvel @ 2019-05-16 14:25 UTC (permalink / raw)
  To: Marcin Wojtas
  Cc: edk2-devel-groups-io, Leif Lindholm, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	Mark Kettenis

On Thu, 16 May 2019 at 16:22, Marcin Wojtas <mw@semihalf.com> wrote:
>
> Hi Ard,
>
> czw., 16 maj 2019 o 16:16 Ard Biesheuvel <ard.biesheuvel@linaro.org> napisał(a):
> >
> > On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
> > >
> > > Wire up the platform libraries to the generic drivers so that we can use
> > > PCI devices and UEFI, and leave the controller initialized so that the
> > > OS can boot it using a generic driver of its own.
> > >
> > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> > > ---
> > >  Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc | 17 +++++++++++++++--
> > >  Silicon/Marvell/Armada7k8k/Armada7k8k.fdf     |  5 +++++
> > >  2 files changed, 20 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
> > > index 545b369..f78a76b 100644
> > > --- a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
> > > +++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc
> > > @@ -70,8 +70,10 @@
> > >    IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
> > >    UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
> > >    CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
> > > -  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
> > > -  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
> > > +  PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
> > > +  PciHostBridgeLib|Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> > > +  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
> > > +  PciExpressLib|Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> > >
> > >  # Basic UEFI services libraries
> > >    UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
> > > @@ -407,6 +409,12 @@
> > >    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x00010000
> > >    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x00010000
> > >
> > > +  # PCIE
> > > +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000
> > > +
> > > +  # SoC Configuration Space
> > > +  gMarvellTokenSpaceGuid.PcdConfigSpaceBaseAddress|0xE0000000
> > > +
> > >  !if $(CAPSULE_ENABLE)
> > >  [PcdsDynamicExDefault.common.DEFAULT]
> > >    gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor|{0x0}|VOID*|0x100
> > > @@ -520,6 +528,11 @@
> > >    MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
> > >    Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf
> > >
> > > +  # PCI
> > > +  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
> >
> > This driver requires gArmTokenSpaceGuid.PcdPciIoTranslation to be set
> > to a sane value. Are you sure this is the case for your platforms?
> >
>
> Do you mean the IO space for the controller? If yes, I'll set the PCD
> to according value I use in board description. I don't have an old
> enough endpoint that requires IO space to test :)
>

Yes, it is basically the MMIO address of the I/O space.

Leif kindly gave me a PCIe serial port controller that I use
especially for testing these things at plugfests.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-platforms: PATCH 10/14] Marvell/Armada80x0Db: Enable ACPI PCIE support
  2019-05-09  9:53 ` [edk2-platforms: PATCH 10/14] Marvell/Armada80x0Db: " Marcin Wojtas
@ 2019-05-16 14:25   ` Ard Biesheuvel
  0 siblings, 0 replies; 36+ messages in thread
From: Ard Biesheuvel @ 2019-05-16 14:25 UTC (permalink / raw)
  To: edk2-devel-groups-io, Marcin Wojtas
  Cc: Leif Lindholm, Jan Dąbroś, Grzegorz Jaszczyk,
	Kostya Porotchkin, Jici Gao, Rebecca Cran, Mark Kettenis

On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
>
> This patch adds description of the PCIE controller in
> ACPI tables of Armada 8040 DB board.
>

Same comments as before.

> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf       |   1 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h    |  25 +++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl  | 217 ++++++++++++++++++++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc |  47 +++++
>  4 files changed, 290 insertions(+)
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc
>
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf
> index 35a679b..9b37eb7 100644
> --- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db.inf
> @@ -25,6 +25,7 @@
>
>  [Sources]
>    Armada80x0Db/Dsdt.asl
> +  Armada80x0Db/Mcfg.aslc
>    Fadt.aslc
>    Gtdt.aslc
>    Madt.aslc
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h
> new file mode 100644
> index 0000000..93631c2
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Pcie.h
> @@ -0,0 +1,25 @@
> +/**
> +
> +  Copyright (C) 2019, Marvell International Ltd. and its affiliates.
> +
> +  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.
> +
> +**/
> +
> +#define PCI_BUS_MIN        0x0
> +#define PCI_BUS_MAX        0x0
> +#define PCI_BUS_COUNT      0x1
> +#define PCI_MMIO32_BASE    0xC0000000
> +#define PCI_MMIO32_SIZE    0x20000000
> +#define PCI_MMIO64_BASE    0x800000000
> +#define PCI_MMIO64_SIZE    0x100000000
> +#define PCI_IO_BASE        0x0
> +#define PCI_IO_SIZE        0x10000
> +#define PCI_IO_TRANSLATION 0xEFF00000
> +#define PCI_ECAM_BASE      0xE0008000
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl
> index 7c65949..0f78e39 100644
> --- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Dsdt.asl
> @@ -15,6 +15,7 @@
>
>  **/
>
> +#include "Armada80x0Db/Pcie.h"
>  #include "IcuInterrupts.h"
>
>  DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
> @@ -326,5 +327,221 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA8K", 3)
>                  }
>              })
>          }
> +
> +        //
> +        // PCIe Root Bus
> +        //
> +        Device (PCI0)
> +        {
> +            Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
> +            Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
> +            Name (_SEG, 0x00)  // _SEG: PCI Segment
> +            Name (_BBN, 0x00)  // _BBN: BIOS Bus Number
> +            Name (_CCA, 0x01)  // _CCA: Cache Coherency Attribute
> +            Name (_PRT, Package ()  // _PRT: PCI Routing Table
> +            {
> +                Package () { 0xFFFF, 0x0, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x1, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x2, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x3, 0x0, 0x40 }
> +            })
> +
> +            Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings
> +            {
> +                Name (RBUF, ResourceTemplate ()
> +                {
> +                    WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
> +                        0x0000,                             // Granularity
> +                        PCI_BUS_MIN,                        // Range Minimum
> +                        PCI_BUS_MAX,                        // Range Maximum
> +                        0x0000,                             // Translation Offset
> +                        PCI_BUS_COUNT                       // Length
> +                        )
> +                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
> +                        0x00000000,                         // Granularity
> +                        PCI_MMIO32_BASE,                    // Range Minimum
> +                        0xDFFFFFFF,                         // Range Maximum
> +                        0x00000000,                         // Translation Offset
> +                        PCI_MMIO32_SIZE                     // Length
> +                        )
> +                    QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
> +                        0x0000000000000000,                 // Granularity
> +                        PCI_MMIO64_BASE,                    // Range Minimum
> +                        0x8FFFFFFFF,                        // Range Maximum
> +                        0x00000000,                         // Translation Offset
> +                        PCI_MMIO64_SIZE                     // Length
> +                        )
> +                    DWordIo (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
> +                        0x00000000,                         // Granularity
> +                        PCI_IO_BASE,                        // Range Minimum
> +                        0x0000FFFF,                         // Range Maximum
> +                        PCI_IO_TRANSLATION,                 // Translation Address
> +                        PCI_IO_SIZE,                        // Length
> +                        ,
> +                        ,
> +                        ,
> +                        TypeTranslation
> +                        )
> +                })
> +                Return (RBUF) /* \_SB_.PCI0._CRS.RBUF */
> +            } // Method(_CRS)
> +
> +            Device (RES0)
> +            {
> +                Name (_HID, "PNP0C02")
> +                Name (_CRS, ResourceTemplate ()
> +                {
> +                    Memory32Fixed (ReadWrite,
> +                                   PCI_ECAM_BASE,
> +                                   0x10000000
> +                                   )
> +                })
> +            }
> +            Name (SUPP, 0x00)
> +            Name (CTRL, 0x00)
> +            Method (_OSC, 4, NotSerialized)  // _OSC: Operating System Capabilities
> +            {
> +                CreateDWordField (Arg3, 0x00, CDW1)
> +                If (LEqual (Arg0, ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") /* PCI Host Bridge Device */))
> +                {
> +                    CreateDWordField (Arg3, 0x04, CDW2)
> +                    CreateDWordField (Arg3, 0x08, CDW3)
> +                    Store (CDW2, SUPP) /* \_SB_.PCI0.SUPP */
> +                    Store (CDW3, CTRL) /* \_SB_.PCI0.CTRL */
> +                    If (LNotEqual (And (SUPP, 0x16), 0x16))
> +                    {
> +                        And (CTRL, 0x1E, CTRL) /* \_SB_.PCI0.CTRL */
> +                    }
> +
> +                    And (CTRL, 0x1D, CTRL) /* \_SB_.PCI0.CTRL */
> +                    If (LNotEqual (Arg1, One))
> +                    {
> +                        Or (CDW1, 0x08, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    }
> +
> +                    If (LNotEqual (CDW3, CTRL))
> +                    {
> +                        Or (CDW1, 0x10, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    }
> +
> +                    Store (CTRL, CDW3) /* \_SB_.PCI0._OSC.CDW3 */
> +                    Return (Arg3)
> +                }
> +                Else
> +                {
> +                    Or (CDW1, 0x04, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    Return (Arg3)
> +                }
> +            } // Method(_OSC)
> +
> +            //
> +            // Device-Specific Methods
> +            //
> +            Method(_DSM, 0x4, NotSerialized) {
> +              If (LEqual(Arg0, ToUUID("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
> +                switch (ToInteger(Arg2)) {
> +                  //
> +                  // Function 0: Return supported functions
> +                  //
> +                  case(0) {
> +                    Return (Buffer() {0xFF})
> +                  }
> +
> +                  //
> +                  // Function 1: Return PCIe Slot Information
> +                  //
> +                  case(1) {
> +                    Return (Package(2) {
> +                      One, // Success
> +                      Package(3) {
> +                        0x1,  // x1 PCIe link
> +                        0x1,  // PCI express card slot
> +                        0x1   // WAKE# signal supported
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 2: Return PCIe Slot Number.
> +                  //
> +                  case(2) {
> +                    Return (Package(1) {
> +                      Package(4) {
> +                        2,  // Source ID
> +                        4,  // Token ID: ID refers to a slot
> +                        0,  // Start bit of the field to use.
> +                        7   // End bit of the field to use.
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 4: Return PCI Bus Capabilities
> +                  //
> +                  case(4) {
> +                    Return (Package(2) {
> +                      One, // Success
> +                      Buffer() {
> +                        1,0,            // Version
> +                        0,0,            // Status, 0:Success
> +                        24,0,0,0,       // Length
> +                        1,0,            // PCI
> +                        16,0,           // Length
> +                        0,              // Attributes
> +                        0x0D,           // Current Speed/Mode
> +                        0x3F,0,         // Supported Speeds/Modes
> +                        0,              // Voltage
> +                        0,0,0,0,0,0,0   // Reserved
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 5: Return Ignore PCI Boot Configuration
> +                  //
> +                  case(5) {
> +                    Return (Package(1) {1})
> +                  }
> +
> +                  //
> +                  // Function 6: Return LTR Maximum Latency
> +                  //
> +                  case(6) {
> +                    Return (Package(4) {
> +                      Package(1){0},  // Maximum Snoop Latency Scale
> +                      Package(1){0},  // Maximum Snoop Latency Value
> +                      Package(1){0},  // Maximum No-Snoop Latency Scale
> +                      Package(1){0}   // Maximum No-Snoop Latency Value
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 7: Return PCI Express Naming
> +                  //
> +                  case(7) {
> +                    Return (Package(2) {
> +                      Package(1) {0},
> +                      Package(1) {Unicode("PCI0")}
> +                    })
> +                  }
> +
> +                  //
> +                  // Not supported
> +                  //
> +                  default {
> +                  }
> +                }
> +              }
> +              Return (Buffer(){0})
> +            } // Method(_DSM)
> +
> +            //
> +            // Root-Complex 0
> +            //
> +            Device (RP0)
> +            {
> +                Name (_ADR, PCI_ECAM_BASE)  // _ADR: Bus 0, Dev 0, Func 0
> +            }
> +        }
>      }
>  }
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc
> new file mode 100644
> index 0000000..da152b7
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada80x0Db/Mcfg.aslc
> @@ -0,0 +1,47 @@
> +/** @file
> +
> +  Memory mapped config space base address table (MCFG)
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019, Marvell International Ltd. and its affiliates.<BR>
> +
> +  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 <Library/AcpiLib.h>
> +
> +#include "AcpiHeader.h"
> +#include "Armada80x0Db/Pcie.h"
> +
> +#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +
> +#pragma pack(1)
> +typedef struct {
> +  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
> +  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE Structure;
> +} ACPI_6_0_MCFG_STRUCTURE;
> +#pragma pack()
> +
> +STATIC ACPI_6_0_MCFG_STRUCTURE Mcfg = {
> +  {
> +    __ACPI_HEADER (EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +                   ACPI_6_0_MCFG_STRUCTURE,
> +                   EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION),
> +    EFI_ACPI_RESERVED_QWORD
> +  }, {
> +    PCI_ECAM_BASE,                   // BaseAddress
> +    0,                               // PciSegmentGroupNumber
> +    PCI_BUS_MIN,                     // StartBusNumber
> +    PCI_BUS_MAX,                     // EndBusNumber
> +    EFI_ACPI_RESERVED_DWORD          // Reserved
> +  }
> +};
> +
> +VOID CONST * CONST ReferenceAcpiTable = &Mcfg;
> --
> 2.7.4
>
>
> 
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation
  2019-05-16 14:02   ` Ard Biesheuvel
@ 2019-05-16 14:26     ` Marcin Wojtas
  0 siblings, 0 replies; 36+ messages in thread
From: Marcin Wojtas @ 2019-05-16 14:26 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: edk2-devel-groups-io, Leif Lindholm, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	Mark Kettenis

czw., 16 maj 2019 o 16:02 Ard Biesheuvel <ard.biesheuvel@linaro.org> napisał(a):
>
> On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
> >
> > From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >
> > Implement a special version of PciExpressLib that takes the quirky
> > nature of the Synopsys Designware PCIe IP into account. In particular,
> > we need to ignores config space accesses to all devices on the first
>
> ignore
>
>
> > bus except device 0, because the broadcast nature of type 0 configuration
> > cycles will result in whatever device is in the slot to appear at each
> > of the 32 device positions.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> > ---
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf |   42 +
> >  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c   | 1529 ++++++++++++++++++++
> >  2 files changed, 1571 insertions(+)
> >  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> >  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> >
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> > new file mode 100644
> > index 0000000..8f09820
> > --- /dev/null
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.inf
> > @@ -0,0 +1,42 @@
> > +## @file
> > +#
> > +#  Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
> > +#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> > +#
> > +#  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                    = 0x0001001B
> > +  BASE_NAME                      = Armada7k8kPciExpressLib
> > +  FILE_GUID                      = f0926204-3061-40ed-8261-2aeccc7914c9
> > +  MODULE_TYPE                    = BASE
> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = PciExpressLib
> > +
> > +[Sources]
> > +  PciExpressLib.c
> > +
> > +[Packages]
> > +  ArmPkg/ArmPkg.dec
> > +  MdePkg/MdePkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +  DebugLib
> > +  IoLib
> > +  PcdLib
> > +
> > +[Pcd]
> > +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress  ## CONSUMES
> > +
> > +[FixedPcd]
> > +  gArmTokenSpaceGuid.PcdPciBusMin
> > +  gArmTokenSpaceGuid.PcdPciBusMax
> > diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> > new file mode 100644
> > index 0000000..8fa2eb6
> > --- /dev/null
> > +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciExpressLib/PciExpressLib.c
> > @@ -0,0 +1,1529 @@
> > +/** @file
> > +
> > +  Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
> > +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> > +
> > +  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 <Base.h>
> > +
> > +#include <Library/BaseLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/IoLib.h>
> > +#include <Library/PcdLib.h>
> > +#include <Library/PciExpressLib.h>
> > +
> > +/**
> > +  Assert the validity of a PCI address. A valid PCI address should contain 1's
> > +  only in the low 28 bits.
> > +
> > +  @param  A The address to validate.
> > +
> > +**/
> > +#define ASSERT_INVALID_PCI_ADDRESS(A) \
> > +  ASSERT (((A) & ~0xfffffff) == 0)
> > +
> > +/**
> > +  Registers a PCI device so PCI configuration registers may be accessed after
> > +  SetVirtualAddressMap().
> > +
> > +  Registers the PCI device specified by Address so all the PCI configuration
> > +  registers associated with that PCI device may be accessed after SetVirtualAddressMap()
> > +  is called.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +
> > +  @retval RETURN_SUCCESS           The PCI device was registered for runtime access.
> > +  @retval RETURN_UNSUPPORTED       An attempt was made to call this function
> > +                                   after ExitBootServices().
> > +  @retval RETURN_UNSUPPORTED       The resources required to access the PCI device
> > +                                   at runtime could not be mapped.
> > +  @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
> > +                                   complete the registration.
> > +
> > +**/
> > +RETURN_STATUS
> > +EFIAPI
> > +PciExpressRegisterForRuntimeAccess (
> > +  IN UINTN  Address
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  return RETURN_UNSUPPORTED;
> > +}
> > +
> > +#define ECAM_BUS_SIZE       SIZE_1MB
> > +#define ECAM_DEV_SIZE       SIZE_32KB
> > +
> > +STATIC
> > +BOOLEAN
> > +IgnoreBusDeviceFunction (
> > +  IN  UINTN   Address
> > +  )
> > +{
> > +  ASSERT (Address >= FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE);
> > +  ASSERT (Address < (FixedPcdGet32 (PcdPciBusMax) + 1) * ECAM_BUS_SIZE);
> > +
> > +  //
> > +  // Type 0 configuration cycles don't contain a b/d/f specifier, and so it
> > +  // is up to the bus that delivers them to ensure they only end up at the
> > +  // correct device/function. Sadly, the Synopsys IP does not implement this,
> > +  // and so we have to ignore config space accesses for all devices on the
> > +  // first bus except device 0.
> > +  //
>
> This is not entirely true. Type 0 PCIe config TLPs (as opposed to
> legacy PCI bus cycles) do contain b/d/f specifiers, but the endpoint
> doesn't know its own device number, and so it responds to all of them.
>

Ok, I will update the original comment.

Thanks,
Marcin

> > +  return (Address >= (FixedPcdGet32 (PcdPciBusMin) * ECAM_BUS_SIZE +
> > +                      ECAM_DEV_SIZE) &&
> > +          Address < (FixedPcdGet32 (PcdPciBusMin) + 1) * ECAM_BUS_SIZE);
> > +}
> > +
> > +/**
> > +  Gets the base address of PCI Express.
> > +
> > +  This internal functions retrieves PCI Express Base Address via a PCD entry
> > +  PcdPciExpressBaseAddress.
> > +
> > +  @return The base address of PCI Express.
> > +
> > +**/
> > +VOID*
> > +GetPciExpressBaseAddress (
> > +  VOID
> > +  )
> > +{
> > +  return (VOID*)(UINTN) PcdGet64 (PcdPciExpressBaseAddress);
> > +}
> > +
> > +/**
> > +  Reads an 8-bit PCI configuration register.
> > +
> > +  Reads and returns the 8-bit PCI configuration register specified by Address.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +
> > +  @return The read value from the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressRead8 (
> > +  IN      UINTN                     Address
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
> > +}
> > +
> > +/**
> > +  Writes an 8-bit PCI configuration register.
> > +
> > +  Writes the 8-bit PCI configuration register specified by Address with the
> > +  value specified by Value. Value is returned. This function must guarantee
> > +  that all PCI read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  Value   The value to write.
> > +
> > +  @return The value written to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressWrite8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT8                     Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> > +}
> > +
> > +/**
> > +  Performs a bitwise OR of an 8-bit PCI configuration register with
> > +  an 8-bit value.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 8-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  OrData  The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressOr8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT8                     OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> > +  value.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 8-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressAnd8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT8                     AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
> > +  value, followed a  bitwise OR with another 8-bit value.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData,
> > +  performs a bitwise OR between the result of the AND operation and
> > +  the value specified by OrData, and writes the result to the 8-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressAndThenOr8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT8                     AndData,
> > +  IN      UINT8                     OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioAndThenOr8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field of a PCI configuration register.
> > +
> > +  Reads the bit field in an 8-bit PCI configuration register. The bit field is
> > +  specified by the StartBit and the EndBit. The value of the bit field is
> > +  returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to read.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +
> > +  @return The value of the bit field read from the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldRead8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldRead8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit
> > +           );
> > +}
> > +
> > +/**
> > +  Writes a bit field to a PCI configuration register.
> > +
> > +  Writes Value to the bit field of the PCI configuration register. The bit
> > +  field is specified by the StartBit and the EndBit. All other bits in the
> > +  destination PCI configuration register are preserved. The new value of the
> > +  8-bit register is returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  Value     The new value of the bit field.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldWrite8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT8                     Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldWrite8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           Value
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
> > +  writes the result back to the bit field in the 8-bit port.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 8-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized. Extra left bits in OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  OrData    The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldOr8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT8                     OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldOr8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
> > +  AND, and writes the result back to the bit field in the 8-bit register.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 8-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized. Extra left bits in AndData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldAnd8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT8                     AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldAnd8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
> > +  bitwise OR, and writes the result back to the bit field in the
> > +  8-bit port.
> > +
> > +  Reads the 8-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND followed by a bitwise OR between the read result and
> > +  the value specified by AndData, and writes the result to the 8-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized. Extra left bits in both AndData and
> > +  OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If StartBit is greater than 7, then ASSERT().
> > +  If EndBit is greater than 7, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..7.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +  @param  OrData    The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT8
> > +EFIAPI
> > +PciExpressBitFieldAndThenOr8 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT8                     AndData,
> > +  IN      UINT8                     OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xff;
> > +  }
> > +  return MmioBitFieldAndThenOr8 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a 16-bit PCI configuration register.
> > +
> > +  Reads and returns the 16-bit PCI configuration register specified by Address.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +
> > +  @return The read value from the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressRead16 (
> > +  IN      UINTN                     Address
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
> > +}
> > +
> > +/**
> > +  Writes a 16-bit PCI configuration register.
> > +
> > +  Writes the 16-bit PCI configuration register specified by Address with the
> > +  value specified by Value. Value is returned. This function must guarantee
> > +  that all PCI read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  Value   The value to write.
> > +
> > +  @return The value written to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressWrite16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> > +}
> > +
> > +/**
> > +  Performs a bitwise OR of a 16-bit PCI configuration register with
> > +  a 16-bit value.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 16-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  OrData  The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> > +  value.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 16-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressAnd16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
> > +  value, followed a  bitwise OR with another 16-bit value.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData,
> > +  performs a bitwise OR between the result of the AND operation and
> > +  the value specified by OrData, and writes the result to the 16-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressAndThenOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    AndData,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioAndThenOr16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field of a PCI configuration register.
> > +
> > +  Reads the bit field in a 16-bit PCI configuration register. The bit field is
> > +  specified by the StartBit and the EndBit. The value of the bit field is
> > +  returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to read.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +
> > +  @return The value of the bit field read from the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldRead16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldRead16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit
> > +           );
> > +}
> > +
> > +/**
> > +  Writes a bit field to a PCI configuration register.
> > +
> > +  Writes Value to the bit field of the PCI configuration register. The bit
> > +  field is specified by the StartBit and the EndBit. All other bits in the
> > +  destination PCI configuration register are preserved. The new value of the
> > +  16-bit register is returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  Value     The new value of the bit field.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldWrite16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT16                    Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldWrite16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           Value
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
> > +  writes the result back to the bit field in the 16-bit port.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 16-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized. Extra left bits in OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  OrData    The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldOr16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
> > +  AND, and writes the result back to the bit field in the 16-bit register.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 16-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized. Extra left bits in AndData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldAnd16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT16                    AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldAnd16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
> > +  bitwise OR, and writes the result back to the bit field in the
> > +  16-bit port.
> > +
> > +  Reads the 16-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND followed by a bitwise OR between the read result and
> > +  the value specified by AndData, and writes the result to the 16-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized. Extra left bits in both AndData and
> > +  OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +  If StartBit is greater than 15, then ASSERT().
> > +  If EndBit is greater than 15, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..15.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +  @param  OrData    The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +PciExpressBitFieldAndThenOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT16                    AndData,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffff;
> > +  }
> > +  return MmioBitFieldAndThenOr16 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a 32-bit PCI configuration register.
> > +
> > +  Reads and returns the 32-bit PCI configuration register specified by Address.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +
> > +  @return The read value from the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressRead32 (
> > +  IN      UINTN                     Address
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address);
> > +}
> > +
> > +/**
> > +  Writes a 32-bit PCI configuration register.
> > +
> > +  Writes the 32-bit PCI configuration register specified by Address with the
> > +  value specified by Value. Value is returned. This function must guarantee
> > +  that all PCI read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  Value   The value to write.
> > +
> > +  @return The value written to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressWrite32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
> > +}
> > +
> > +/**
> > +  Performs a bitwise OR of a 32-bit PCI configuration register with
> > +  a 32-bit value.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 32-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  OrData  The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> > +  value.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 32-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressAnd32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
> > +}
> > +
> > +/**
> > +  Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
> > +  value, followed a  bitwise OR with another 32-bit value.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData,
> > +  performs a bitwise OR between the result of the AND operation and
> > +  the value specified by OrData, and writes the result to the 32-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The address that encodes the PCI Bus, Device, Function and
> > +                  Register.
> > +  @param  AndData The value to AND with the PCI configuration register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressAndThenOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    AndData,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioAndThenOr32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field of a PCI configuration register.
> > +
> > +  Reads the bit field in a 32-bit PCI configuration register. The bit field is
> > +  specified by the StartBit and the EndBit. The value of the bit field is
> > +  returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to read.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +
> > +  @return The value of the bit field read from the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldRead32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldRead32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit
> > +           );
> > +}
> > +
> > +/**
> > +  Writes a bit field to a PCI configuration register.
> > +
> > +  Writes Value to the bit field of the PCI configuration register. The bit
> > +  field is specified by the StartBit and the EndBit. All other bits in the
> > +  destination PCI configuration register are preserved. The new value of the
> > +  32-bit register is returned.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  Value     The new value of the bit field.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldWrite32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT32                    Value
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldWrite32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           Value
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
> > +  writes the result back to the bit field in the 32-bit port.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise OR between the read result and the value specified by
> > +  OrData, and writes the result to the 32-bit PCI configuration register
> > +  specified by Address. The value written to the PCI configuration register is
> > +  returned. This function must guarantee that all PCI read and write operations
> > +  are serialized. Extra left bits in OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  OrData    The value to OR with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldOr32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
> > +  AND, and writes the result back to the bit field in the 32-bit register.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND between the read result and the value specified by AndData, and
> > +  writes the result to the 32-bit PCI configuration register specified by
> > +  Address. The value written to the PCI configuration register is returned.
> > +  This function must guarantee that all PCI read and write operations are
> > +  serialized. Extra left bits in AndData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldAnd32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT32                    AndData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldAnd32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
> > +  bitwise OR, and writes the result back to the bit field in the
> > +  32-bit port.
> > +
> > +  Reads the 32-bit PCI configuration register specified by Address, performs a
> > +  bitwise AND followed by a bitwise OR between the read result and
> > +  the value specified by AndData, and writes the result to the 32-bit PCI
> > +  configuration register specified by Address. The value written to the PCI
> > +  configuration register is returned. This function must guarantee that all PCI
> > +  read and write operations are serialized. Extra left bits in both AndData and
> > +  OrData are stripped.
> > +
> > +  If Address > 0x0FFFFFFF, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +  If StartBit is greater than 31, then ASSERT().
> > +  If EndBit is greater than 31, then ASSERT().
> > +  If EndBit is less than StartBit, then ASSERT().
> > +  If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +  If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
> > +
> > +  @param  Address   The PCI configuration register to write.
> > +  @param  StartBit  The ordinal of the least significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  EndBit    The ordinal of the most significant bit in the bit field.
> > +                    Range 0..31.
> > +  @param  AndData   The value to AND with the PCI configuration register.
> > +  @param  OrData    The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the PCI configuration register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +PciExpressBitFieldAndThenOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINTN                     StartBit,
> > +  IN      UINTN                     EndBit,
> > +  IN      UINT32                    AndData,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  ASSERT_INVALID_PCI_ADDRESS (Address);
> > +  if (IgnoreBusDeviceFunction (Address)) {
> > +    return 0xffffffff;
> > +  }
> > +  return MmioBitFieldAndThenOr32 (
> > +           (UINTN) GetPciExpressBaseAddress () + Address,
> > +           StartBit,
> > +           EndBit,
> > +           AndData,
> > +           OrData
> > +           );
> > +}
> > +
> > +/**
> > +  Reads a range of PCI configuration registers into a caller supplied buffer.
> > +
> > +  Reads the range of PCI configuration registers specified by StartAddress and
> > +  Size into the buffer specified by Buffer. This function only allows the PCI
> > +  configuration registers from a single PCI function to be read. Size is
> > +  returned. When possible 32-bit PCI configuration read cycles are used to read
> > +  from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit
> > +  and 16-bit PCI configuration read cycles may be used at the beginning and the
> > +  end of the range.
> > +
> > +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> > +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> > +  If Size > 0 and Buffer is NULL, then ASSERT().
> > +
> > +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> > +                        Function and Register.
> > +  @param  Size          The size in bytes of the transfer.
> > +  @param  Buffer        The pointer to a buffer receiving the data read.
> > +
> > +  @return Size read data from StartAddress.
> > +
> > +**/
> > +UINTN
> > +EFIAPI
> > +PciExpressReadBuffer (
> > +  IN      UINTN                     StartAddress,
> > +  IN      UINTN                     Size,
> > +  OUT     VOID                      *Buffer
> > +  )
> > +{
> > +  UINTN   ReturnValue;
> > +
> > +  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
> > +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> > +
> > +  if (Size == 0) {
> > +    return Size;
> > +  }
> > +
> > +  ASSERT (Buffer != NULL);
> > +
> > +  //
> > +  // Save Size for return
> > +  //
> > +  ReturnValue = Size;
> > +
> > +  if ((StartAddress & 1) != 0) {
> > +    //
> > +    // Read a byte if StartAddress is byte aligned
> > +    //
> > +    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
> > +    StartAddress += sizeof (UINT8);
> > +    Size -= sizeof (UINT8);
> > +    Buffer = (UINT8*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
> > +    //
> > +    // Read a word if StartAddress is word aligned
> > +    //
> > +    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
> > +
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + 1;
> > +  }
> > +
> > +  while (Size >= sizeof (UINT32)) {
> > +    //
> > +    // Read as many double words as possible
> > +    //
> > +    WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress));
> > +
> > +    StartAddress += sizeof (UINT32);
> > +    Size -= sizeof (UINT32);
> > +    Buffer = (UINT32*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16)) {
> > +    //
> > +    // Read the last remaining word if exist
> > +    //
> > +    WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT8)) {
> > +    //
> > +    // Read the last remaining byte if exist
> > +    //
> > +    *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
> > +  }
> > +
> > +  return ReturnValue;
> > +}
> > +
> > +/**
> > +  Copies the data in a caller supplied buffer to a specified range of PCI
> > +  configuration space.
> > +
> > +  Writes the range of PCI configuration registers specified by StartAddress and
> > +  Size from the buffer specified by Buffer. This function only allows the PCI
> > +  configuration registers from a single PCI function to be written. Size is
> > +  returned. When possible 32-bit PCI configuration write cycles are used to
> > +  write from StartAddress to StartAddress + Size. Due to alignment restrictions,
> > +  8-bit and 16-bit PCI configuration write cycles may be used at the beginning
> > +  and the end of the range.
> > +
> > +  If StartAddress > 0x0FFFFFFF, then ASSERT().
> > +  If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
> > +  If Size > 0 and Buffer is NULL, then ASSERT().
> > +
> > +  @param  StartAddress  The starting address that encodes the PCI Bus, Device,
> > +                        Function and Register.
> > +  @param  Size          The size in bytes of the transfer.
> > +  @param  Buffer        The pointer to a buffer containing the data to write.
> > +
> > +  @return Size written to StartAddress.
> > +
> > +**/
> > +UINTN
> > +EFIAPI
> > +PciExpressWriteBuffer (
> > +  IN      UINTN                     StartAddress,
> > +  IN      UINTN                     Size,
> > +  IN      VOID                      *Buffer
> > +  )
> > +{
> > +  UINTN                             ReturnValue;
> > +
> > +  ASSERT_INVALID_PCI_ADDRESS (StartAddress);
> > +  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
> > +
> > +  if (Size == 0) {
> > +    return 0;
> > +  }
> > +
> > +  ASSERT (Buffer != NULL);
> > +
> > +  //
> > +  // Save Size for return
> > +  //
> > +  ReturnValue = Size;
> > +
> > +  if ((StartAddress & 1) != 0) {
> > +    //
> > +    // Write a byte if StartAddress is byte aligned
> > +    //
> > +    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
> > +    StartAddress += sizeof (UINT8);
> > +    Size -= sizeof (UINT8);
> > +    Buffer = (UINT8*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
> > +    //
> > +    // Write a word if StartAddress is word aligned
> > +    //
> > +    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + 1;
> > +  }
> > +
> > +  while (Size >= sizeof (UINT32)) {
> > +    //
> > +    // Write as many double words as possible
> > +    //
> > +    PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
> > +    StartAddress += sizeof (UINT32);
> > +    Size -= sizeof (UINT32);
> > +    Buffer = (UINT32*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16)) {
> > +    //
> > +    // Write the last remaining word if exist
> > +    //
> > +    PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + 1;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT8)) {
> > +    //
> > +    // Write the last remaining byte if exist
> > +    //
> > +    PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
> > +  }
> > +
> > +  return ReturnValue;
> > +}
> > --
> > 2.7.4
> >

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-platforms: PATCH 11/14] Marvell/Armada70x0Db: Enable ACPI PCIE support
  2019-05-09  9:53 ` [edk2-platforms: PATCH 11/14] Marvell/Armada70x0Db: " Marcin Wojtas
@ 2019-05-16 14:26   ` Ard Biesheuvel
  0 siblings, 0 replies; 36+ messages in thread
From: Ard Biesheuvel @ 2019-05-16 14:26 UTC (permalink / raw)
  To: edk2-devel-groups-io, Marcin Wojtas
  Cc: Leif Lindholm, Jan Dąbroś, Grzegorz Jaszczyk,
	Kostya Porotchkin, Jici Gao, Rebecca Cran, Mark Kettenis

On Thu, 9 May 2019 at 11:54, Marcin Wojtas <mw@semihalf.com> wrote:
>
> This patch adds description of the PCIE controller in
> ACPI tables of Armada 7040 DB board.
>

Idem

> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf       |   1 +
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h    |  25 +++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl  | 217 ++++++++++++++++++++
>  Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc |  47 +++++
>  4 files changed, 290 insertions(+)
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc
>
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf
> index 659c333..96bcdf0 100644
> --- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db.inf
> @@ -25,6 +25,7 @@
>
>  [Sources]
>    Armada70x0Db/Dsdt.asl
> +  Armada70x0Db/Mcfg.aslc
>    Fadt.aslc
>    Gtdt.aslc
>    Madt.aslc
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h
> new file mode 100644
> index 0000000..93631c2
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Pcie.h
> @@ -0,0 +1,25 @@
> +/**
> +
> +  Copyright (C) 2019, Marvell International Ltd. and its affiliates.
> +
> +  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.
> +
> +**/
> +
> +#define PCI_BUS_MIN        0x0
> +#define PCI_BUS_MAX        0x0
> +#define PCI_BUS_COUNT      0x1
> +#define PCI_MMIO32_BASE    0xC0000000
> +#define PCI_MMIO32_SIZE    0x20000000
> +#define PCI_MMIO64_BASE    0x800000000
> +#define PCI_MMIO64_SIZE    0x100000000
> +#define PCI_IO_BASE        0x0
> +#define PCI_IO_SIZE        0x10000
> +#define PCI_IO_TRANSLATION 0xEFF00000
> +#define PCI_ECAM_BASE      0xE0008000
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl
> index 621b688..a23bd70 100644
> --- a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Dsdt.asl
> @@ -15,6 +15,7 @@
>
>  **/
>
> +#include "Armada70x0Db/Pcie.h"
>  #include "IcuInterrupts.h"
>
>  DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA7K", 3)
> @@ -225,5 +226,221 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "MVEBU ", "ARMADA7K", 3)
>                  }
>              })
>          }
> +
> +        //
> +        // PCIe Root Bus
> +        //
> +        Device (PCI0)
> +        {
> +            Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
> +            Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
> +            Name (_SEG, 0x00)  // _SEG: PCI Segment
> +            Name (_BBN, 0x00)  // _BBN: BIOS Bus Number
> +            Name (_CCA, 0x01)  // _CCA: Cache Coherency Attribute
> +            Name (_PRT, Package ()  // _PRT: PCI Routing Table
> +            {
> +                Package () { 0xFFFF, 0x0, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x1, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x2, 0x0, 0x40 },
> +                Package () { 0xFFFF, 0x3, 0x0, 0x40 }
> +            })
> +
> +            Method (_CRS, 0, Serialized)  // _CRS: Current Resource Settings
> +            {
> +                Name (RBUF, ResourceTemplate ()
> +                {
> +                    WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
> +                        0x0000,                             // Granularity
> +                        PCI_BUS_MIN,                        // Range Minimum
> +                        PCI_BUS_MAX,                        // Range Maximum
> +                        0x0000,                             // Translation Offset
> +                        PCI_BUS_COUNT                       // Length
> +                        )
> +                    DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
> +                        0x00000000,                         // Granularity
> +                        PCI_MMIO32_BASE,                    // Range Minimum
> +                        0xDFFFFFFF,                         // Range Maximum
> +                        0x00000000,                         // Translation Offset
> +                        PCI_MMIO32_SIZE                     // Length
> +                        )
> +                    QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
> +                        0x0000000000000000,                 // Granularity
> +                        PCI_MMIO64_BASE,                    // Range Minimum
> +                        0x8FFFFFFFF,                        // Range Maximum
> +                        0x00000000,                         // Translation Offset
> +                        PCI_MMIO64_SIZE                     // Length
> +                        )
> +                    DWordIo (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
> +                        0x00000000,                         // Granularity
> +                        PCI_IO_BASE,                        // Range Minimum
> +                        0x0000FFFF,                         // Range Maximum
> +                        PCI_IO_TRANSLATION,                 // Translation Address
> +                        PCI_IO_SIZE,                        // Length
> +                        ,
> +                        ,
> +                        ,
> +                        TypeTranslation
> +                        )
> +                })
> +                Return (RBUF) /* \_SB_.PCI0._CRS.RBUF */
> +            } // Method(_CRS)
> +
> +            Device (RES0)
> +            {
> +                Name (_HID, "PNP0C02")
> +                Name (_CRS, ResourceTemplate ()
> +                {
> +                    Memory32Fixed (ReadWrite,
> +                                   PCI_ECAM_BASE,
> +                                   0x10000000
> +                                   )
> +                })
> +            }
> +            Name (SUPP, 0x00)
> +            Name (CTRL, 0x00)
> +            Method (_OSC, 4, NotSerialized)  // _OSC: Operating System Capabilities
> +            {
> +                CreateDWordField (Arg3, 0x00, CDW1)
> +                If (LEqual (Arg0, ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") /* PCI Host Bridge Device */))
> +                {
> +                    CreateDWordField (Arg3, 0x04, CDW2)
> +                    CreateDWordField (Arg3, 0x08, CDW3)
> +                    Store (CDW2, SUPP) /* \_SB_.PCI0.SUPP */
> +                    Store (CDW3, CTRL) /* \_SB_.PCI0.CTRL */
> +                    If (LNotEqual (And (SUPP, 0x16), 0x16))
> +                    {
> +                        And (CTRL, 0x1E, CTRL) /* \_SB_.PCI0.CTRL */
> +                    }
> +
> +                    And (CTRL, 0x1D, CTRL) /* \_SB_.PCI0.CTRL */
> +                    If (LNotEqual (Arg1, One))
> +                    {
> +                        Or (CDW1, 0x08, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    }
> +
> +                    If (LNotEqual (CDW3, CTRL))
> +                    {
> +                        Or (CDW1, 0x10, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    }
> +
> +                    Store (CTRL, CDW3) /* \_SB_.PCI0._OSC.CDW3 */
> +                    Return (Arg3)
> +                }
> +                Else
> +                {
> +                    Or (CDW1, 0x04, CDW1) /* \_SB_.PCI0._OSC.CDW1 */
> +                    Return (Arg3)
> +                }
> +            } // Method(_OSC)
> +
> +            //
> +            // Device-Specific Methods
> +            //
> +            Method(_DSM, 0x4, NotSerialized) {
> +              If (LEqual(Arg0, ToUUID("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
> +                switch (ToInteger(Arg2)) {
> +                  //
> +                  // Function 0: Return supported functions
> +                  //
> +                  case(0) {
> +                    Return (Buffer() {0xFF})
> +                  }
> +
> +                  //
> +                  // Function 1: Return PCIe Slot Information
> +                  //
> +                  case(1) {
> +                    Return (Package(2) {
> +                      One, // Success
> +                      Package(3) {
> +                        0x1,  // x1 PCIe link
> +                        0x1,  // PCI express card slot
> +                        0x1   // WAKE# signal supported
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 2: Return PCIe Slot Number.
> +                  //
> +                  case(2) {
> +                    Return (Package(1) {
> +                      Package(4) {
> +                        2,  // Source ID
> +                        4,  // Token ID: ID refers to a slot
> +                        0,  // Start bit of the field to use.
> +                        7   // End bit of the field to use.
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 4: Return PCI Bus Capabilities
> +                  //
> +                  case(4) {
> +                    Return (Package(2) {
> +                      One, // Success
> +                      Buffer() {
> +                        1,0,            // Version
> +                        0,0,            // Status, 0:Success
> +                        24,0,0,0,       // Length
> +                        1,0,            // PCI
> +                        16,0,           // Length
> +                        0,              // Attributes
> +                        0x0D,           // Current Speed/Mode
> +                        0x3F,0,         // Supported Speeds/Modes
> +                        0,              // Voltage
> +                        0,0,0,0,0,0,0   // Reserved
> +                      }
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 5: Return Ignore PCI Boot Configuration
> +                  //
> +                  case(5) {
> +                    Return (Package(1) {1})
> +                  }
> +
> +                  //
> +                  // Function 6: Return LTR Maximum Latency
> +                  //
> +                  case(6) {
> +                    Return (Package(4) {
> +                      Package(1){0},  // Maximum Snoop Latency Scale
> +                      Package(1){0},  // Maximum Snoop Latency Value
> +                      Package(1){0},  // Maximum No-Snoop Latency Scale
> +                      Package(1){0}   // Maximum No-Snoop Latency Value
> +                    })
> +                  }
> +
> +                  //
> +                  // Function 7: Return PCI Express Naming
> +                  //
> +                  case(7) {
> +                    Return (Package(2) {
> +                      Package(1) {0},
> +                      Package(1) {Unicode("PCI0")}
> +                    })
> +                  }
> +
> +                  //
> +                  // Not supported
> +                  //
> +                  default {
> +                  }
> +                }
> +              }
> +              Return (Buffer(){0})
> +            } // Method(_DSM)
> +
> +            //
> +            // Root-Complex 0
> +            //
> +            Device (RP0)
> +            {
> +                Name (_ADR, PCI_ECAM_BASE)  // _ADR: Bus 0, Dev 0, Func 0
> +            }
> +        }
>      }
>  }
> diff --git a/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc
> new file mode 100644
> index 0000000..90bf163
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/AcpiTables/Armada70x0Db/Mcfg.aslc
> @@ -0,0 +1,47 @@
> +/** @file
> +
> +  Memory mapped config space base address table (MCFG)
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019, Marvell International Ltd. and its affiliates.<BR>
> +
> +  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 <Library/AcpiLib.h>
> +
> +#include "AcpiHeader.h"
> +#include "Armada70x0Db/Pcie.h"
> +
> +#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
> +
> +#pragma pack(1)
> +typedef struct {
> +  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
> +  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE Structure;
> +} ACPI_6_0_MCFG_STRUCTURE;
> +#pragma pack()
> +
> +STATIC ACPI_6_0_MCFG_STRUCTURE Mcfg = {
> +  {
> +    __ACPI_HEADER (EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
> +                   ACPI_6_0_MCFG_STRUCTURE,
> +                   EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION),
> +    EFI_ACPI_RESERVED_QWORD
> +  }, {
> +    PCI_ECAM_BASE,                   // BaseAddress
> +    0,                               // PciSegmentGroupNumber
> +    PCI_BUS_MIN,                     // StartBusNumber
> +    PCI_BUS_MAX,                     // EndBusNumber
> +    EFI_ACPI_RESERVED_DWORD          // Reserved
> +  }
> +};
> +
> +VOID CONST * CONST ReferenceAcpiTable = &Mcfg;
> --
> 2.7.4
>
>
> 
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-platforms: PATCH 08/14] Marvell/Armada7k8k: Enable PCIE support
  2019-05-16 14:25       ` Ard Biesheuvel
@ 2019-05-16 14:32         ` Leif Lindholm
  0 siblings, 0 replies; 36+ messages in thread
From: Leif Lindholm @ 2019-05-16 14:32 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Marcin Wojtas, edk2-devel-groups-io, Jan Dąbroś,
	Grzegorz Jaszczyk, Kostya Porotchkin, Jici Gao, Rebecca Cran,
	Mark Kettenis

On Thu, May 16, 2019 at 04:25:14PM +0200, Ard Biesheuvel wrote:
> > > This driver requires gArmTokenSpaceGuid.PcdPciIoTranslation to be set
> > > to a sane value. Are you sure this is the case for your platforms?
> > >
> >
> > Do you mean the IO space for the controller? If yes, I'll set the PCD
> > to according value I use in board description. I don't have an old
> > enough endpoint that requires IO space to test :)
> >
> 
> Yes, it is basically the MMIO address of the I/O space.
> 
> Leif kindly gave me a PCIe serial port controller that I use
> especially for testing these things at plugfests.

This one in fact:
https://www.amazon.co.uk/gp/product/B00NNRYZOE/

/
    Leif

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2019-05-16 14:32 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-09  9:53 [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Marcin Wojtas
2019-05-09  9:53 ` [edk2-platforms: PATCH 01/14] Marvell/Library: MvGpioLib: Extend GPIO pin description Marcin Wojtas
2019-05-09  9:53 ` [edk2-platforms: PATCH 02/14] Marvell/Library: ArmadaSoCDescLib: Add PCIE information Marcin Wojtas
2019-05-10 14:59   ` Leif Lindholm
2019-05-10 15:03     ` Marcin Wojtas
2019-05-09  9:53 ` [edk2-platforms: PATCH 03/14] Marvell/Library: ArmadaBoardDescLib: " Marcin Wojtas
2019-05-16 13:57   ` Ard Biesheuvel
2019-05-09  9:53 ` [edk2-platforms: PATCH 04/14] Marvell/Armada7k8k: Extend board description libraries with PCIE Marcin Wojtas
2019-05-09 10:16   ` Marcin Wojtas
2019-05-09  9:53 ` [edk2-platforms: PATCH 05/14] Marvell/Armada7k8k: MvBoardDesc: Extend protocol with PCIE support Marcin Wojtas
2019-05-16 13:53   ` Ard Biesheuvel
2019-05-09  9:53 ` [edk2-platforms: PATCH 06/14] Marvell/Armada7k8k: Add PciExpressLib implementation Marcin Wojtas
2019-05-10 15:25   ` Leif Lindholm
2019-05-10 15:29     ` Marcin Wojtas
2019-05-16 14:02   ` Ard Biesheuvel
2019-05-16 14:26     ` Marcin Wojtas
2019-05-09  9:53 ` [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib Marcin Wojtas
2019-05-10 15:50   ` Leif Lindholm
2019-05-12 11:41     ` Marcin Wojtas
2019-05-16 14:14   ` Ard Biesheuvel
2019-05-09  9:53 ` [edk2-platforms: PATCH 08/14] Marvell/Armada7k8k: Enable PCIE support Marcin Wojtas
2019-05-16 14:16   ` Ard Biesheuvel
2019-05-16 14:22     ` Marcin Wojtas
2019-05-16 14:25       ` Ard Biesheuvel
2019-05-16 14:32         ` Leif Lindholm
2019-05-09  9:53 ` [edk2-platforms: PATCH 09/14] Marvell/Armada80x0McBin: Enable ACPI " Marcin Wojtas
2019-05-10 15:54   ` Leif Lindholm
2019-05-16 14:23   ` Ard Biesheuvel
2019-05-09  9:53 ` [edk2-platforms: PATCH 10/14] Marvell/Armada80x0Db: " Marcin Wojtas
2019-05-16 14:25   ` [edk2-devel] " Ard Biesheuvel
2019-05-09  9:53 ` [edk2-platforms: PATCH 11/14] Marvell/Armada70x0Db: " Marcin Wojtas
2019-05-16 14:26   ` [edk2-devel] " Ard Biesheuvel
2019-05-09  9:53 ` [edk2-platforms: PATCH 12/14] Marvell/Armada80x0McBin: DeviceTree: Use pci-host-generic driver Marcin Wojtas
2019-05-09  9:53 ` [edk2-platforms: PATCH 13/14] Marvell/Armada7k8k: Remove duplication in .dsc files Marcin Wojtas
2019-05-09  9:53 ` [edk2-platforms: PATCH 14/14] Marvell/Armada7k8: Add 'acpiview' shell command to build Marcin Wojtas
2019-05-10 15:58 ` [edk2-platforms: PATCH 00/14] Armada7k8k PCIE support Leif Lindholm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox