public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "John Chew" <yuinyee.chew@starfivetech.com>
To: <devel@edk2.groups.io>
Cc: mindachen1987 <minda.chen@starfivetech.com>,
	Sunil V L <sunilvl@ventanamicro.com>,
	Leif Lindholm <quic_llindhol@quicinc.com>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Li Yong <yong.li@intel.com>,
	John Chew <yuinyee.chew@starfivetech.com>
Subject: [edk2-devel] [PATCH v4 1/6] StarFive/JH7110Pkg: Add Pci controller driver
Date: Fri, 3 Nov 2023 10:30:50 +0800	[thread overview]
Message-ID: <20231103023055.1629-2-yuinyee.chew@starfivetech.com> (raw)
In-Reply-To: <20231103023055.1629-1-yuinyee.chew@starfivetech.com>

From: mindachen1987 <minda.chen@starfivetech.com>

Implement Pci Host Bridge and Pci Segment driver:
JH7110 SoC contains two PCI segment:

- PCI Segment 0 (USB):
    32-bit Memory: 0x3000_0000 ~ 0x3FFF_FFFF
    64-bit Memory: 0x9_0000_0000 ~0x9_4000_0000
- PCI Segment 1 (NVME):
    32-bit Memory: 0x3800_0000 ~ 0x37FF_FFFF
    64-bit Memory: 0x9_8000_0000 ~0x9_C000_0000

Non-prefetachable memory is not used in this configuration.

Cc: Sunil V L <sunilvl@ventanamicro.com>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Li Yong <yong.li@intel.com>
Co-authored-by: John Chew <yuinyee.chew@starfivetech.com>
Signed-off-by: mindachen1987 <minda.chen@starfivetech.com>
Acked-by: Sunil V L <sunilvl@ventanamicro.com>
---
 Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLib.c            |  263 ++++
 Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf          |   61 +
 Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLibConstructor.c |  406 ++++++
 Silicon/StarFive/JH7110Pkg/Library/PciSegmentLib/PciSegmentLib.c                  | 1460 ++++++++++++++++++++
 Silicon/StarFive/JH7110Pkg/Library/PciSegmentLib/PciSegmentLib.inf                |   33 +
 5 files changed, 2223 insertions(+)

diff --git a/Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
new file mode 100644
index 000000000000..8b46f6ff58e5
--- /dev/null
+++ b/Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -0,0 +1,263 @@
+/** @file

+ *

+ * PCI Host Bridge Library instance for StarFive JH7110 SOC

+ *

+ * Copyright (c) 2023, StarFive Technology Co., Ltd. All rights reserved.<BR>

+ *

+ * SPDX-License-Identifier: BSD-2-Clause-Patent

+ *

+ **/

+

+#include <IndustryStandard/JH7110.h>

+#include <IndustryStandard/Pci22.h>

+#include <Library/DebugLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/PcdLib.h>

+#include <Library/PciHostBridgeLib.h>

+#include <PiDxe.h>

+#include <Protocol/PciRootBridgeIo.h>

+#include <Protocol/PciHostBridgeResourceAllocation.h>

+

+#pragma pack(1)

+

+typedef PACKED struct {

+  ACPI_HID_DEVICE_PATH        AcpiDevicePath;

+  EFI_DEVICE_PATH_PROTOCOL    EndDevicePath;

+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;

+

+#pragma pack ()

+

+STATIC CONST 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

+      }

+    }

+  },

+

+  {

+    {

+      {

+        ACPI_DEVICE_PATH,

+        ACPI_DP,

+        {

+          (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),

+          (UINT8)(sizeof (ACPI_HID_DEVICE_PATH) >> 8)

+        }

+      },

+      EISA_PNP_ID (0x0A08), // PCI Express

+      1

+    },

+

+    {

+      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"

+};

+

+//

+// See description in MdeModulePkg/Include/Library/PciHostBridgeLib.h

+//

+PCI_ROOT_BRIDGE  mPciRootBridges[] = {

+  {

+    0,                                      // Segment

+    0,                                      // Supports

+    0,                                      // Attributes

+    FALSE,                                  // DmaAbove4G

+    FALSE,                                  // NoExtendedConfigSpace (true=256 byte config, false=4k)

+    FALSE,                                  // ResourceAssigned

+    EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |

+    EFI_PCI_HOST_BRIDGE_MEM64_DECODE,       // AllocationAttributes

+    {

+      // Bus

+      FixedPcdGet32 (PcdPciBusMin),

+      FixedPcdGet32 (PcdPciBusMax)

+    }, {

+      // Io

+      FixedPcdGet64 (PcdPciIoBase),

+      FixedPcdGet64 (PcdPciIoBase) + FixedPcdGet64 (PcdPciIoSize) - 1,

+      MAX_UINT64 - FixedPcdGet64 (PcdPciIoOffset) + 1

+    }, {

+      // Mem

+      FixedPcdGet32 (PcdPci0Mmio32Base),

+      FixedPcdGet32 (PcdPci0Mmio32Base) + FixedPcdGet32 (PcdPci0Mmio32Size) - 1

+    }, {

+      // MemAbove4G

+      FixedPcdGet64 (PcdPci0Mmio64Base),

+      FixedPcdGet64 (PcdPci0Mmio64Base) + FixedPcdGet64 (PcdPci0Mmio64Size) - 1

+    },

+    {

+      // Pefetchable Mem

+      MAX_UINT32,

+      0x0

+    }, {

+      // Pefetchable MemAbove4G

+      MAX_UINT64,

+      0x0

+    },

+    (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[0]

+  },

+  {

+    1,                                  // Segment

+    0,                                  // Supports

+    0,                                  // Attributes

+    FALSE,                              // DmaAbove4G

+    FALSE,                              // NoExtendedConfigSpace (true=256 byte config, false=4k)

+    FALSE,                              // ResourceAssigned

+    EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |

+    EFI_PCI_HOST_BRIDGE_MEM64_DECODE,   // AllocationAttributes

+    {

+      // Bus

+      FixedPcdGet32 (PcdPciBusMin),

+      FixedPcdGet32 (PcdPciBusMax)

+    }, {

+      // Io

+      FixedPcdGet64 (PcdPciIoBase),

+      FixedPcdGet64 (PcdPciIoBase) + FixedPcdGet64 (PcdPciIoSize) - 1,

+      MAX_UINT64 - FixedPcdGet64 (PcdPciIoOffset) + 1

+    }, {

+      // Mem

+      FixedPcdGet32 (PcdPci1Mmio32Base),

+      FixedPcdGet32 (PcdPci1Mmio32Base) + FixedPcdGet32 (PcdPci1Mmio32Size) - 1

+    }, {

+      // MemAbove4G

+      FixedPcdGet64 (PcdPci1Mmio64Base),

+      FixedPcdGet64 (PcdPci1Mmio64Base) + FixedPcdGet64 (PcdPci1Mmio64Size) - 1

+    },

+    {

+      // Pefetchable Mem

+      MAX_UINT32,

+      0x0

+    }, {

+      // Pefetchable MemAbove4G

+      MAX_UINT64,

+      0x0

+    },

+    (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[1]

+  }

+};

+

+/**

+  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 (

+  OUT UINTN  *Count

+  )

+{

+  *Count = ARRAY_SIZE (mPciRootBridges);

+  return mPciRootBridges;

+}

+

+/**

+  Free the root bridge instances array returned from PciHostBridgeGetRootBridges().

+

+  @param Bridges The root bridge instances array.

+  @param Count   The count of the array.

+**/

+VOID

+EFIAPI

+PciHostBridgeFreeRootBridges (

+  PCI_ROOT_BRIDGE  *Bridges,

+  UINTN            Count

+  )

+{

+}

+

+/**

+  Inform the platform that the resource conflict happens.

+

+  @param HostBridgeHandle Handle of the Host Bridge.

+  @param Configuration    Pointer to PCI I/O and PCI memory resource

+                          descriptors. The Configuration contains the resources

+                          for all the root bridges. The resource for each root

+                          bridge is terminated with END descriptor and an

+                          additional END is appended indicating the end of the

+                          entire resources. The resource descriptor field

+                          values follow the description in

+                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL

+                          .SubmitResources().

+**/

+VOID

+EFIAPI

+PciHostBridgeResourceConflict (

+  EFI_HANDLE  HostBridgeHandle,

+  VOID        *Configuration

+  )

+{

+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Descriptor;

+  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 <

+              ARRAY_SIZE (mPciHostBridgeLibAcpiAddressSpaceTypeStr)

+              );

+      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/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
new file mode 100644
index 000000000000..e18e8e57829f
--- /dev/null
+++ b/Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -0,0 +1,61 @@
+## @file

+#

+#  PCI Host Bridge Library instance for StarFive JH7110 SOC

+#  Liberally borrowed from the SynQuacer

+#

+#  Copyright (c) 2023, StarFive Technology Co., Ltd. All rights reserved.<BR>

+#

+#  SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010019

+  BASE_NAME                      = PciHostBridgeLib

+  FILE_GUID                      = 606d906f-eba7-d5c6-fcf0-6aeedea00193

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = PciHostBridgeLib|DXE_DRIVER

+  CONSTRUCTOR                    = JH7110PciHostBridgeLibConstructor

+

+#

+# The following information is for reference only and not required by the build

+# tools.

+#

+#  VALID_ARCHITECTURES           = ARM AARCH64 RISCV64

+#

+

+[Sources]

+  PciHostBridgeLib.c

+  PciHostBridgeLibConstructor.c

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  Silicon/StarFive/JH7110Pkg/JH7110Pkg.dec

+

+[LibraryClasses]

+  DebugLib

+  DevicePathLib

+  MemoryAllocationLib

+  PcdLib

+  UefiBootServicesTableLib

+

+[FixedPcd]

+  gJH7110TokenSpaceGuid.PcdPciRegBase

+  gJH7110TokenSpaceGuid.PcdPciBusMmioAdr

+  gJH7110TokenSpaceGuid.PcdPciBusMmioLen

+  gJH7110TokenSpaceGuid.PcdPciCpuMmioAdr

+  gJH7110TokenSpaceGuid.PcdPciBusMin

+  gJH7110TokenSpaceGuid.PcdPciBusMax

+  gJH7110TokenSpaceGuid.PcdPciIoBase

+  gJH7110TokenSpaceGuid.PcdPciIoSize

+  gJH7110TokenSpaceGuid.PcdPciIoOffset

+  gJH7110TokenSpaceGuid.PcdPci0Mmio32Base

+  gJH7110TokenSpaceGuid.PcdPci0Mmio32Size

+  gJH7110TokenSpaceGuid.PcdPci0Mmio64Base

+  gJH7110TokenSpaceGuid.PcdPci0Mmio64Size

+  gJH7110TokenSpaceGuid.PcdPci1Mmio32Base

+  gJH7110TokenSpaceGuid.PcdPci1Mmio32Size

+  gJH7110TokenSpaceGuid.PcdPci1Mmio64Base

+  gJH7110TokenSpaceGuid.PcdPci1Mmio64Size

diff --git a/Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLibConstructor.c b/Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLibConstructor.c
new file mode 100644
index 000000000000..cc505f2723d1
--- /dev/null
+++ b/Silicon/StarFive/JH7110Pkg/Library/PciHostBridgeLib/PciHostBridgeLibConstructor.c
@@ -0,0 +1,406 @@
+/** @file

+ *

+ * PCI Host Bridge Library instance for StarFive JH7110 SOC

+ *

+ * Copyright (c) 2023, StarFive Technology Co., Ltd. All rights reserved.<BR>

+ *

+ * SPDX-License-Identifier: BSD-2-Clause-Patent

+ *

+ * This module initializes the Pci as close to a standard

+ * PCI root complex as possible. The general information

+ * for this driver was sourced from.

+ *

+ *

+ **/

+

+#include <IndustryStandard/JH7110.h>

+#include <IndustryStandard/Pci22.h>

+#include <Library/DebugLib.h>

+#include <Library/IoLib.h>

+#include <Library/PcdLib.h>

+#include <Library/PciHostBridgeLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <PiDxe.h>

+#include <Protocol/PciHostBridgeResourceAllocation.h>

+#include <Library/TimerLib.h>

+

+#define RegWrite(addr, data)  MmioWrite32((addr), (data))

+#define RegRead(addr, data)   ((data) = MmioRead32 (addr))

+

+#define STG_SYSCON_BASE  0x10240000

+

+#define STG_SYSCON_K_RP_NEP_MASK    (1 << 8)

+#define STG_SYSCON_CKREF_SRC_SHIFT  18

+#define STG_SYSCON_CKREF_SRC_MASK   (0x3 << 18)

+#define STG_SYSCON_CLKREQ_MASK      (1 << 22)

+#define STG_SYSCON_BASE             0x10240000

+#define SYS_CLK_BASE                0x13020000

+#define STG_CLK_BASE                0x10230000

+#define SYS_CLK_NOC_OFFSET          0x98

+#define STG_PCIE_CLK_OFFSET         0x20

+#define STG_PCIE_CLKS               0xc

+#define STG_PCIE_RESET_OFFSET       0x74

+#define SYS_GPIO_BASE               0x13040000

+

+#define PREF_MEM_WIN_64_SUPPORT  (1 << 3)

+#define PMSG_LTR_SUPPORT         (1 << 2)

+#define PDLA_LINK_SPEED_GEN2     (1 << 12)

+#define PLDA_FUNCTION_DIS        (1 << 15)

+#define PLDA_FUNC_NUM            4

+#define PLDA_PHY_FUNC_SHIFT      9

+#define PLDA_RP_ENABLE           1

+

+#define PCIE_BASIC_STATUS  0x018

+#define PCIE_CFGNUM        0x140

+#define IMASK_LOCAL        0x180

+#define ISTATUS_LOCAL      0x184

+#define IMSI_ADDR          0x190

+#define ISTATUS_MSI        0x194

+#define CFG_SPACE          0x1000

+#define GEN_SETTINGS       0x80

+#define PCIE_PCI_IDS       0x9C

+#define PCIE_WINROM        0xFC

+#define PMSG_SUPPORT_RX    0x3F0

+#define PCI_MISC           0xB4

+

+#define STG_SYSCON_AXI4_SLVL_ARFUNC_MASK   0x7FFF00

+#define STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT  0x8

+#define STG_SYSCON_AXI4_SLVL_AWFUNC_MASK   0x7FFF

+#define STG_SYSCON_AXI4_SLVL_AWFUNC_SHIFT  0x0

+

+#define XR3PCI_ATR_AXI4_SLV0       0x800

+#define XR3PCI_ATR_SRC_ADDR_LOW    0x0

+#define XR3PCI_ATR_SRC_ADDR_HIGH   0x4

+#define XR3PCI_ATR_TRSL_ADDR_LOW   0x8

+#define XR3PCI_ATR_TRSL_ADDR_HIGH  0xc

+#define XR3PCI_ATR_TRSL_PARAM      0x10

+#define XR3PCI_ATR_TABLE_OFFSET    0x20

+#define XR3PCI_ATR_MAX_TABLE_NUM   8

+

+#define XR3PCI_ATR_SRC_ADDR_MASK       0xfffff000

+#define XR3PCI_ATR_TRSL_ADDR_MASK      0xfffff000

+#define XR3PCI_ATR_SRC_WIN_SIZE_SHIFT  1

+#define XR3_PCI_ECAM_SIZE              28

+

+#define IDS_PCI_TO_PCI_BRIDGE  0x060400

+#define IDS_CLASS_CODE_SHIFT   8

+#define SYS_GPIO_OUTPUT_OFF    0x40

+

+UINT32  AtrTableNum;

+UINT64  PCIE_CFG_BASE[2]      = { FixedPcdGet32 (PcdPci0Mmio64Base) + FixedPcdGet32 (PcdPci0Mmio64Size),

+                                  FixedPcdGet32 (PcdPci1Mmio64Base) + FixedPcdGet32 (PcdPci1Mmio64Size) };

+UINT64  PCI_MEMREGION_32[2]   = { FixedPcdGet32 (PcdPci0Mmio32Base), FixedPcdGet32 (PcdPci1Mmio32Base) };

+UINT64  PCI_MEMREGION_64[2]   = { FixedPcdGet32 (PcdPci0Mmio64Base), FixedPcdGet32 (PcdPci1Mmio64Base) };

+UINT64  PCI_MEMREGION_SIZE[2] = { 27, 30 };

+UINT32  STG_ARFUNC_OFFSET[2]  = { 0xc0, 0x270 };

+UINT32  STG_AWFUNC_OFFSET[2]  = { 0xc4, 0x274 };

+UINT32  STG_RP_REP_OFFSET[2]  = { 0x130, 0x2e0 };

+UINT32  PCIE_GPIO[2]          = { 26, 28 };

+

+STATIC inline UINT64

+GetPcieRegBase (

+  IN UINT32  Port

+  )

+{

+  return PCIE_REG_BASE + Port * 0x1000000;

+}

+

+VOID

+PcieRegWrite (

+  IN UINT32  Port,

+  IN UINTN   Offset,

+  IN UINT32  Value

+  )

+{

+  UINT64  Base = GetPcieRegBase (Port);

+

+  RegWrite ((UINT64)Base + Offset, Value);

+}

+

+UINT32

+PcieRegRead (

+  IN UINT32  Port,

+  IN UINTN   Offset

+  )

+{

+  UINT32  Value = 0;

+  UINT64  Base  = GetPcieRegBase (Port);

+

+  RegRead ((UINT64)Base + Offset, Value);

+  return Value;

+}

+

+STATIC VOID

+PcieUpdatebits (

+  IN UINT64  Base,

+  IN UINTN   Offset,

+  IN UINT32  Mask,

+  IN UINT32  val

+  )

+{

+  UINT32  Value = 0;

+

+  Value  = MmioRead32 ((UINT64)Base + Offset);

+  Value &= ~Mask;

+  Value |= val;

+  MmioWrite32 ((UINT64)Base + Offset, Value);

+}

+

+STATIC

+VOID

+PcieFuncSet (

+  IN UINT32  Port

+  )

+{

+  INTN    i;

+  UINT32  Value;

+  UINT64  Base = GetPcieRegBase (Port);

+

+  /* Disable physical functions except #0 */

+  for (i = 1; i < PLDA_FUNC_NUM; i++) {

+    PcieUpdatebits (

+                    STG_SYSCON_BASE,

+                    STG_ARFUNC_OFFSET[Port],

+                    STG_SYSCON_AXI4_SLVL_ARFUNC_MASK,

+                    (i << PLDA_PHY_FUNC_SHIFT) <<

+                    STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT

+                    );

+    PcieUpdatebits (

+                    STG_SYSCON_BASE,

+                    STG_AWFUNC_OFFSET[Port],

+                    STG_SYSCON_AXI4_SLVL_AWFUNC_MASK,

+                    (i << PLDA_PHY_FUNC_SHIFT) <<

+                    STG_SYSCON_AXI4_SLVL_AWFUNC_SHIFT

+                    );

+    PcieUpdatebits (

+                    Base,

+                    PCI_MISC,

+                    PLDA_FUNCTION_DIS,

+                    PLDA_FUNCTION_DIS

+                    );

+  }

+

+  PcieUpdatebits (

+                  STG_SYSCON_BASE,

+                  STG_ARFUNC_OFFSET[Port],

+                  STG_SYSCON_AXI4_SLVL_ARFUNC_MASK,

+                  0

+                  );

+  PcieUpdatebits (

+                  STG_SYSCON_BASE,

+                  STG_AWFUNC_OFFSET[Port],

+                  STG_SYSCON_AXI4_SLVL_AWFUNC_MASK,

+                  0

+                  );

+

+  /* Enable root port*/

+  PcieUpdatebits (

+                  Base,

+                  GEN_SETTINGS,

+                  PLDA_RP_ENABLE,

+                  PLDA_RP_ENABLE

+                  );

+

+  Value = (IDS_PCI_TO_PCI_BRIDGE << IDS_CLASS_CODE_SHIFT);

+  PcieRegWrite (Port, PCIE_PCI_IDS, Value);

+

+  PcieUpdatebits (

+                  Base,

+                  PMSG_SUPPORT_RX,

+                  PMSG_LTR_SUPPORT,

+                  0

+                  );

+

+  /* Prefetchable memory window 64-bit addressing support */

+  PcieUpdatebits (

+                  Base,

+                  PCIE_WINROM,

+                  PREF_MEM_WIN_64_SUPPORT,

+                  PREF_MEM_WIN_64_SUPPORT

+                  );

+}

+

+STATIC

+VOID

+PcieSTGInit (

+  IN UINT32  Port

+  )

+{

+  PcieUpdatebits (

+                  STG_SYSCON_BASE,

+                  STG_RP_REP_OFFSET[Port],

+                  STG_SYSCON_K_RP_NEP_MASK,

+                  STG_SYSCON_K_RP_NEP_MASK

+                  );

+  PcieUpdatebits (

+                  STG_SYSCON_BASE,

+                  STG_AWFUNC_OFFSET[Port],

+                  STG_SYSCON_CKREF_SRC_MASK,

+                  2 << STG_SYSCON_CKREF_SRC_SHIFT

+                  );

+  PcieUpdatebits (

+                  STG_SYSCON_BASE,

+                  STG_AWFUNC_OFFSET[Port],

+                  STG_SYSCON_CLKREQ_MASK,

+                  STG_SYSCON_CLKREQ_MASK

+                  );

+}

+

+STATIC

+VOID

+PcieClockInit (

+  IN UINT32  Port

+  )

+{

+  RegWrite (

+            STG_CLK_BASE + STG_PCIE_CLK_OFFSET

+            + Port * STG_PCIE_CLKS,

+            1 << 31

+            ); /*axi mst0*/

+  RegWrite (

+            STG_CLK_BASE + STG_PCIE_CLK_OFFSET

+            + Port * STG_PCIE_CLKS + 4,

+            1 << 31

+            ); /* apb */

+  RegWrite (

+            STG_CLK_BASE + STG_PCIE_CLK_OFFSET

+            + Port * STG_PCIE_CLKS + 8,

+            1 << 31

+            ); /* tl0 */

+}

+

+STATIC

+VOID

+PcieResetDeassert (

+  IN UINT32  Port

+  )

+{

+  UINT32  PortOffset = Port * 6 + 11;

+

+  PcieUpdatebits (

+                  STG_CLK_BASE,

+                  STG_PCIE_RESET_OFFSET,

+                  0x3f << (PortOffset),

+                  0

+                  ); /*reset all*/

+}

+

+VOID

+PcieResetAssert (

+  IN UINT32  Port

+  )

+{

+  UINT32  PortOffset = Port * 6 + 11;

+

+  PcieUpdatebits (

+                  STG_CLK_BASE,

+                  STG_PCIE_RESET_OFFSET,

+                  0x3f << (PortOffset),

+                  0x3f << (PortOffset)

+                  ); /*axi mst0*/

+}

+

+STATIC

+VOID

+PcieGpioResetSet (

+  IN UINT32  Port,

+  IN UINT32  Value

+  )

+{

+  UINT32  Remain, Mask;

+

+  Remain = PCIE_GPIO[Port] & 0x3;

+  Mask   = 0xff << (Remain * 8);

+  PcieUpdatebits (

+                  SYS_GPIO_BASE,

+                  SYS_GPIO_OUTPUT_OFF + (PCIE_GPIO[Port] & 0xfffc),

+                  Mask,

+                  Value << (Remain * 8)

+                  );

+}

+

+STATIC

+VOID

+PcieAtrInit (

+  IN UINT32  Port,

+  IN UINT64  SrcAddr,

+  IN UINT64  TrslAddr,

+  IN UINT32  WinSize,

+  IN UINT32  Config

+  )

+{

+  UINT64  Base = GetPcieRegBase (Port) + XR3PCI_ATR_AXI4_SLV0;

+  UINT32  Value;

+

+  Base +=  XR3PCI_ATR_TABLE_OFFSET * AtrTableNum;

+  AtrTableNum++;

+

+  /* X3PCI_ATR_SRC_ADDR_LOW:

+   *   - bit 0: enable entry,

+   *   - bits 1-6: ATR window size: total size in bytes: 2^(ATR_WSIZE + 1)

+   *   - bits 7-11: reserved

+   *   - bits 12-31: start of source address

+   */

+  Value = SrcAddr;

+

+  RegWrite (

+            Base + XR3PCI_ATR_SRC_ADDR_LOW,

+            (Value & XR3PCI_ATR_SRC_ADDR_MASK) | ((WinSize - 1) << 1) | 0x1

+            );

+  Value = SrcAddr >> 32;

+

+  RegWrite (Base + XR3PCI_ATR_SRC_ADDR_HIGH, Value);

+  Value = TrslAddr;

+  RegWrite (Base + XR3PCI_ATR_TRSL_ADDR_LOW, Value);

+  Value = TrslAddr >> 32;

+  RegWrite (Base + XR3PCI_ATR_TRSL_ADDR_HIGH, Value);

+  RegWrite (Base + XR3PCI_ATR_TRSL_PARAM, Config);

+}

+

+EFI_STATUS

+EFIAPI

+JH7110PciHostBridgeLibConstructor (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+  UINT32  PortIndex;

+

+  DEBUG ((DEBUG_ERROR, "PCIe RootBridge constructor\n"));

+  for (PortIndex = 0; PortIndex < 2; PortIndex++) {

+    PcieSTGInit (PortIndex);

+    RegWrite (SYS_CLK_BASE + SYS_CLK_NOC_OFFSET, 1 << 31);

+    PcieClockInit (PortIndex);

+    PcieResetDeassert (PortIndex);

+    PcieGpioResetSet (PortIndex, 0);

+    PcieFuncSet (PortIndex);

+

+    PcieAtrInit (

+                 PortIndex,

+                 PCIE_CFG_BASE[PortIndex],

+                 0,

+                 XR3_PCI_ECAM_SIZE,

+                 1

+                 );

+    PcieAtrInit (

+                 PortIndex,

+                 PCI_MEMREGION_32[PortIndex],

+                 PCI_MEMREGION_32[PortIndex],

+                 PCI_MEMREGION_SIZE[0],

+                 0

+                 );

+    PcieAtrInit (

+                 PortIndex,

+                 PCI_MEMREGION_64[PortIndex],

+                 PCI_MEMREGION_64[PortIndex],

+                 PCI_MEMREGION_SIZE[1],

+                 0

+                 );

+    PcieGpioResetSet (PortIndex, 1);

+    MicroSecondDelay (300);

+

+    DEBUG ((DEBUG_ERROR, "PCIe port %d init\n", PortIndex));

+  }

+

+  return EFI_SUCCESS;

+}

diff --git a/Silicon/StarFive/JH7110Pkg/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/StarFive/JH7110Pkg/Library/PciSegmentLib/PciSegmentLib.c
new file mode 100644
index 000000000000..43dca2a6236a
--- /dev/null
+++ b/Silicon/StarFive/JH7110Pkg/Library/PciSegmentLib/PciSegmentLib.c
@@ -0,0 +1,1460 @@
+/** @file

+ *

+ * PCI Segment Library for StarFive JH7110 SoC

+ *

+ * Copyright (c) 2023, StarFive Technology Co., Ltd. All rights reserved.<BR>

+ *

+ * SPDX-License-Identifier: BSD-2-Clause-Patent

+ *

+ **/

+

+#include <Base.h>

+#include <Uefi.h>

+#include <Library/BaseLib.h>

+#include <Library/DebugLib.h>

+#include <Library/IoLib.h>

+#include <Library/PcdLib.h>

+#include <Library/PciSegmentLib.h>

+#include <Library/UefiLib.h>

+#include <IndustryStandard/JH7110.h>

+#include <IndustryStandard/Pci30.h>

+

+typedef enum {

+  PciCfgWidthUint8 = 0,

+  PciCfgWidthUint16,

+  PciCfgWidthUint32,

+  PciCfgWidthMax

+} PCI_CFG_WIDTH;

+

+/*

+ * This PCIe config space is unusual...

+ * The root port is the first bytes of the register space (offset 0)

+ * The individual devices are then selected by computing their BDF index

+ * and writing that into the CFG_INDEX register (offset 0x9000)

+ * the "ECAM" data is then read/writeable at CFG_DATA (offset 0x8000)

+ */

+

+#define EFI_PCI_ADDR_BUS(bus)  ((bus >> 20) & 0xFF)   /* Note PCI_SEGMENT_LIB_ADDRESS */

+#define EFI_PCI_ADDR_DEV(dev)  ((dev >> 15) & 0x1F)

+#define EFI_PCI_ADDR_FUN(fun)  ((fun >> 12) & 0x07)

+

+/**

+  Assert the validity of a PCI Segment address.

+  A valid PCI Segment address should not contain 1's in bits 28..31 and 48..63

+

+  @param  A The address to validate.

+  @param  M Additional bits to assert to be zero.

+

+**/

+#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A, M) \

+  ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0)

+

+/**

+  Given the nature of how we access PCI devices, we ensure that

+  read/write accesses are serialized through the use of a lock.

+**/

+STATIC

+EFI_LOCK  mPciSegmentReadWriteLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);

+

+// STATIC UINT64 mPciSegmentLastAccess;     /* Avoid repeat CFG_INDEX updates */

+

+/**

+  Internal worker function to obtain config space base address.

+

+  @param  Address The address that encodes the PCI Bus, Device, Function and

+                  Register.

+

+  @return The value read from the PCI configuration register.

+

+**/

+STATIC

+UINT64

+PciSegmentLibGetConfigBase (

+  IN  UINT64  Address,

+  IN  UINT16  Segment,

+  IN  UINT32  Write

+  )

+{

+  UINT64  Base;

+  UINT64  Offset;

+  UINT32  Dev;

+  UINT32  Bus;

+

+  Base     = PCIE_CONFIG_BASE;

+  Offset   = Address & 0xFFF;      /* Pick off the 4k register offset */

+  Address &= 0xFFFF000;            /* Clear the offset leave only the BDF */

+

+  /* The root port is at the base of the PCIe register space */

+  if (Address != 0) {

+    Dev = EFI_PCI_ADDR_DEV (Address);

+    Bus = EFI_PCI_ADDR_BUS (Address);

+

+    /*

+     * There can only be a single device on bus 1 (downstream of root).

+     * Subsequent busses (behind a PCIe switch) can have more.

+     */

+    if (Dev > 0) {

+      return 0xFFFFFFFF;

+    }

+

+    return Base + Segment * 0x80000000 + Address + Offset;

+  } else {

+    if (Write && ((Offset == 0x10) || (Offset == 0x14))) {

+      return 0xFFFFFFFF;

+    }

+  }

+

+  return Base + Segment * 0x80000000 + Offset;

+}

+

+/**

+  Internal worker function to read a PCI configuration register.

+

+  @param  Address The address that encodes the PCI Bus, Device, Function and

+                  Register.

+  @param  Width   The width of data to read

+

+  @return The value read from the PCI configuration register.

+

+**/

+STATIC

+UINT32

+PciSegmentLibReadWorker (

+  IN  UINT64         Address,

+  IN  PCI_CFG_WIDTH  Width

+  )

+{

+  UINT64  Base;

+  UINT32  Ret;

+  UINT16  Segment = (Address >> 32);

+

+  EfiAcquireLock (&mPciSegmentReadWriteLock);

+  Base = PciSegmentLibGetConfigBase (Address, Segment, 0);

+

+  if (Base == 0xFFFFFFFF) {

+    EfiReleaseLock (&mPciSegmentReadWriteLock);

+    return Base;

+  }

+

+  switch (Width) {

+    case PciCfgWidthUint8:

+      Ret = MmioRead8 (Base);

+      break;

+    case PciCfgWidthUint16:

+      Ret = MmioRead16 (Base);

+      break;

+    case PciCfgWidthUint32:

+      Ret = MmioRead32 (Base);

+      break;

+    default:

+      ASSERT (FALSE);

+      Ret = 0;

+  }

+

+  EfiReleaseLock (&mPciSegmentReadWriteLock);

+  // DEBUG ((DEBUG_ERROR, "PCIe seg read Address %lx %lx width %d val %x Segment %d\n", Base, Address, Width, Ret, Segment));

+  return Ret;

+}

+

+/**

+  Internal worker function to writes a PCI configuration register.

+

+  @param  Address The address that encodes the PCI Bus, Device, Function and

+                  Register.

+  @param  Width   The width of data to write

+  @param  Data    The value to write.

+

+  @return The value written to the PCI configuration register.

+

+**/

+STATIC

+UINT32

+PciSegmentLibWriteWorker (

+  IN  UINT64         Address,

+  IN  PCI_CFG_WIDTH  Width,

+  IN  UINT32         Data

+  )

+{

+  UINT64  Base;

+  UINT16  Segment = (Address >> 32);

+

+  EfiAcquireLock (&mPciSegmentReadWriteLock);

+  Base = PciSegmentLibGetConfigBase (Address, Segment, 1);

+

+  if (Base == 0xFFFFFFFF) {

+    EfiReleaseLock (&mPciSegmentReadWriteLock);

+    return Data;

+  }

+

+  switch (Width) {

+    case PciCfgWidthUint8:

+      MmioWrite8 (Base, Data);

+      break;

+    case PciCfgWidthUint16:

+      MmioWrite16 (Base, Data);

+      break;

+    case PciCfgWidthUint32:

+      MmioWrite32 (Base, Data);

+      break;

+    default:

+      ASSERT (FALSE);

+  }

+

+  EfiReleaseLock (&mPciSegmentReadWriteLock);

+  return Data;

+}

+

+/**

+  Register a PCI device so PCI configuration registers may be accessed after

+  SetVirtualAddressMap().

+

+  If any reserved bits in Address are set, 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

+PciSegmentRegisterForRuntimeAccess (

+  IN UINTN  Address

+  )

+{

+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);

+  return RETURN_UNSUPPORTED;

+}

+

+/**

+  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 any reserved bits in Address are set, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function,

+                    and Register.

+

+  @return The 8-bit PCI configuration register specified by Address.

+

+**/

+UINT8

+EFIAPI

+PciSegmentRead8 (

+  IN UINT64  Address

+  )

+{

+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);

+

+  return (UINT8)PciSegmentLibReadWorker (Address, PciCfgWidthUint8);

+}

+

+/**

+  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 any reserved bits in Address are set, then ASSERT().

+

+  @param  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.

+  @param  Value       The value to write.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT8

+EFIAPI

+PciSegmentWrite8 (

+  IN UINT64  Address,

+  IN UINT8   Value

+  )

+{

+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);

+

+  return (UINT8)PciSegmentLibWriteWorker (Address, PciCfgWidthUint8, 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 any reserved bits in Address are set, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.

+  @param  OrData    The value to OR with the PCI configuration register.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT8

+EFIAPI

+PciSegmentOr8 (

+  IN UINT64  Address,

+  IN UINT8   OrData

+  )

+{

+  return PciSegmentWrite8 (Address, (UINT8)(PciSegmentRead8 (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 any reserved bits in Address are set, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.

+  @param  AndData   The value to AND with the PCI configuration register.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT8

+EFIAPI

+PciSegmentAnd8 (

+  IN UINT64  Address,

+  IN UINT8   AndData

+  )

+{

+  return PciSegmentWrite8 (Address, (UINT8)(PciSegmentRead8 (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 any reserved bits in Address are set, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.

+  @param  AndData    The value to AND with the PCI configuration register.

+  @param  OrData    The value to OR with the PCI configuration register.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT8

+EFIAPI

+PciSegmentAndThenOr8 (

+  IN UINT64  Address,

+  IN UINT8   AndData,

+  IN UINT8   OrData

+  )

+{

+  return PciSegmentWrite8 (Address, (UINT8)((PciSegmentRead8 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldRead8 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit

+  )

+{

+  return BitFieldRead8 (PciSegmentRead8 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldWrite8 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT8   Value

+  )

+{

+  return PciSegmentWrite8 (

+                           Address,

+                           BitFieldWrite8 (PciSegmentRead8 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldOr8 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT8   OrData

+  )

+{

+  return PciSegmentWrite8 (

+                           Address,

+                           BitFieldOr8 (PciSegmentRead8 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldAnd8 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT8   AndData

+  )

+{

+  return PciSegmentWrite8 (

+                           Address,

+                           BitFieldAnd8 (PciSegmentRead8 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldAndThenOr8 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT8   AndData,

+  IN UINT8   OrData

+  )

+{

+  return PciSegmentWrite8 (

+                           Address,

+                           BitFieldAndThenOr8 (PciSegmentRead8 (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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 16-bit boundary, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.

+

+  @return The 16-bit PCI configuration register specified by Address.

+

+**/

+UINT16

+EFIAPI

+PciSegmentRead16 (

+  IN UINT64  Address

+  )

+{

+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);

+

+  return (UINT16)PciSegmentLibReadWorker (Address, PciCfgWidthUint16);

+}

+

+/**

+  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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 16-bit boundary, then ASSERT().

+

+  @param  Address     The address that encodes the PCI Segment, Bus, Device, Function, and Register.

+  @param  Value       The value to write.

+

+  @return The parameter of Value.

+

+**/

+UINT16

+EFIAPI

+PciSegmentWrite16 (

+  IN UINT64  Address,

+  IN UINT16  Value

+  )

+{

+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);

+

+  return (UINT16)PciSegmentLibWriteWorker (Address, PciCfgWidthUint16, 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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 16-bit boundary, then ASSERT().

+

+  @param  Address The address that encodes the PCI Segment, 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

+PciSegmentOr16 (

+  IN UINT64  Address,

+  IN UINT16  OrData

+  )

+{

+  return PciSegmentWrite16 (Address, (UINT16)(PciSegmentRead16 (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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 16-bit boundary, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.

+  @param  AndData   The value to AND with the PCI configuration register.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT16

+EFIAPI

+PciSegmentAnd16 (

+  IN UINT64  Address,

+  IN UINT16  AndData

+  )

+{

+  return PciSegmentWrite16 (Address, (UINT16)(PciSegmentRead16 (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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 16-bit boundary, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.

+  @param  AndData   The value to AND with the PCI configuration register.

+  @param  OrData    The value to OR with the PCI configuration register.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT16

+EFIAPI

+PciSegmentAndThenOr16 (

+  IN UINT64  Address,

+  IN UINT16  AndData,

+  IN UINT16  OrData

+  )

+{

+  return PciSegmentWrite16 (Address, (UINT16)((PciSegmentRead16 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldRead16 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit

+  )

+{

+  return BitFieldRead16 (PciSegmentRead16 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldWrite16 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT16  Value

+  )

+{

+  return PciSegmentWrite16 (

+                            Address,

+                            BitFieldWrite16 (PciSegmentRead16 (Address), StartBit, EndBit, 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.

+

+  If any reserved bits in Address are set, 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

+PciSegmentBitFieldOr16 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT16  OrData

+  )

+{

+  return PciSegmentWrite16 (

+                            Address,

+                            BitFieldOr16 (PciSegmentRead16 (Address), StartBit, EndBit, OrData)

+                            );

+}

+

+/**

+  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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 16-bit boundary, 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 address that encodes the PCI Segment, Bus, Device, Function, and Register.

+  @param  StartBit  The ordinal of the least significant bit in the bit field.

+                    The ordinal of the least significant bit in a byte is bit 0.

+  @param  EndBit    The ordinal of the most significant bit in the bit field.

+                    The ordinal of the most significant bit in a byte is bit 7.

+  @param  AndData   The value to AND with the read value from the PCI configuration register.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT16

+EFIAPI

+PciSegmentBitFieldAnd16 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT16  AndData

+  )

+{

+  return PciSegmentWrite16 (

+                            Address,

+                            BitFieldAnd16 (PciSegmentRead16 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldAndThenOr16 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT16  AndData,

+  IN UINT16  OrData

+  )

+{

+  return PciSegmentWrite16 (

+                            Address,

+                            BitFieldAndThenOr16 (PciSegmentRead16 (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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 32-bit boundary, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function,

+                    and Register.

+

+  @return The 32-bit PCI configuration register specified by Address.

+

+**/

+UINT32

+EFIAPI

+PciSegmentRead32 (

+  IN UINT64  Address

+  )

+{

+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);

+

+  return PciSegmentLibReadWorker (Address, PciCfgWidthUint32);

+}

+

+/**

+  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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 32-bit boundary, then ASSERT().

+

+  @param  Address     The address that encodes the PCI Segment, Bus, Device,

+                      Function, and Register.

+  @param  Value       The value to write.

+

+  @return The parameter of Value.

+

+**/

+UINT32

+EFIAPI

+PciSegmentWrite32 (

+  IN UINT64  Address,

+  IN UINT32  Value

+  )

+{

+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);

+

+  return PciSegmentLibWriteWorker (Address, PciCfgWidthUint32, 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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 32-bit boundary, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function, and Register.

+  @param  OrData    The value to OR with the PCI configuration register.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT32

+EFIAPI

+PciSegmentOr32 (

+  IN UINT64  Address,

+  IN UINT32  OrData

+  )

+{

+  return PciSegmentWrite32 (Address, PciSegmentRead32 (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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 32-bit boundary, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function,

+                    and Register.

+  @param  AndData   The value to AND with the PCI configuration register.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT32

+EFIAPI

+PciSegmentAnd32 (

+  IN UINT64  Address,

+  IN UINT32  AndData

+  )

+{

+  return PciSegmentWrite32 (Address, PciSegmentRead32 (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 any reserved bits in Address are set, then ASSERT().

+  If Address is not aligned on a 32-bit boundary, then ASSERT().

+

+  @param  Address   The address that encodes the PCI Segment, Bus, Device, Function,

+                    and Register.

+  @param  AndData   The value to AND with the PCI configuration register.

+  @param  OrData    The value to OR with the PCI configuration register.

+

+  @return The value written to the PCI configuration register.

+

+**/

+UINT32

+EFIAPI

+PciSegmentAndThenOr32 (

+  IN UINT64  Address,

+  IN UINT32  AndData,

+  IN UINT32  OrData

+  )

+{

+  return PciSegmentWrite32 (Address, (PciSegmentRead32 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldRead32 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit

+  )

+{

+  return BitFieldRead32 (PciSegmentRead32 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldWrite32 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT32  Value

+  )

+{

+  return PciSegmentWrite32 (

+                            Address,

+                            BitFieldWrite32 (PciSegmentRead32 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldOr32 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT32  OrData

+  )

+{

+  return PciSegmentWrite32 (

+                            Address,

+                            BitFieldOr32 (PciSegmentRead32 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldAnd32 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT32  AndData

+  )

+{

+  return PciSegmentWrite32 (

+                            Address,

+                            BitFieldAnd32 (PciSegmentRead32 (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 any reserved bits in Address are set, 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

+PciSegmentBitFieldAndThenOr32 (

+  IN UINT64  Address,

+  IN UINTN   StartBit,

+  IN UINTN   EndBit,

+  IN UINT32  AndData,

+  IN UINT32  OrData

+  )

+{

+  return PciSegmentWrite32 (

+                            Address,

+                            BitFieldAndThenOr32 (PciSegmentRead32 (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 StartAdress 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 any reserved bits in StartAddress are set, 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 Segment, 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

+

+**/

+UINTN

+EFIAPI

+PciSegmentReadBuffer (

+  IN  UINT64  StartAddress,

+  IN  UINTN   Size,

+  OUT VOID    *Buffer

+  )

+{

+  UINTN  ReturnValue;

+

+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);

+  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);

+

+  if (Size == 0) {

+    return Size;

+  }

+

+  ASSERT (Buffer != NULL);

+

+  //

+  // Save Size for return

+  //

+  ReturnValue = Size;

+

+  if ((StartAddress & BIT0) != 0) {

+    //

+    // Read a byte if StartAddress is byte aligned

+    //

+    *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress);

+    StartAddress             += sizeof (UINT8);

+    Size                     -= sizeof (UINT8);

+    Buffer                    = (UINT8 *)Buffer + 1;

+  }

+

+  if ((Size >= sizeof (UINT16)) && ((StartAddress & BIT1) != 0)) {

+    //

+    // Read a word if StartAddress is word aligned

+    //

+    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));

+    StartAddress += sizeof (UINT16);

+    Size         -= sizeof (UINT16);

+    Buffer        = (UINT16 *)Buffer + 1;

+  }

+

+  while (Size >= sizeof (UINT32)) {

+    //

+    // Read as many double words as possible

+    //

+    WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));

+    StartAddress += sizeof (UINT32);

+    Size         -= sizeof (UINT32);

+    Buffer        = (UINT32 *)Buffer + 1;

+  }

+

+  if (Size >= sizeof (UINT16)) {

+    //

+    // Read the last remaining word if exist

+    //

+    WriteUnaligned16 (Buffer, PciSegmentRead16 (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 = PciSegmentRead8 (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 StartAdress 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 any reserved bits in StartAddress are set, 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 Segment, 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 The parameter of Size.

+

+**/

+UINTN

+EFIAPI

+PciSegmentWriteBuffer (

+  IN UINT64  StartAddress,

+  IN UINTN   Size,

+  IN VOID    *Buffer

+  )

+{

+  UINTN  ReturnValue;

+

+  ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);

+  ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);

+

+  if (Size == 0) {

+    return 0;

+  }

+

+  ASSERT (Buffer != NULL);

+

+  // The Bcm/Rpi has a single cfg which can be mapped

+  // to any given device on the bus, which means we need to remap

+  // it basically everytime a new config access is done

+

+  //

+  // Save Size for return

+  //

+  ReturnValue = Size;

+

+  if ((StartAddress & BIT0) != 0) {

+    //

+    // Write a byte if StartAddress is byte aligned

+    //

+    PciSegmentWrite8 (StartAddress, *(UINT8 *)Buffer);

+    StartAddress += sizeof (UINT8);

+    Size         -= sizeof (UINT8);

+    Buffer        = (UINT8 *)Buffer + 1;

+  }

+

+  if ((Size >= sizeof (UINT16)) && ((StartAddress & BIT1) != 0)) {

+    //

+    // Write a word if StartAddress is word aligned

+    //

+    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));

+    StartAddress += sizeof (UINT16);

+    Size         -= sizeof (UINT16);

+    Buffer        = (UINT16 *)Buffer + 1;

+  }

+

+  while (Size >= sizeof (UINT32)) {

+    //

+    // Write as many double words as possible

+    //

+    PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));

+    StartAddress += sizeof (UINT32);

+    Size         -= sizeof (UINT32);

+    Buffer        = (UINT32 *)Buffer + 1;

+  }

+

+  if (Size >= sizeof (UINT16)) {

+    //

+    // Write the last remaining word if exist

+    //

+    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));

+    StartAddress += sizeof (UINT16);

+    Size         -= sizeof (UINT16);

+    Buffer        = (UINT16 *)Buffer + 1;

+  }

+

+  if (Size >= sizeof (UINT8)) {

+    //

+    // Write the last remaining byte if exist

+    //

+    PciSegmentWrite8 (StartAddress, *(UINT8 *)Buffer);

+  }

+

+  return ReturnValue;

+}

diff --git a/Silicon/StarFive/JH7110Pkg/Library/PciSegmentLib/PciSegmentLib.inf b/Silicon/StarFive/JH7110Pkg/Library/PciSegmentLib/PciSegmentLib.inf
new file mode 100644
index 000000000000..063c85ebc428
--- /dev/null
+++ b/Silicon/StarFive/JH7110Pkg/Library/PciSegmentLib/PciSegmentLib.inf
@@ -0,0 +1,33 @@
+## @file

+# PCI Segment Library for StarFive JH7110 SoC

+#

+# Copyright (c) 2023, StarFive Technology Co., Ltd. All rights reserved.<BR>

+#

+#  SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x0001001B

+  BASE_NAME                      = PciSegmentLib

+  FILE_GUID                      = 832163a2-41f5-c529-3f02-77fb68abbc2c

+  MODULE_TYPE                    = BASE

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = PciSegmentLib

+

+[Sources]

+  PciSegmentLib.c

+

+[Packages]

+  MdePkg/MdePkg.dec

+  Silicon/StarFive/JH7110Pkg/JH7110Pkg.dec

+

+[LibraryClasses]

+  BaseLib

+  DebugLib

+  IoLib

+  PcdLib

+  UefiLib

+

+[FixedPcd]

+  gJH7110TokenSpaceGuid.PcdPciConfigRegBase

-- 
2.34.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110591): https://edk2.groups.io/g/devel/message/110591
Mute This Topic: https://groups.io/mt/102357025/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  reply	other threads:[~2023-11-03  2:32 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-03  2:30 [edk2-devel] [PATCH v4 0/6] StarFive/VisionFive2: Add VisionFive 2 platform John Chew
2023-11-03  2:30 ` John Chew [this message]
2023-11-03  2:30 ` [edk2-devel] [PATCH v4 2/6] StarFive/JH7110Pkg: Add SPI protocol and driver support John Chew
2023-11-03  2:30 ` [edk2-devel] [PATCH v4 3/6] StarFive/JH7110Pkg: Add firmware volume block protocol John Chew
2023-11-03  2:30 ` [edk2-devel] [PATCH v4 4/6] StarFive/JH7110Pkg: Add JH7110 Silicon Package John Chew
2023-11-03  2:30 ` [edk2-devel] [PATCH v4 5/6] StarFive/VisionFive2: Add VisionFive 2 platform John Chew
2023-11-03  2:30 ` [edk2-devel] [PATCH v4 6/6] Maintainers.txt: Add maintainers for StarFive platform John Chew
2023-11-15  1:39 ` [edk2-devel] [PATCH v4 0/6] StarFive/VisionFive2: Add VisionFive 2 platform John Chew

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231103023055.1629-2-yuinyee.chew@starfivetech.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox