public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH edk2-platforms 00/16] Add PCIe Support
@ 2020-05-21 23:02 Wasim Khan
  2020-05-21 23:02 ` [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs Wasim Khan
                   ` (16 more replies)
  0 siblings, 17 replies; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Add PCIe Support for NXP Layerscape SoC which supports
different PCIe controllers.
Use generic PCIe drivers and wire up PciHostBridgeLib,
PciSegmentLib and PciCpuIo2Dxe driver for controller
specific implementation.

Wasim Khan (16):
  Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs.
  Silicon/NXP: LS1043A: Define PCIe related PCDs
  Silicon/NXP: Implement PciHostBridgeLib support
  Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS
    Ctrl
  Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU
    Windows
  Silicon/NXP: PciHostBridgeLib: add Workaround for A-011451
  Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows
  Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows
  Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller
  Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS
    Controller
  Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller
  Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264
  Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver
  Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg
  Platform/NXP: LS1043aRdbPkg: Enable PCIE support
  Platform/NXP: LS1043aRdbPkg : Increase fv image size

 Silicon/NXP/NxpQoriqLs.dec                         |  13 +
 Silicon/NXP/LS1043A/LS1043A.dsc.inc                |   8 +
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc       |  20 +
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf       |  20 +-
 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf  |  40 +
 .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  45 ++
 .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  36 +
 Silicon/NXP/Include/Pcie.h                         | 231 ++++++
 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c    | 628 +++++++++++++++
 .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 842 +++++++++++++++++++++
 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 699 +++++++++++++++++
 11 files changed, 2579 insertions(+), 3 deletions(-)
 create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
 create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
 create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
 create mode 100755 Silicon/NXP/Include/Pcie.h
 create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c
 create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
 create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c

-- 
2.7.4


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

* [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs.
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:12   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 02/16] Silicon/NXP: LS1043A: Define " Wasim Khan
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Add PCIe related PCDs.

Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Silicon/NXP/NxpQoriqLs.dec | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
index 0722f59ef4f6..bafdfd9f4298 100644
--- a/Silicon/NXP/NxpQoriqLs.dec
+++ b/Silicon/NXP/NxpQoriqLs.dec
@@ -27,3 +27,12 @@ [Guids.common]
 [PcdsFeatureFlag]
   gNxpQoriqLsTokenSpaceGuid.PcdI2cErratumA009203|FALSE|BOOLEAN|0x00000315
   gNxpQoriqLsTokenSpaceGuid.PcdDcfgBigEndian|FALSE|BOOLEAN|0x00000316
+  gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian|FALSE|BOOLEAN|0x00000317
+
+[PcdsFixedAtBuild.common]
+  # Pcds for PCI Express
+  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr|0x0|UINT64|0x00000500
+  gNxpQoriqLsTokenSpaceGuid.PcdNumPciController|0|UINT32|0x00000501
+  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase|0x0|UINT32|0x00000502
+  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg|0x0|UINT32|0x00000503
+  gNxpQoriqLsTokenSpaceGuid.PcdPciDebug|FALSE|BOOLEAN|0x00000504
-- 
2.7.4


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

* [PATCH edk2-platforms 02/16] Silicon/NXP: LS1043A: Define PCIe related PCDs
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
  2020-05-21 23:02 ` [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-21 23:02 ` [PATCH edk2-platforms 03/16] Silicon/NXP: Implement PciHostBridgeLib support Wasim Khan
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Define PCIe related PCDs for LS1043A.

Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Silicon/NXP/LS1043A/LS1043A.dsc.inc | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Silicon/NXP/LS1043A/LS1043A.dsc.inc b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
index 67f5ba68dcd5..4b6eccc99885 100644
--- a/Silicon/NXP/LS1043A/LS1043A.dsc.inc
+++ b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
@@ -30,4 +30,12 @@ [PcdsFixedAtBuild.common]
 
 [PcdsFeatureFlag]
   gNxpQoriqLsTokenSpaceGuid.PcdDcfgBigEndian|TRUE
+  gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian|TRUE
+
+[PcdsFixedAtBuild.common]
+  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr|0x4000000000
+  gNxpQoriqLsTokenSpaceGuid.PcdNumPciController|3
+  gNxpQoriqLsTokenSpaceGuid.PcdPciDebug|FALSE
+  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase|0x10000
+  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg|0x7FC
 ##
-- 
2.7.4


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

* [PATCH edk2-platforms 03/16] Silicon/NXP: Implement PciHostBridgeLib support
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
  2020-05-21 23:02 ` [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs Wasim Khan
  2020-05-21 23:02 ` [PATCH edk2-platforms 02/16] Silicon/NXP: LS1043A: Define " Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:20   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 04/16] Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS Ctrl Wasim Khan
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Implement PciHostBridgeLib that exposes the PCIe root complexes to
the generic PCI host bridge driver.

Setup PCIe Layerscape Controller and setup CFG, IO,
MMIO and MMIO64 iATU windows.

Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  40 ++
 Silicon/NXP/Include/Pcie.h                         |  85 +++
 .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 568 +++++++++++++++++++++
 3 files changed, 693 insertions(+)
 create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
 create mode 100755 Silicon/NXP/Include/Pcie.h
 create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c

diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
new file mode 100644
index 000000000000..5ddb96e4fa6a
--- /dev/null
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -0,0 +1,40 @@
+## @file
+#  PCI Host Bridge Library instance for NXP ARM SOC
+#
+#  Copyright 2018-2020 NXP
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = PciHostBridgeLib
+  FILE_GUID                      = f4c99bcc-5c95-49ad-b0f3-fc5b611dc9c1
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciHostBridgeLib
+
+[Sources]
+  PciHostBridgeLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  Silicon/NXP/NxpQoriqLs.dec
+
+[LibraryClasses]
+  DebugLib
+  DevicePathLib
+  IoAccessLib
+  MemoryAllocationLib
+  PcdLib
+
+[FeaturePcd]
+  gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian
+
+[FixedPcd]
+  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
+  gNxpQoriqLsTokenSpaceGuid.PcdNumPciController
+  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase
+  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg
diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
new file mode 100755
index 000000000000..d5b5a3884e0a
--- /dev/null
+++ b/Silicon/NXP/Include/Pcie.h
@@ -0,0 +1,85 @@
+/** @file
+  PCI memory configuration for NXP
+
+  Copyright 2018-2020 NXP
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __PCI_H__
+#define __PCI_H__
+
+#define PCI_SEG0_NUM              0
+#define PCI_SEG1_NUM              1
+#define PCI_SEG2_NUM              2
+#define PCI_SEG3_NUM              3
+#define PCI_SEG4_NUM              4
+#define PCI_SEG5_NUM              5
+#define PCI_SEG0_MMIO_MEMBASE     FixedPcdGet64 (PcdPciExp1BaseAddr)
+#define PCI_SEG0_DBI_BASE         0x03400000
+
+#define PCI_LINK_DOWN             0x0
+#define PCI_LINK_UP               0x1
+
+// Segment configuration
+#define PCI_SEG_BUSNUM_MIN        0x0
+#define PCI_SEG_BUSNUM_MAX        0xff
+#define PCI_SEG_PORTIO_MIN        0x0
+#define PCI_SEG_PORTIO_MAX        0xffff
+#define SEG_CFG_SIZE              0x00001000
+#define SEG_MEM_BASE              0x40000000
+#define SEG_MEM_SIZE              0xC0000000
+#define SEG_MEM_LIMIT             SEG_MEM_BASE + (SEG_MEM_SIZE -1)
+#define SEG_IO_BASE               0x10000000
+#define SEG_MEM64_BASE            0x400000000
+#define PCI_BASE_DIFF             0x800000000
+#define PCI_DBI_SIZE_DIFF         0x100000
+#define PCI_SEG0_PHY_CFG0_BASE    PCI_SEG0_MMIO_MEMBASE
+#define PCI_SEG0_PHY_CFG1_BASE    PCI_SEG0_PHY_CFG0_BASE + SEG_CFG_SIZE
+#define PCI_SEG0_PHY_MEM_BASE     PCI_SEG0_MMIO_MEMBASE + SEG_MEM_BASE
+#define PCI_SEG0_PHY_MEM64_BASE   PCI_SEG0_MMIO_MEMBASE + SEG_MEM64_BASE
+#define PCI_SEG0_PHY_IO_BASE      PCI_SEG0_MMIO_MEMBASE + SEG_IO_BASE
+
+// PCIe Controller configuration
+#define NUM_PCIE_CONTROLLER       FixedPcdGet32 (PcdNumPciController)
+#define PCI_LUT_DBG               FixedPcdGet32 (PcdPcieLutDbg)
+#define PCI_LUT_BASE              FixedPcdGet32 (PcdPcieLutBase)
+#define LTSSM_PCIE_L0             0x11
+
+#define PCI_CLASS_BRIDGE_PCI      0x0604
+#define PCI_CLASS_DEVICE          0x8
+#define PCI_DBI_RO_WR_EN          0x8bc
+#define CLASS_CODE_MASK           0xffff
+#define CLASS_CODE_SHIFT          0x10
+
+// PCIe Layerscape Controller
+#define IATU_VIEWPORT_OFF                            0x900
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0            0x904
+#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0            0x908
+#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 IATU_VIEWPORT_OUTBOUND                       0x0
+#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN  BIT31
+
+// ATU Programming
+#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_INDEX0        0x0
+#define IATU_REGION_INDEX1        0x1
+#define IATU_REGION_INDEX2        0x2
+#define IATU_REGION_INDEX3        0x3
+#define IATU_REGION_INDEX4        0x4
+#define IATU_REGION_INDEX5        0x5
+#define IATU_REGION_INDEX6        0x6
+#define IATU_REGION_INDEX7        0x7
+#define SEG_CFG_BUS               0x00000000
+#define SEG_MEM_BUS               0x40000000
+#define SEG_IO_SIZE               0x10000
+#define SEG_IO_BUS                0x0
+
+#endif
diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
new file mode 100644
index 000000000000..cf872370c7cd
--- /dev/null
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -0,0 +1,568 @@
+/** @file
+  PCI Host Bridge Library instance for NXP SoCs
+
+  Copyright 2018-2020 NXP
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiDxe.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/IoAccessLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Pcie.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 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
+      PCI_SEG0_NUM
+    },
+
+    {
+      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
+      PCI_SEG1_NUM
+    },
+
+    {
+      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
+      PCI_SEG2_NUM
+    },
+
+    {
+      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
+      PCI_SEG3_NUM
+    },
+
+    {
+      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
+      PCI_SEG4_NUM
+    },
+
+    {
+      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
+      PCI_SEG5_NUM
+    },
+
+    {
+      END_DEVICE_PATH_TYPE,
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,
+      {
+        END_DEVICE_PATH_LENGTH,
+        0
+      }
+    }
+  }
+};
+
+STATIC
+GLOBAL_REMOVE_IF_UNREFERENCED
+CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
+  L"Mem", L"I/O", L"Bus"
+};
+
+#define PCI_ALLOCATION_ATTRIBUTES       EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | \
+                                        EFI_PCI_HOST_BRIDGE_MEM64_DECODE
+
+#define PCI_SUPPORT_ATTRIBUTES          EFI_PCI_ATTRIBUTE_ISA_IO_16 | \
+                                        EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \
+                                        EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
+                                        EFI_PCI_ATTRIBUTE_VGA_IO_16  | \
+                                        EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
+
+PCI_ROOT_BRIDGE mPciRootBridges[NUM_PCIE_CONTROLLER];
+
+/**
+   Helper function to check PCIe link state
+
+   @param Pcie Address of PCIe host controller.
+
+**/
+STATIC
+INTN
+PcieLinkUp (
+  IN EFI_PHYSICAL_ADDRESS Pcie,
+  IN UINT32 Idx
+  )
+{
+  MMIO_OPERATIONS *PcieOps;
+  UINT32 State;
+  UINT32 LtssmMask;
+
+  LtssmMask = 0x3f;
+
+  PcieOps = GetMmioOperations (FeaturePcdGet (PcdPciLutBigEndian));
+  State = PcieOps->Read32 ((UINTN)Pcie + PCI_LUT_BASE + PCI_LUT_DBG) & LtssmMask;
+
+  if (State < LTSSM_PCIE_L0) {
+    DEBUG ((DEBUG_INFO,"PCIE%d : reg @ 0x%lx, no link: LTSSM=0x%02x\n",
+            Idx + 1, Pcie, State));
+    return PCI_LINK_DOWN;
+  }
+
+  return PCI_LINK_UP;
+}
+
+/**
+  Function to set-up PCIe outbound window
+
+  @param Dbi     Address of PCIe host controller.
+  @param Idx     Index of iATU outbound window.
+  @param Type    Type(Cfg0/Cfg1/Mem/IO) of iATU outbound window.
+  @param Phys    PCIe controller phy address for outbound window.
+  @param BusAdr  PCIe controller bus address for outbound window.
+  @param Size    Window size
+
+**/
+STATIC
+VOID
+PcieOutboundSet (
+  IN EFI_PHYSICAL_ADDRESS Dbi,
+  IN UINT32 Idx,
+  IN UINT32 Type,
+  IN UINT64 Phys,
+  IN UINT64 BusAddr,
+  IN UINT64 Size
+  )
+{
+  // PCIe Layerscape : Outbound Window
+  MmioWrite32 (Dbi + IATU_VIEWPORT_OFF,
+                (UINT32)(IATU_VIEWPORT_OUTBOUND | Idx));
+
+  MmioWrite32 (Dbi + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
+                (UINT32)Phys);
+
+  MmioWrite32 (Dbi + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
+                (UINT32)(Phys >> 32));
+
+  MmioWrite32 (Dbi + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
+                (UINT32)(Phys + Size - BIT0));
+
+  MmioWrite32 (Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
+                (UINT32)BusAddr);
+
+  MmioWrite32 (Dbi + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
+                (UINT32)(BusAddr >> 32));
+
+  MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
+                (UINT32)Type);
+
+  MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
+                IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
+}
+
+/**
+  Function to set-up iATU windows for Layerscape PCIe controller
+
+  @param Pcie      Address of PCIe host controller
+  @param Cfg0Base  PCIe controller phy address Type0 Configuration Space.
+  @param Cfg1Base  PCIe controller phy address Type1 Configuration Space.
+  @param MemBase   PCIe controller phy address Memory Space.
+  @param Mem64Base PCIe controller phy address MMIO64 Space.
+  @param IoBase    PCIe controller phy address IO Space.
+**/
+STATIC
+VOID
+PcieLsSetupAtu (
+  IN EFI_PHYSICAL_ADDRESS Pcie,
+  IN EFI_PHYSICAL_ADDRESS Cfg0Base,
+  IN EFI_PHYSICAL_ADDRESS Cfg1Base,
+  IN EFI_PHYSICAL_ADDRESS MemBase,
+  IN EFI_PHYSICAL_ADDRESS Mem64Base,
+  IN EFI_PHYSICAL_ADDRESS IoBase
+  )
+{
+  UINT64 Cfg0BaseAddr;
+  UINT64 Cfg1BaseAddr;
+  UINT64 Cfg0BusAddress;
+  UINT64 Cfg1BusAddress;
+  UINT64 Cfg0Size;
+  UINT64 Cfg1Size;
+
+  Cfg0BaseAddr = Cfg0Base;
+  Cfg1BaseAddr = Cfg1Base;
+  Cfg0BusAddress = SEG_CFG_BUS;
+  Cfg1BusAddress = SEG_CFG_BUS;
+  Cfg0Size = SEG_CFG_SIZE;
+  Cfg1Size = SEG_CFG_SIZE;
+
+  // iATU : OUTBOUND WINDOW 1 : CFG0
+  PcieOutboundSet (Pcie,
+    IATU_REGION_INDEX0,
+    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0,
+    Cfg0BaseAddr,
+    Cfg0BusAddress,
+    Cfg0Size);
+
+  // iATU : OUTBOUND WINDOW 2 : CFG1
+  PcieOutboundSet (Pcie,
+    IATU_REGION_INDEX1,
+    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1,
+    Cfg1BaseAddr,
+    Cfg1BusAddress,
+    Cfg1Size);
+
+  // iATU : OUTBOUND WINDOW 3 : MEM
+  PcieOutboundSet (Pcie,
+    IATU_REGION_INDEX2,
+    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
+    MemBase,
+    SEG_MEM_BUS,
+    SEG_MEM_SIZE);
+
+  // iATU : OUTBOUND WINDOW 4 : MMIO64
+  PcieOutboundSet (Pcie,
+    IATU_REGION_INDEX3,
+    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
+    Mem64Base,
+    Mem64Base,
+    SIZE_4GB);
+  Mem64Base += SIZE_4GB;
+
+  // iATU : OUTBOUND WINDOW 5 : MMIO64
+  PcieOutboundSet (Pcie,
+    IATU_REGION_INDEX4,
+    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
+    Mem64Base,
+    Mem64Base,
+    SIZE_4GB);
+  Mem64Base += SIZE_4GB;
+
+  // iATU : OUTBOUND WINDOW 6 : MMIO64
+  PcieOutboundSet (Pcie,
+    IATU_REGION_INDEX5,
+    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
+    Mem64Base,
+    Mem64Base,
+    SIZE_4GB
+    );
+  Mem64Base += SIZE_4GB;
+
+  // iATU : OUTBOUND WINDOW 7 : MMIO64
+  PcieOutboundSet (Pcie,
+    IATU_REGION_INDEX6,
+    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
+    Mem64Base,
+    Mem64Base,
+    SIZE_4GB
+    );
+
+  // iATU : OUTBOUND WINDOW 8: IO
+  PcieOutboundSet (Pcie,
+    IATU_REGION_INDEX7,
+    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO,
+    IoBase,
+    SEG_IO_BUS,
+    SEG_IO_SIZE
+    );
+}
+/**
+  Helper function to set-up PCIe controller
+
+  @param Pcie       Address of PCIe host controller
+  @param Cfg0Base   PCIe controller phy address Type0 Configuration Space.
+  @param Cfg1Base   PCIe controller phy address Type1 Configuration Space.
+  @param MemBase    PCIe controller phy address Memory Space.
+  @param Mem64Base  PCIe controller phy address MMIO64 Space.
+  @param IoBase     PCIe controller phy address IO Space.
+
+**/
+STATIC
+VOID
+PcieSetupCntrl (
+  IN EFI_PHYSICAL_ADDRESS Pcie,
+  IN EFI_PHYSICAL_ADDRESS Cfg0Base,
+  IN EFI_PHYSICAL_ADDRESS Cfg1Base,
+  IN EFI_PHYSICAL_ADDRESS MemBase,
+  IN EFI_PHYSICAL_ADDRESS Mem64Base,
+  IN EFI_PHYSICAL_ADDRESS IoBase
+  )
+{
+  UINT32 Val;
+
+  // PCIe Layerscape Controller Setup
+  PcieLsSetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base, IoBase);
+
+  // Program Class code for Layerscape PCIe controller
+  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 1);
+  Val = MmioRead32 ((UINTN)Pcie + PCI_CLASS_DEVICE);
+  Val &= ~(CLASS_CODE_MASK << CLASS_CODE_SHIFT);
+  Val |= (PCI_CLASS_BRIDGE_PCI << CLASS_CODE_SHIFT);
+  MmioWrite32 ((UINTN)Pcie + PCI_CLASS_DEVICE, Val);
+  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 0);
+}
+
+/**
+  Return all the root bridge instances in an array.
+
+  @param Count  Return the count of root bridge instances.
+
+  @return All the root bridge instances in an array.
+
+**/
+PCI_ROOT_BRIDGE *
+EFIAPI
+PciHostBridgeGetRootBridges (
+  OUT UINTN     *Count
+  )
+{
+  UINTN         Idx;
+  UINTN         Loop;
+  UINT64        PciPhyMemAddr[NUM_PCIE_CONTROLLER];
+  UINT64        PciPhyMem64Addr[NUM_PCIE_CONTROLLER];
+  UINT64        PciPhyCfg0Addr[NUM_PCIE_CONTROLLER];
+  UINT64        PciPhyCfg1Addr[NUM_PCIE_CONTROLLER];
+  UINT64        PciPhyIoAddr[NUM_PCIE_CONTROLLER];
+  UINT64        Regs[NUM_PCIE_CONTROLLER];
+  INTN          LinkUp;
+
+  for  (Idx = 0, Loop = 0; Idx < NUM_PCIE_CONTROLLER; Idx++) {
+    PciPhyMemAddr[Idx] = PCI_SEG0_PHY_MEM_BASE + (PCI_BASE_DIFF * Idx);
+    PciPhyMem64Addr[Idx] = PCI_SEG0_PHY_MEM64_BASE + (PCI_BASE_DIFF * Idx);
+    PciPhyCfg0Addr[Idx] = PCI_SEG0_PHY_CFG0_BASE + (PCI_BASE_DIFF * Idx);
+    PciPhyCfg1Addr[Idx] = PCI_SEG0_PHY_CFG1_BASE + (PCI_BASE_DIFF * Idx);
+    PciPhyIoAddr [Idx] =  PCI_SEG0_PHY_IO_BASE + (PCI_BASE_DIFF * Idx);
+    Regs[Idx] =  PCI_SEG0_DBI_BASE + (PCI_DBI_SIZE_DIFF * Idx);
+
+    // Check PCIe Link
+    LinkUp = PcieLinkUp(Regs[Idx], Idx);
+
+    if (!LinkUp) {
+      continue;
+    }
+    DEBUG ((DEBUG_INFO, "PCIE%d Passed Linkup Phase\n", Idx + 1));
+    // Set up PCIe Controller and ATU windows
+    PcieSetupCntrl (Regs[Idx],
+                    PciPhyCfg0Addr[Idx],
+                    PciPhyCfg1Addr[Idx],
+                    PciPhyMemAddr[Idx],
+                    PciPhyMem64Addr[Idx],
+                    PciPhyIoAddr[Idx]);
+
+    mPciRootBridges[Loop].Segment               = Idx;
+    mPciRootBridges[Loop].Supports              = PCI_SUPPORT_ATTRIBUTES;
+    mPciRootBridges[Loop].Attributes            = PCI_SUPPORT_ATTRIBUTES;
+    mPciRootBridges[Loop].DmaAbove4G            = TRUE;
+    mPciRootBridges[Loop].NoExtendedConfigSpace = FALSE;
+    mPciRootBridges[Loop].ResourceAssigned      = FALSE;
+    mPciRootBridges[Loop].AllocationAttributes  = PCI_ALLOCATION_ATTRIBUTES;
+
+    mPciRootBridges[Loop].Bus.Base              = PCI_SEG_BUSNUM_MIN;
+    mPciRootBridges[Loop].Bus.Limit             = PCI_SEG_BUSNUM_MAX;
+
+    mPciRootBridges[Loop].Io.Base               = PCI_SEG_PORTIO_MIN;
+    mPciRootBridges[Loop].Io.Limit              = PCI_SEG_PORTIO_MAX;
+    mPciRootBridges[Loop].Io.Translation        = MAX_UINT64 -
+                                                  (SEG_IO_SIZE * Idx) + 1;
+
+    mPciRootBridges[Loop].Mem.Base              = SEG_MEM_BASE;
+    mPciRootBridges[Loop].Mem.Limit             = SEG_MEM_LIMIT;
+    mPciRootBridges[Loop].Mem.Translation       = MAX_UINT64 -
+                                                  (PCI_SEG0_MMIO_MEMBASE +
+                                                  (PCI_BASE_DIFF *
+                                                  Idx)) + 1;
+
+    mPciRootBridges[Loop].MemAbove4G.Base       = PciPhyMem64Addr[Idx];
+    mPciRootBridges[Loop].MemAbove4G.Limit      = PciPhyMem64Addr[Idx] +
+                                                  (SIZE_16GB - 1);
+
+    mPciRootBridges[Loop].PMem.Base             = MAX_UINT64;
+    mPciRootBridges[Loop].PMem.Limit            = 0;
+    mPciRootBridges[Loop].PMemAbove4G.Base      = MAX_UINT64;
+    mPciRootBridges[Loop].PMemAbove4G.Limit     = 0;
+    mPciRootBridges[Loop].DevicePath            = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Idx];
+    Loop++;
+  }
+
+  if (Loop == 0) {
+    return NULL;
+  }
+
+  *Count = Loop;
+  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
+                   );
+  }
+
+  return;
+}
-- 
2.7.4


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

* [PATCH edk2-platforms 04/16] Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS Ctrl
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (2 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 03/16] Silicon/NXP: Implement PciHostBridgeLib support Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:22   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 05/16] Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU Windows Wasim Khan
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

PCIe layerscape controller supports CFG Shift feature. It can be
enabled by setting BIT[28] of iATU Control 2 Register.
Check PcdPciCfgShiftEnable to enable 'CFG Shift feature' in
PCIe controller.
if enable, PCIe layerscape controller shifts BDF from bits[27:12] to
bits[31:16] and supports Enhanced Configuration Address Mapping (ECAM)
mechanism.

PCIe layerscape controller is ECAM complaint for bus[0x1-0xff].
So create outbound CFG windows from 1MB-256MB (255 buses) for
type0/type1 configuration access.
PCIe layerscape controller is Non-ECAM complaint for bus 0.It does
not support device > 0 on bus 0. PciSegmentLib should handles this
limitation.

Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Silicon/NXP/NxpQoriqLs.dec                         |  3 ++
 .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  3 ++
 Silicon/NXP/Include/Pcie.h                         |  3 ++
 .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 35 +++++++++++++++++-----
 4 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
index bafdfd9f4298..293fd773fd3d 100644
--- a/Silicon/NXP/NxpQoriqLs.dec
+++ b/Silicon/NXP/NxpQoriqLs.dec
@@ -36,3 +36,6 @@ [PcdsFixedAtBuild.common]
   gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase|0x0|UINT32|0x00000502
   gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg|0x0|UINT32|0x00000503
   gNxpQoriqLsTokenSpaceGuid.PcdPciDebug|FALSE|BOOLEAN|0x00000504
+
+[PcdsDynamic.common]
+  gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable|FALSE|BOOLEAN|0x00000600
diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
index 5ddb96e4fa6a..98cfb6aee6b0 100644
--- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -38,3 +38,6 @@ [FixedPcd]
   gNxpQoriqLsTokenSpaceGuid.PcdNumPciController
   gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase
   gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg
+
+[Pcd]
+  gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
index d5b5a3884e0a..ae85190180e8 100755
--- a/Silicon/NXP/Include/Pcie.h
+++ b/Silicon/NXP/Include/Pcie.h
@@ -63,6 +63,7 @@
 #define IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0        0x91C
 #define IATU_VIEWPORT_OUTBOUND                       0x0
 #define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN  BIT31
+#define IATU_ENABLE_CFG_SHIFT_FEATURE                BIT28
 
 // ATU Programming
 #define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM   0x0
@@ -82,4 +83,6 @@
 #define SEG_IO_SIZE               0x10000
 #define SEG_IO_BUS                0x0
 
+#define CFG_SHIFT_ENABLE          (PcdGetBool (PcdPciCfgShiftEnable))
+
 #endif
diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
index cf872370c7cd..f92863c60868 100644
--- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -259,8 +259,17 @@ PcieOutboundSet (
   MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
                 (UINT32)Type);
 
-  MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
-                IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
+  if (CFG_SHIFT_ENABLE &&
+     ((Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0) ||
+     (Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1))) {
+       MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
+         (IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN |
+         IATU_ENABLE_CFG_SHIFT_FEATURE)
+         );
+  } else {
+    MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
+                  IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
+  }
 }
 
 /**
@@ -291,12 +300,22 @@ PcieLsSetupAtu (
   UINT64 Cfg0Size;
   UINT64 Cfg1Size;
 
-  Cfg0BaseAddr = Cfg0Base;
-  Cfg1BaseAddr = Cfg1Base;
-  Cfg0BusAddress = SEG_CFG_BUS;
-  Cfg1BusAddress = SEG_CFG_BUS;
-  Cfg0Size = SEG_CFG_SIZE;
-  Cfg1Size = SEG_CFG_SIZE;
+  if (CFG_SHIFT_ENABLE) {
+    DEBUG ((DEBUG_INFO, "PCIe: CFG Shit Method Enabled \n"));
+    Cfg0BaseAddr = Cfg0Base + SIZE_1MB;
+    Cfg1BaseAddr = Cfg0Base + SIZE_2MB;
+    Cfg0BusAddress = SIZE_1MB;
+    Cfg1BusAddress = SIZE_2MB;
+    Cfg0Size = SIZE_1MB;
+    Cfg1Size = (SIZE_256MB - SIZE_1MB); // 255MB
+  } else {
+    Cfg0BaseAddr = Cfg0Base;
+    Cfg1BaseAddr = Cfg1Base;
+    Cfg0BusAddress = SEG_CFG_BUS;
+    Cfg1BusAddress = SEG_CFG_BUS;
+    Cfg0Size = SEG_CFG_SIZE;
+    Cfg1Size = SEG_CFG_SIZE;
+  }
 
   // iATU : OUTBOUND WINDOW 1 : CFG0
   PcieOutboundSet (Pcie,
-- 
2.7.4


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

* [PATCH edk2-platforms 05/16] Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU Windows
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (3 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 04/16] Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS Ctrl Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:24   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 06/16] Silicon/NXP: PciHostBridgeLib: add Workaround for A-011451 Wasim Khan
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Setup PCIe LayerscapeGen4 controller and setup CFG, IO,
MMIO and MMIO64 iATU windows.
Check for PcdPciLsGen4Ctrl to enable LsGen4 PCIe
controller.

Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Silicon/NXP/NxpQoriqLs.dec                         |   1 +
 .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |   1 +
 Silicon/NXP/Include/Pcie.h                         | 120 ++++++++++
 .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 255 +++++++++++++++++----
 4 files changed, 336 insertions(+), 41 deletions(-)

diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
index 293fd773fd3d..8271d19ed8e5 100644
--- a/Silicon/NXP/NxpQoriqLs.dec
+++ b/Silicon/NXP/NxpQoriqLs.dec
@@ -39,3 +39,4 @@ [PcdsFixedAtBuild.common]
 
 [PcdsDynamic.common]
   gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable|FALSE|BOOLEAN|0x00000600
+  gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl|FALSE|BOOLEAN|0x00000601
diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
index 98cfb6aee6b0..b777acdc103f 100644
--- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -41,3 +41,4 @@ [FixedPcd]
 
 [Pcd]
   gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
+  gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl
diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
index ae85190180e8..4c41c3585a8b 100755
--- a/Silicon/NXP/Include/Pcie.h
+++ b/Silicon/NXP/Include/Pcie.h
@@ -84,5 +84,125 @@
 #define SEG_IO_BUS                0x0
 
 #define CFG_SHIFT_ENABLE          (PcdGetBool (PcdPciCfgShiftEnable))
+#define PCI_LS_GEN4_CTRL          (PcdGetBool (PcdPciLsGen4Ctrl))
 
+// PCIe Layerscape Gen4 Controller
+#define GPEX_CLASSCODE                          0x474
+#define GPEX_CLASSCODE_SHIFT                    16
+#define GPEX_CLASSCODE_MASK                     0xffff
+#define PAB_AXI_PIO_CTRL(Idx)                   (0x840 + 0x10 * Idx)
+#define APIO_EN                                 0x1
+#define MEM_WIN_EN                              0x1 << 1
+#define IO_WIN_EN                               0x1 << 2
+#define CFG_WIN_EN                              0x1 << 3
+#define PAB_PEX_PIO_CTRL(Idx)                   (0x8c0 + 0x10 * Idx)
+#define PPIO_EN                                 (0x1 << 0)
+#define PAB_PEX_PIO_STAT(Idx)                   (0x8c4 + 0x10 * Idx)
+#define PAB_PEX_PIO_MT_STAT(Idx)                (0x8c8 + 0x10 * Idx)
+#define PEX_AMAP_CTRL_TYPE_SHIFT                0x1
+#define PEX_AMAP_CTRL_EN_SHIFT                  0x0
+#define PEX_AMAP_CTRL_TYPE_MASK                 0x3
+#define PEX_AMAP_CTRL_EN_MASK                   0x1
+#define PAB_PEX_AMAP_CTRL(Idx)                  (0x4ba0 + 0x10 * Idx)
+#define PAB_EXT_PEX_AMAP_SIZE(Idx)              (0xbef0 + 0x04 * Idx)
+#define PAB_PEX_AMAP_AXI_WIN(Idx)               (0x4ba4 + 0x10 * Idx)
+#define PAB_EXT_PEX_AMAP_AXI_WIN(Idx)           (0xb4a0 + 0x04 * Idx)
+#define PAB_PEX_AMAP_PEX_WIN_L(Idx)             (0x4ba8 + 0x10 * Idx)
+#define PAB_PEX_AMAP_PEX_WIN_H(Idx)             (0x4bac + 0x10 * Idx)
+#define PAB_CTRL                                0x808
+#define PAB_CTRL_APIO_EN                        0x1
+#define PAB_CTRL_PPIO_EN                        (0x1 << 1)
+#define PAB_CTRL_PAGE_SEL_SHIFT                 13
+#define PAB_CTRL_PAGE_SEL_MASK                  0x3f
+#define INDIRECT_ADDR_BNDRY                     0xc00
+#define PAGE_IDX_SHIFT                          10
+#define PAGE_ADDR_MASK                          0x3ff
+#define PAB_AXI_AMAP_CTRL(Idx)                  (0xba0 + 0x10 * Idx)
+#define PAB_EXT_AXI_AMAP_SIZE(Idx)              (0xbaf0 + 0x4 * Idx)
+#define PAB_AXI_AMAP_AXI_WIN(Idx)               (0xba4 + 0x10 * Idx)
+#define PAB_EXT_AXI_AMAP_AXI_WIN(Idx)           (0x80a0 + 0x4 * Idx)
+#define PAB_AXI_AMAP_PEX_WIN_L(Idx)             (0xba8 + 0x10 * Idx)
+#define PAB_AXI_AMAP_PEX_WIN_H(Idx)             (0xbac + 0x10 * Idx)
+#define PAB_AXI_TYPE_CFG                        0x00
+#define PAB_AXI_TYPE_IO                         0x01
+#define PAB_AXI_TYPE_MEM                        0x02
+#define AXI_AMAP_CTRL_EN                        0x1
+#define AXI_AMAP_CTRL_TYPE_SHIFT                1
+#define AXI_AMAP_CTRL_TYPE_MASK                 0x3
+#define AXI_AMAP_CTRL_SIZE_SHIFT                10
+#define AXI_AMAP_CTRL_SIZE_MASK                 0x3fffff
+
+
+#define OFFSET_TO_PAGE_IDX(Off)                 ((Off >> PAGE_IDX_SHIFT) \
+                                                & PAB_CTRL_PAGE_SEL_MASK)
+
+#define OFFSET_TO_PAGE_ADDR(Off)                ((Off & PAGE_ADDR_MASK) \
+                                                | INDIRECT_ADDR_BNDRY)
+/**
+  Function to set page for LsGen4 Ctrl
+
+  @param  Dbi    GPEX host controller address.
+  @param  PgIdx  The page index to select
+
+**/
+STATIC inline VOID PciLsGen4SetPg (
+  IN EFI_PHYSICAL_ADDRESS Dbi,
+  IN UINT8 PgIdx
+  )
+{
+  UINT32 Val;
+  Val = MmioRead32 (Dbi + PAB_CTRL);
+  Val &= ~(PAB_CTRL_PAGE_SEL_MASK << PAB_CTRL_PAGE_SEL_SHIFT);
+  Val |= (PgIdx & PAB_CTRL_PAGE_SEL_MASK) << PAB_CTRL_PAGE_SEL_SHIFT;
+  MmioWrite32 (Dbi + PAB_CTRL, Val);
+}
+
+/**
+  Function to read LsGen4 PCIe controller config space
+  LsGen4 PCIe controller requires page number to be set
+  in Bridge Control Register(PAB) for offset > 3KB.
+
+  @param  Dbi     GPEX host controller address.
+  @param  Offset  Offset to read from
+
+**/
+STATIC inline INTN PciLsGen4Read32 (
+  IN EFI_PHYSICAL_ADDRESS Dbi,
+  IN UINT32 Offset
+  )
+{
+  if (Offset < INDIRECT_ADDR_BNDRY) {
+    PciLsGen4SetPg (Dbi, 0);
+    return MmioRead32 (Dbi + Offset);
+  } else {
+    // If Offset > 3KB, paging mechanism is used
+    // Select page index and offset within the page
+    PciLsGen4SetPg (Dbi, OFFSET_TO_PAGE_IDX (Offset));
+    return MmioRead32 (Dbi + OFFSET_TO_PAGE_ADDR (Offset));
+  }
+}
+
+/**
+  Function to write to LsGen4 PCIe controller config space
+  LsGen4 PCIe controller requires page number to be set
+  in Bridge Control Register(PAB) for offset > 3KB.
+
+  @param  Dbi     GPEX host controller address
+  @param  Offset  Offset to read from
+
+**/
+STATIC inline VOID PciLsGen4Write32 (
+  IN EFI_PHYSICAL_ADDRESS Dbi,
+  IN UINT32 Offset,
+  IN UINT32 Value
+  )
+{
+  if (Offset < INDIRECT_ADDR_BNDRY) {
+    PciLsGen4SetPg (Dbi, 0);
+    MmioWrite32 (Dbi + Offset, Value);
+  } else {
+    PciLsGen4SetPg (Dbi, OFFSET_TO_PAGE_IDX (Offset));
+    MmioWrite32 (Dbi + OFFSET_TO_PAGE_ADDR (Offset), Value);
+  }
+}
 #endif
diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
index f92863c60868..d9944313da21 100644
--- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -201,7 +201,11 @@ PcieLinkUp (
   UINT32 State;
   UINT32 LtssmMask;
 
-  LtssmMask = 0x3f;
+  if (PCI_LS_GEN4_CTRL) {
+    LtssmMask = 0x7f;
+  } else {
+    LtssmMask = 0x3f;
+  }
 
   PcieOps = GetMmioOperations (FeaturePcdGet (PcdPciLutBigEndian));
   State = PcieOps->Read32 ((UINTN)Pcie + PCI_LUT_BASE + PCI_LUT_DBG) & LtssmMask;
@@ -237,38 +241,58 @@ PcieOutboundSet (
   IN UINT64 Size
   )
 {
-  // PCIe Layerscape : Outbound Window
-  MmioWrite32 (Dbi + IATU_VIEWPORT_OFF,
-                (UINT32)(IATU_VIEWPORT_OUTBOUND | Idx));
+  UINT32 Val;
 
-  MmioWrite32 (Dbi + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
-                (UINT32)Phys);
-
-  MmioWrite32 (Dbi + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
-                (UINT32)(Phys >> 32));
-
-  MmioWrite32 (Dbi + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
-                (UINT32)(Phys + Size - BIT0));
-
-  MmioWrite32 (Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
-                (UINT32)BusAddr);
-
-  MmioWrite32 (Dbi + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
-                (UINT32)(BusAddr >> 32));
-
-  MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
-                (UINT32)Type);
-
-  if (CFG_SHIFT_ENABLE &&
-     ((Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0) ||
-     (Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1))) {
-       MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
-         (IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN |
-         IATU_ENABLE_CFG_SHIFT_FEATURE)
-         );
+  if (PCI_LS_GEN4_CTRL) {
+    // PCIe Layerscape Gen4: Outbound Window
+    Size = ~(Size -1 );
+    Val = PciLsGen4Read32 ((UINTN)Dbi, PAB_AXI_AMAP_CTRL (Idx));
+    Val &= ~((AXI_AMAP_CTRL_TYPE_MASK << AXI_AMAP_CTRL_TYPE_SHIFT) |
+              (AXI_AMAP_CTRL_SIZE_MASK << AXI_AMAP_CTRL_SIZE_SHIFT) |
+              AXI_AMAP_CTRL_EN);
+    Val |= ((Type & AXI_AMAP_CTRL_TYPE_MASK) << AXI_AMAP_CTRL_TYPE_SHIFT) |
+             (((UINT32)Size >> AXI_AMAP_CTRL_SIZE_SHIFT) <<
+             AXI_AMAP_CTRL_SIZE_SHIFT) | AXI_AMAP_CTRL_EN;
+    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_CTRL (Idx), Val);
+    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_AXI_WIN (Idx), (UINT32)Phys);
+    PciLsGen4Write32 ((UINTN)Dbi, PAB_EXT_AXI_AMAP_AXI_WIN (Idx), Phys >> 32);
+    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_L (Idx), (UINT32)BusAddr);
+    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_H (Idx), BusAddr >> 32);
+    PciLsGen4Write32 ((UINTN)Dbi, PAB_EXT_AXI_AMAP_SIZE (Idx), Size >> 32);
   } else {
-    MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
-                  IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
+    // PCIe Layerscape : Outbound Window
+    MmioWrite32 (Dbi + IATU_VIEWPORT_OFF,
+                  (UINT32)(IATU_VIEWPORT_OUTBOUND | Idx));
+
+    MmioWrite32 (Dbi + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
+                  (UINT32)Phys);
+
+    MmioWrite32 (Dbi + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
+                  (UINT32)(Phys >> 32));
+
+    MmioWrite32 (Dbi + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
+                  (UINT32)(Phys + Size - BIT0));
+
+    MmioWrite32 (Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
+                  (UINT32)BusAddr);
+
+    MmioWrite32 (Dbi + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
+                  (UINT32)(BusAddr >> 32));
+
+    MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
+                  (UINT32)Type);
+
+    if (CFG_SHIFT_ENABLE &&
+       ((Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0) ||
+       (Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1))) {
+         MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
+           (IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN |
+           IATU_ENABLE_CFG_SHIFT_FEATURE)
+           );
+    } else {
+      MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
+                    IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
+    }
   }
 }
 
@@ -387,6 +411,124 @@ PcieLsSetupAtu (
     SEG_IO_SIZE
     );
 }
+
+/**
+  Function to set-up ATU windows for PCIe LayerscapeGen4 controller
+
+  @param Pcie      Address of PCIe host controller
+  @param Cfg0Base  PCIe controller phy address Type0 Configuration Space.
+  @param Cfg1Base  PCIe controller phy address Type1 Configuration Space.
+  @param MemBase   PCIe controller phy address Memory Space.
+  @param Mem64Base PCIe controller phy address MMIO64 Space.
+  @param IoBase    PCIe controller phy address IO Space.
+**/
+STATIC
+VOID
+PcieLsGen4SetupAtu (
+  IN EFI_PHYSICAL_ADDRESS Pcie,
+  IN EFI_PHYSICAL_ADDRESS Cfg0Base,
+  IN EFI_PHYSICAL_ADDRESS Cfg1Base,
+  IN EFI_PHYSICAL_ADDRESS MemBase,
+  IN EFI_PHYSICAL_ADDRESS Mem64Base,
+  IN EFI_PHYSICAL_ADDRESS IoBase
+  )
+{
+  // ATU : OUTBOUND WINDOW 1 : CFG0
+  PcieOutboundSet (Pcie, IATU_REGION_INDEX0,
+                         PAB_AXI_TYPE_CFG,
+                         Cfg0Base,
+                         SEG_CFG_BUS,
+                         SEG_CFG_SIZE);
+
+  // ATU : OUTBOUND WINDOW 2 : IO
+  PcieOutboundSet (Pcie, IATU_REGION_INDEX1,
+                         PAB_AXI_TYPE_IO,
+                         IoBase,
+                         SEG_IO_BUS,
+                         SEG_IO_SIZE);
+
+  // ATU : OUTBOUND WINDOW 3 : MEM
+  PcieOutboundSet (Pcie, IATU_REGION_INDEX2,
+                         PAB_AXI_TYPE_MEM,
+                         MemBase,
+                         SEG_MEM_BUS,
+                         SEG_MEM_SIZE);
+
+  // ATU : OUTBOUND WINDOW 4 : MMIO64
+  PcieOutboundSet (Pcie, IATU_REGION_INDEX3,
+                            PAB_AXI_TYPE_MEM,
+                            Mem64Base,
+                            Mem64Base,
+                            SIZE_4GB);
+  Mem64Base += SIZE_4GB;
+
+  // ATU : OUTBOUND WINDOW 5 : MMIO64
+  PcieOutboundSet (Pcie, IATU_REGION_INDEX4,
+                            PAB_AXI_TYPE_MEM,
+                            Mem64Base,
+                            Mem64Base,
+                            SIZE_4GB);
+  Mem64Base += SIZE_4GB;
+
+  // ATU : OUTBOUND WINDOW 6 : MMIO64
+  PcieOutboundSet (Pcie, IATU_REGION_INDEX5,
+                            PAB_AXI_TYPE_MEM,
+                            Mem64Base,
+                            Mem64Base,
+                            SIZE_4GB);
+  Mem64Base += SIZE_4GB;
+
+  // ATU : OUTBOUND WINDOW 7 : MMIO64
+  PcieOutboundSet (Pcie, IATU_REGION_INDEX6,
+                            PAB_AXI_TYPE_MEM,
+                            Mem64Base,
+                            Mem64Base,
+                            SIZE_4GB);
+}
+
+/**
+  Function to set-up PCIe inbound window
+
+  @param Pcie    Address of PCIe host controller.
+  @param Idx     Index of inbound window.
+  @param Type    Type(Cfg/Mem/IO) of iATU outbound window.
+  @param Phys    PCIe controller phy address for inbound window.
+  @param BusAdr  PCIe controller bus address for inbound window.
+  @param Size    Window size
+
+**/
+
+STATIC
+VOID
+PciSetupInBoundWin (
+  IN EFI_PHYSICAL_ADDRESS Pcie,
+  IN UINT32 Idx,
+  IN UINT32  Type,
+  IN UINT64 Phys,
+  IN UINT64 BusAddr,
+  IN UINT64 Size)
+{
+  UINT32 Val;
+  UINT64 WinSize;
+
+  if (PCI_LS_GEN4_CTRL) {
+    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_PEX_AMAP_CTRL(Idx));
+    Val &= ~(PEX_AMAP_CTRL_TYPE_MASK << PEX_AMAP_CTRL_TYPE_SHIFT);
+    Val &= ~(PEX_AMAP_CTRL_EN_MASK << PEX_AMAP_CTRL_EN_SHIFT);
+    Val = (Val | (Type << PEX_AMAP_CTRL_TYPE_SHIFT));
+    Val = (Val | (1 << PEX_AMAP_CTRL_EN_SHIFT));
+
+    WinSize = ~(Size - 1);
+    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_CTRL(Idx),
+                       (Val | (UINT32)WinSize));
+    PciLsGen4Write32 ((UINTN)Pcie, PAB_EXT_PEX_AMAP_SIZE(Idx), (WinSize>>32));
+    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_AXI_WIN(Idx), (UINT32)Phys);
+    PciLsGen4Write32 ((UINTN)Pcie, PAB_EXT_PEX_AMAP_AXI_WIN(Idx), (Phys>>32));
+    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_PEX_WIN_L(Idx), (UINT32)BusAddr);
+    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_PEX_WIN_H(Idx), (BusAddr >>32));
+  }
+}
+
 /**
   Helper function to set-up PCIe controller
 
@@ -411,16 +553,47 @@ PcieSetupCntrl (
 {
   UINT32 Val;
 
-  // PCIe Layerscape Controller Setup
-  PcieLsSetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base, IoBase);
-
-  // Program Class code for Layerscape PCIe controller
-  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 1);
-  Val = MmioRead32 ((UINTN)Pcie + PCI_CLASS_DEVICE);
-  Val &= ~(CLASS_CODE_MASK << CLASS_CODE_SHIFT);
-  Val |= (PCI_CLASS_BRIDGE_PCI << CLASS_CODE_SHIFT);
-  MmioWrite32 ((UINTN)Pcie + PCI_CLASS_DEVICE, Val);
-  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 0);
+  if (PCI_LS_GEN4_CTRL) {
+    // PCIe LsGen4 Controller Setup
+
+    //Fix Class Code
+    Val = PciLsGen4Read32 ((UINTN)Pcie, GPEX_CLASSCODE);
+    Val &= ~(GPEX_CLASSCODE_MASK << GPEX_CLASSCODE_SHIFT);
+    Val |= PCI_CLASS_BRIDGE_PCI << GPEX_CLASSCODE_SHIFT;
+    PciLsGen4Write32 ((UINTN)Pcie, GPEX_CLASSCODE, Val);
+
+    // Enable APIO and Memory/IO/CFG Windows
+    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_PIO_CTRL (0));
+    Val |= APIO_EN | MEM_WIN_EN | IO_WIN_EN | CFG_WIN_EN;
+    PciLsGen4Write32 ((UINTN)Pcie, PAB_AXI_PIO_CTRL (0), Val);
+
+    // LsGen4 Inbound Window Setup
+    PciSetupInBoundWin (Pcie, 0, PAB_AXI_TYPE_MEM, 0 , 0, SIZE_1TB);
+
+    // LsGen4 Outbound Window Setup
+    PcieLsGen4SetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base, IoBase);
+
+    // Enable AMBA & PEX PIO
+    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_CTRL);
+    Val |= PAB_CTRL_APIO_EN | PAB_CTRL_PPIO_EN;
+    PciLsGen4Write32 ((UINTN)Pcie, PAB_CTRL, Val);
+
+    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_PEX_PIO_CTRL(0));
+    Val |= PPIO_EN;
+    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_PIO_CTRL(0), Val);
+
+  } else {
+    // PCIe Layerscape Controller Setup
+    PcieLsSetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base, IoBase);
+
+    // Program Class code for Layerscape PCIe controller
+    MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 1);
+    Val = MmioRead32 ((UINTN)Pcie + PCI_CLASS_DEVICE);
+    Val &= ~(CLASS_CODE_MASK << CLASS_CODE_SHIFT);
+    Val |= (PCI_CLASS_BRIDGE_PCI << CLASS_CODE_SHIFT);
+    MmioWrite32 ((UINTN)Pcie + PCI_CLASS_DEVICE, Val);
+    MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 0);
+  }
 }
 
 /**
-- 
2.7.4


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

* [PATCH edk2-platforms 06/16] Silicon/NXP: PciHostBridgeLib: add Workaround for A-011451
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (4 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 05/16] Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU Windows Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-21 23:02 ` [PATCH edk2-platforms 07/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows Wasim Khan
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

When PCIe Layerscape Gen4 controller is sending multiple split
completions and ACK latency expires indicating that ACK should
be send at priority. But because of large number of split completions
and FC update DLLP,the controller does not give priority to ACK
transmission. This results into ACK latency timer timeout error
at the link partner and the pending TLPs are replayed by the
link partner again.

Workaround:
Reduce the ACK latency timeout value.

Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Silicon/NXP/Include/Pcie.h                              | 4 ++++
 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c | 6 ++++++
 2 files changed, 10 insertions(+)

diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
index 4c41c3585a8b..bc35570f79bc 100755
--- a/Silicon/NXP/Include/Pcie.h
+++ b/Silicon/NXP/Include/Pcie.h
@@ -205,4 +205,8 @@ STATIC inline VOID PciLsGen4Write32 (
     MmioWrite32 (Dbi + OFFSET_TO_PAGE_ADDR (Offset), Value);
   }
 }
+
+#define GPEX_ACK_REPLAY_TO                      0x438
+#define ACK_LAT_TO_VAL_SHIFT                    0
+#define ACK_LAT_TO_VAL_MASK                     0x1fff
 #endif
diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
index d9944313da21..bacdc29d60d6 100644
--- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -556,6 +556,12 @@ PcieSetupCntrl (
   if (PCI_LS_GEN4_CTRL) {
     // PCIe LsGen4 Controller Setup
 
+    // Workaround for A-011451
+    Val = PciLsGen4Read32 ((UINTN)Pcie, GPEX_ACK_REPLAY_TO);
+    Val &= ~(ACK_LAT_TO_VAL_MASK << ACK_LAT_TO_VAL_SHIFT);
+    Val |= (4 << ACK_LAT_TO_VAL_SHIFT);
+    PciLsGen4Write32 ((UINTN)Pcie, GPEX_ACK_REPLAY_TO, Val);
+
     //Fix Class Code
     Val = PciLsGen4Read32 ((UINTN)Pcie, GPEX_CLASSCODE);
     Val &= ~(GPEX_CLASSCODE_MASK << GPEX_CLASSCODE_SHIFT);
-- 
2.7.4


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

* [PATCH edk2-platforms 07/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (5 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 06/16] Silicon/NXP: PciHostBridgeLib: add Workaround for A-011451 Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:33   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 08/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows Wasim Khan
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Dump ATU windows for PCIe LsGen4 controller if PcdPciDebug
is enabled.

Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  1 +
 .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 34 ++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
index b777acdc103f..df1590172e15 100644
--- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -38,6 +38,7 @@ [FixedPcd]
   gNxpQoriqLsTokenSpaceGuid.PcdNumPciController
   gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase
   gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg
+  gNxpQoriqLsTokenSpaceGuid.PcdPciDebug
 
 [Pcd]
   gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
index bacdc29d60d6..1de20c621dc0 100644
--- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -413,6 +413,36 @@ PcieLsSetupAtu (
 }
 
 /**
+  Dump PCIe LsGen4 ATU
+
+  @param Pcie     Address of PCIe host controller.
+**/
+VOID LsGen4DumpAtu (
+  IN EFI_PHYSICAL_ADDRESS Pcie
+  )
+{
+  UINT32 Cnt;
+  for (Cnt = 0; Cnt <= IATU_REGION_INDEX6; Cnt++) {
+    DEBUG ((DEBUG_INFO,"APIO WINDOW%d:\n", Cnt));
+    DEBUG ((DEBUG_INFO,"\tLOWER PHYS 0x%08x\n",
+            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_AXI_WIN (Cnt))));
+    DEBUG ((DEBUG_INFO,"\tUPPER PHYS 0x%08x\n",
+            PciLsGen4Read32 ((UINTN)Pcie, PAB_EXT_AXI_AMAP_AXI_WIN (Cnt))));
+    DEBUG ((DEBUG_INFO,"\tLOWER BUS  0x%08x\n",
+            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_PEX_WIN_L (Cnt))));
+    DEBUG ((DEBUG_INFO,"\tUPPER BUS  0x%08x\n",
+            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_PEX_WIN_H (Cnt))));
+    DEBUG ((DEBUG_INFO,"\tSIZE      0x%08x\n",
+            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_CTRL (Cnt)) &
+            (AXI_AMAP_CTRL_SIZE_MASK << AXI_AMAP_CTRL_SIZE_SHIFT)));
+    DEBUG ((DEBUG_INFO,"\tEXT_SIZE        0x%08x\n",
+            PciLsGen4Read32 ((UINTN)Pcie, PAB_EXT_AXI_AMAP_SIZE (Cnt))));
+    DEBUG ((DEBUG_INFO,"\tCTRL:        0x%08x\n",
+            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_CTRL (Cnt))));
+  }
+}
+
+/**
   Function to set-up ATU windows for PCIe LayerscapeGen4 controller
 
   @param Pcie      Address of PCIe host controller
@@ -484,6 +514,10 @@ PcieLsGen4SetupAtu (
                             Mem64Base,
                             Mem64Base,
                             SIZE_4GB);
+
+  if (FixedPcdGetBool (PcdPciDebug) == TRUE) {
+    LsGen4DumpAtu (Pcie);
+  }
 }
 
 /**
-- 
2.7.4


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

* [PATCH edk2-platforms 08/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (6 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 07/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:31   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 09/16] Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller Wasim Khan
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Dump ATU windows for PCIe Layerscape controller if PcdPciDebug
is enabled.

Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
index 1de20c621dc0..3ad526218bcf 100644
--- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -297,6 +297,44 @@ PcieOutboundSet (
 }
 
 /**
+  Dump PCIe Layerscape ATU
+
+  @param Pcie     Address of PCIe host controller.
+**/
+VOID LsDumpAtu (
+  IN EFI_PHYSICAL_ADDRESS Pcie
+  )
+{
+  UINT32 Cnt;
+  for (Cnt = 0; Cnt <= IATU_REGION_INDEX7; Cnt++) {
+    MmioWrite32 ((UINTN)Pcie + IATU_VIEWPORT_OFF,
+                  (UINT32)(IATU_VIEWPORT_OUTBOUND | Cnt));
+
+    DEBUG ((DEBUG_INFO, "iATU%d:\n",Cnt));
+    DEBUG ((DEBUG_INFO, "\tLOWER PHYS 0x%08x\n",
+            MmioRead32 ((UINTN)Pcie + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0)));
+
+    DEBUG ((DEBUG_INFO, "\tUPPER PHYS 0x%08x\n",
+            MmioRead32 ((UINTN)Pcie + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0)));
+
+    DEBUG ((DEBUG_INFO, "\tLOWER BUS 0x%08x\n",
+            MmioRead32 ((UINTN)Pcie + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0)));
+
+    DEBUG ((DEBUG_INFO, "\tUPPER BUS 0x%08x\n",
+            MmioRead32 ((UINTN)Pcie + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0)));
+
+    DEBUG ((DEBUG_INFO, "\tLIMIT     0x%08x\n",
+            MmioRead32 ((UINTN)Pcie + IATU_LIMIT_ADDR_OFF_OUTBOUND_0)));
+
+    DEBUG ((DEBUG_INFO, "\tCR1       0x%08x\n",
+            MmioRead32 ((UINTN)Pcie + IATU_REGION_CTRL_1_OFF_OUTBOUND_0)));
+
+    DEBUG ((DEBUG_INFO, "\tCR2       0x%08x\n",
+            MmioRead32 ((UINTN)Pcie + IATU_REGION_CTRL_2_OFF_OUTBOUND_0)));
+  }
+}
+
+/**
   Function to set-up iATU windows for Layerscape PCIe controller
 
   @param Pcie      Address of PCIe host controller
@@ -410,6 +448,10 @@ PcieLsSetupAtu (
     SEG_IO_BUS,
     SEG_IO_SIZE
     );
+
+  if (FixedPcdGetBool (PcdPciDebug) == TRUE) {
+    LsDumpAtu (Pcie);
+  }
 }
 
 /**
-- 
2.7.4


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

* [PATCH edk2-platforms 09/16] Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (7 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 08/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:29   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 10/16] Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS Controller Wasim Khan
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

We have different PCI config space region for bus 0 (Controller space) and
bus[0x1-0xff] on NXP SoCs with PCIe LS controller.
Add PciSegmentLib for PCIe LS controller.

For config transactions for Bus0:
  - Config transaction address = PCIe controller address + offset

For config transactions for Bus[0x1-0xff]:
  - PCIe IP requires target BDF to be written at bit[31:16] of PCIe
    type0/type1 outbound window.
  - Config transaction address = PCIe config space address + offset

Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  32 ++
 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 612 +++++++++++++++++++++
 2 files changed, 644 insertions(+)
 create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
 create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c

diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
new file mode 100755
index 000000000000..a36e79239b33
--- /dev/null
+++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
@@ -0,0 +1,32 @@
+## @file
+#  PCI Segment Library for NXP SoCs with multiple RCs
+#
+#  Copyright 2018-2020 NXP
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = PciSegmentLib
+  FILE_GUID                      = c9f59261-5a60-4a4c-82f6-1f520442e100
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciSegmentLib|DXE_DRIVER
+  CONSTRUCTOR                    = PciSegLibInit
+
+[Sources]
+  PciSegmentLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  Silicon/NXP/NxpQoriqLs.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
+  PcdLib
+
+[FixedPcd]
+  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
new file mode 100755
index 000000000000..ecd36971b753
--- /dev/null
+++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
@@ -0,0 +1,612 @@
+/** @file
+  PCI Segment Library for NXP SoCs with multiple RCs
+
+  Copyright 2018-2020 NXP
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <PiDxe.h>
+#include <Base.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Pcie.h>
+
+typedef enum {
+  PciCfgWidthUint8      = 0,
+  PciCfgWidthUint16,
+  PciCfgWidthUint32,
+  PciCfgWidthMax
+} PCI_CFG_WIDTH;
+
+/**
+  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)
+
+STATIC
+UINT64
+PciLsCfgTarget (
+  IN  EFI_PHYSICAL_ADDRESS Dbi,
+  IN  UINT64               Address,
+  IN  UINT16               Segment,
+  IN  UINT8                Bus,
+  IN  UINT16               Offset
+  )
+{
+  UINT32 Target;
+
+  Target = ((((Address >> 20) & 0xFF) << 24) |
+           (((Address >> 15) & 0x1F) << 19) |
+           (((Address >> 12) & 0x7) << 16));
+
+  if (Bus > 1) {
+    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF, IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX1);
+  } else {
+    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF, IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX0);
+  }
+
+  MmioWrite32 ((UINTN)Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0, Target);
+
+  if (Bus > 1) {
+    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment + SEG_CFG_SIZE + Offset;
+  } else {
+    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment + Offset;
+  }
+}
+
+/**
+  Function to return PCIe Physical Address(PCIe view) or Controller
+  Address(CPU view) for different RCs
+
+  @param  Address Address passed from bus layer.
+  @param  Segment Segment number for Root Complex.
+  @param  Offset  Config space register offset.
+  @param  Bus     PCIe Bus number.
+
+  @return Return PCIe CPU or Controller address.
+
+**/
+STATIC
+UINT64
+PciLsGetConfigBase (
+  IN  UINT64      Address,
+  IN  UINT16      Segment,
+  IN  UINT16      Offset,
+  IN  UINT8       Bus
+  )
+{
+  UINT32 CfgAddr;
+
+  CfgAddr = (UINT16)Offset;
+  if (Bus) {
+    return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, Address, Segment, Bus, Offset);
+  } else {
+    return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
+  }
+}
+
+/**
+  Function to return PCIe Physical Address(PCIe view) or Controller
+  Address(CPU view) for different RCs
+
+  @param  Address Address passed from bus layer.
+  @param  Segment Segment number for Root Complex.
+  @param  Offset  Config space register offset.
+
+  @return Return PCIe CPU or Controller address.
+
+**/
+STATIC
+UINT64
+PciSegmentLibGetConfigBase (
+  IN  UINT64      Address,
+  IN  UINT16      Segment,
+  IN  UINT16      Offset
+  )
+{
+  UINT8  Bus;
+
+  Bus = ((UINT32)Address >> 20) & 0xff;
+  return PciLsGetConfigBase (Address, Segment, Offset, Bus);
+}
+
+/**
+  Internal worker function to read a PCI configuration register.
+
+  @param  Address The address that encodes the Segment, 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;
+  UINT16    Offset;
+  UINT16    Segment;
+
+  Segment = (Address >> 32);
+  Offset = (Address & 0xfff );
+
+  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
+
+  // ignore devices > 0 on bus 0
+  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
+    return MAX_UINT32;
+  }
+
+  // ignore device > 0 on bus 1
+  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
+    return MAX_UINT32;
+  }
+
+  switch (Width) {
+  case PciCfgWidthUint8:
+    return MmioRead8 (Base);
+  case PciCfgWidthUint16:
+    return MmioRead16 (Base);
+  case PciCfgWidthUint32:
+    return MmioRead32 (Base);
+  default:
+    ASSERT (FALSE);
+  }
+
+  return CHAR_NULL;
+}
+
+/**
+  Internal worker function to writes a PCI configuration register.
+
+  @param  Address The address that encodes the Segment, 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;
+  UINT32    Offset;
+  UINT16    Segment;
+
+  Segment = (Address >> 32);
+  Offset = (Address & 0xfff );
+
+  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
+
+  // ignore devices > 0 on bus 0
+  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
+    return Data;
+  }
+
+  // ignore device > 0 on bus 1
+  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
+    return MAX_UINT32;
+  }
+
+  switch (Width) {
+  case PciCfgWidthUint8:
+    MmioWrite8 (Base , Data);
+    break;
+  case PciCfgWidthUint16:
+    MmioWrite16 (Base , Data);
+    break;
+  case PciCfgWidthUint32:
+    MmioWrite32 (Base , Data);
+    break;
+  default:
+    ASSERT (FALSE);
+  }
+
+  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.
+
+  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);
+}
+
+/**
+  Reads a 16-bit PCI configuration register.
+
+  Reads and returns 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().
+
+  @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.
+
+  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);
+}
+
+/**
+  Reads a 32-bit PCI configuration register.
+
+  Reads and returns the 32-bit PCI configuration register specified by Address.
+
+  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.
+
+  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);
+}
+
+/**
+  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.
+
+  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) <= SIZE_4KB);
+
+  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 + BIT0;
+  }
+
+  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 + BIT0;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Read as many double words as possible
+    //
+    WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*)Buffer + BIT0;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Read the last remaining word if exist
+    //
+    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + BIT0;
+  }
+
+  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.
+
+  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) <= SIZE_4KB);
+
+  if (Size == 0) {
+    return Size;
+  }
+
+  ASSERT (Buffer != NULL);
+
+  //
+  // 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 + BIT0;
+  }
+
+  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 + BIT0;
+  }
+
+  while (Size >= sizeof (UINT32)) {
+    //
+    // Write as many double words as possible
+    //
+    PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));
+    StartAddress += sizeof (UINT32);
+    Size -= sizeof (UINT32);
+    Buffer = (UINT32*)Buffer + BIT0;
+  }
+
+  if (Size >= sizeof (UINT16)) {
+    //
+    // Write the last remaining word if exist
+    //
+    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
+    StartAddress += sizeof (UINT16);
+    Size -= sizeof (UINT16);
+    Buffer = (UINT16*)Buffer + BIT0;
+  }
+
+  if (Size >= sizeof (UINT8)) {
+    //
+    // Write the last remaining byte if exist
+    //
+    PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer);
+  }
+
+  return ReturnValue;
+}
+
+EFI_STATUS
+PciSegLibInit (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
-- 
2.7.4


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

* [PATCH edk2-platforms 10/16] Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS Controller
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (8 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 09/16] Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:36   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 11/16] Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller Wasim Khan
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

PCIe Layerscape controller can be enabled for ECAM style
configuration access using CFG SHIFT Feature.

Check for PcdPciCfgShiftEnable to decide the configuration access
scheme to be used with PCIe LS controller.

Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf |  3 +++
 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c   | 20 ++++++++++++++++----
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
index a36e79239b33..936213dc8a9d 100755
--- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
+++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
@@ -30,3 +30,6 @@ [LibraryClasses]
 
 [FixedPcd]
   gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
+
+[Pcd]
+  gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
index ecd36971b753..552a425c6832 100755
--- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
+++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
@@ -34,6 +34,8 @@ typedef enum {
 #define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \
   ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0)
 
+static BOOLEAN CfgShiftEnable;
+
 STATIC
 UINT64
 PciLsCfgTarget (
@@ -88,11 +90,20 @@ PciLsGetConfigBase (
 {
   UINT32 CfgAddr;
 
-  CfgAddr = (UINT16)Offset;
-  if (Bus) {
-    return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, Address, Segment, Bus, Offset);
+  if (CfgShiftEnable) {
+    CfgAddr = (UINT32)Address;
+    if (Bus) {
+      return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment + CfgAddr;
+    } else {
+      return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
+    }
   } else {
-    return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
+    CfgAddr = (UINT16)Offset;
+    if (Bus) {
+      return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, Address, Segment, Bus, Offset);
+    } else {
+      return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
+    }
   }
 }
 
@@ -608,5 +619,6 @@ PciSegLibInit (
   IN EFI_SYSTEM_TABLE  *SystemTable
   )
 {
+  CfgShiftEnable = CFG_SHIFT_ENABLE;
   return EFI_SUCCESS;
 }
-- 
2.7.4


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

* [PATCH edk2-platforms 11/16] Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (9 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 10/16] Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS Controller Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:38   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 12/16] Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264 Wasim Khan
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

PCIe Layerscape Gen4 controller is not ECAM complaint and have
different PCI config space region for bus 0 (Controller space) and
bus[0x1-0xff] on NXP SoCs.

For config transactions for Bus0:
  - Config transaction address = PCIe controller address + offset

For config transactions for Bus[0x1-0xff]:
  - PCIe IP requires target BDF to be written at bit[31:16] of PCIe
    outbound configuration window.

PCIe LsGen4 controller uses paging mechanism to access registers.
To access PCIe CCSR registers which are above 3KB offset, page number
must be set in Bridge Control Register.

Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  1 +
 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 60 +++++++++++++++++++++-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
index 936213dc8a9d..d6d7ea6e3b6b 100755
--- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
+++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
@@ -33,3 +33,4 @@ [FixedPcd]
 
 [Pcd]
   gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
+  gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl
diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
index 552a425c6832..02a1525ef308 100755
--- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
+++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
@@ -35,6 +35,58 @@ typedef enum {
   ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0)
 
 static BOOLEAN CfgShiftEnable;
+static BOOLEAN PciLsGen4Ctrl;
+
+STATIC
+VOID
+PcieCfgSetTarget (
+  IN EFI_PHYSICAL_ADDRESS Dbi,
+  IN UINT32 Target)
+{
+    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_L(0), Target);
+    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_H(0), 0);
+}
+
+/**
+  Function to return PCIe Physical Address(PCIe view) or Controller
+  Address(CPU view) for NXP Layerscape Gen4 SoC
+
+  @param  Address Address passed from bus layer.
+  @param  Segment Segment number for Root Complex.
+  @param  Offset  Config space register offset.
+  @param  Bus     PCIe Bus number.
+
+  @return Return PCIe CPU or Controller address.
+
+**/
+STATIC
+UINT64
+PciLsGen4GetConfigBase (
+  IN  UINT64      Address,
+  IN  UINT16      Segment,
+  IN  UINT16      Offset,
+  IN  UINT8       Bus
+  )
+{
+  UINT32 Target;
+
+  if (Bus) {
+    Target = ((((Address >> 20) & 0xFF) << 24) |
+             (((Address >> 15) & 0x1F) << 19) |
+             (((Address >> 12) & 0x7) << 16));
+
+    PcieCfgSetTarget ((PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF* Segment), Target);
+    return PCI_SEG0_MMIO_MEMBASE + Offset + PCI_BASE_DIFF * Segment;
+  } else {
+      if (Offset < INDIRECT_ADDR_BNDRY) {
+        PciLsGen4SetPg (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, 0);
+        return (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + Offset);
+      }
+      PciLsGen4SetPg (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, OFFSET_TO_PAGE_IDX (Offset));
+      Offset = OFFSET_TO_PAGE_ADDR (Offset);
+      return (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + Offset);
+  }
+}
 
 STATIC
 UINT64
@@ -129,7 +181,12 @@ PciSegmentLibGetConfigBase (
   UINT8  Bus;
 
   Bus = ((UINT32)Address >> 20) & 0xff;
-  return PciLsGetConfigBase (Address, Segment, Offset, Bus);
+
+  if (PciLsGen4Ctrl) {
+    return PciLsGen4GetConfigBase (Address, Segment, Offset, Bus);
+  } else {
+    return PciLsGetConfigBase (Address, Segment, Offset, Bus);
+  }
 }
 
 /**
@@ -620,5 +677,6 @@ PciSegLibInit (
   )
 {
   CfgShiftEnable = CFG_SHIFT_ENABLE;
+  PciLsGen4Ctrl = PCI_LS_GEN4_CTRL;
   return EFI_SUCCESS;
 }
-- 
2.7.4


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

* [PATCH edk2-platforms 12/16] Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (10 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 11/16] Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:39   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 13/16] Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver Wasim Khan
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

With PCIe LsGen4 controller, clearing the Bus Master Enable bit in
Command register blocks all outbound transactions to be sent out
in RC mode.

According to PCI Express base specification, the Command register’s
Bus Master Enable bit of a PCI Express RC controller can only
control the forwarding of memory requests received at its root port
in the upstream direction. In other words, clearing the Bus Master
Enable bit must not block all outbound transactions to be sent out
toward RC’s downstream devices. Due to this erratum, when the
Command register’s Bus Master Enable bit is cleared, all the outbound
transactions from the device’s internal bus masters, including but
not limited to configuration read and write transactions, are
terminated with the slave error (SLVERR) response status on the PCI
Express RC controller’s internal AXI bus interface.

Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
index 02a1525ef308..c3bc14820ea5 100755
--- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
+++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
@@ -39,6 +39,21 @@ static BOOLEAN PciLsGen4Ctrl;
 
 STATIC
 VOID
+PciLsGen4SetBusMaster (
+  IN EFI_PHYSICAL_ADDRESS Dbi
+  )
+{
+  UINT32 Val;
+
+  /* Make sure the Master Enable bit not cleared */
+  Val = PciLsGen4Read32 ((UINTN)Dbi, PCI_COMMAND_OFFSET);
+  if (!(Val & EFI_PCI_COMMAND_BUS_MASTER)) {
+    PciLsGen4Write32 ((UINTN)Dbi, PCI_COMMAND_OFFSET, Val | EFI_PCI_COMMAND_BUS_MASTER);
+  }
+}
+
+STATIC
+VOID
 PcieCfgSetTarget (
   IN EFI_PHYSICAL_ADDRESS Dbi,
   IN UINT32 Target)
@@ -71,6 +86,8 @@ PciLsGen4GetConfigBase (
   UINT32 Target;
 
   if (Bus) {
+    PciLsGen4SetBusMaster (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF* Segment);
+
     Target = ((((Address >> 20) & 0xFF) << 24) |
              (((Address >> 15) & 0x1F) << 19) |
              (((Address >> 12) & 0x7) << 16));
-- 
2.7.4


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

* [PATCH edk2-platforms 13/16] Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (11 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 12/16] Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264 Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:42   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 14/16] Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg Wasim Khan
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

NXP SoC has multiple PCIe RCs and there is no fix translation
offset between I/O port accesses and MMIO accesses.
Add PciCpuIo2Dxe driver to implement EFI_CPU_IO2_PROTOCOL
to add the translation for different RCs for IO access.

Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf |  40 ++
 Silicon/NXP/Include/Pcie.h                        |  19 +
 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c   | 628 ++++++++++++++++++++++
 3 files changed, 687 insertions(+)
 create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
 create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c

diff --git a/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
new file mode 100755
index 000000000000..0ee470e41d5e
--- /dev/null
+++ b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
@@ -0,0 +1,40 @@
+## @file
+#  Produces the CPU I/O 2 Protocol by using the services of the I/O Library.
+#
+# Copyright 2018, 2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = PciCpuIo2Dxe
+  FILE_GUID                      = 7bff18d7-9aae-434b-9c06-f10a7e157eac
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PciCpuIo2Initialize
+
+[Sources]
+  PciCpuIo2Dxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  Silicon/NXP/NxpQoriqLs.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Pcd]
+  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
+  gNxpQoriqLsTokenSpaceGuid.PcdNumPciController
+
+[Protocols]
+  gEfiCpuIo2ProtocolGuid                         ## PRODUCES
+
+[Depex]
+  TRUE
diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
index bc35570f79bc..b561d0e3ba11 100755
--- a/Silicon/NXP/Include/Pcie.h
+++ b/Silicon/NXP/Include/Pcie.h
@@ -39,6 +39,25 @@
 #define PCI_SEG0_PHY_MEM_BASE     PCI_SEG0_MMIO_MEMBASE + SEG_MEM_BASE
 #define PCI_SEG0_PHY_MEM64_BASE   PCI_SEG0_MMIO_MEMBASE + SEG_MEM64_BASE
 #define PCI_SEG0_PHY_IO_BASE      PCI_SEG0_MMIO_MEMBASE + SEG_IO_BASE
+#define PCI_SEG0_PORTIO_MIN       0x0
+#define PCI_SEG0_PORTIO_MAX       0xffff
+#define PCI_SEG0_PORTIO_OFFSET    0x0
+#define PCI_SEG1_PORTIO_MIN       0x0
+#define PCI_SEG1_PORTIO_MAX       0xffff
+#define PCI_SEG1_PORTIO_OFFSET    0x10000
+#define PCI_SEG2_PORTIO_MIN       0x0
+#define PCI_SEG2_PORTIO_MAX       0xffff
+#define PCI_SEG2_PORTIO_OFFSET    0x20000
+#define PCI_SEG3_PORTIO_MIN       0x0
+#define PCI_SEG3_PORTIO_MAX       0xffff
+#define PCI_SEG3_PORTIO_OFFSET    0x30000
+#define PCI_SEG4_PORTIO_MIN       0x0
+#define PCI_SEG4_PORTIO_MAX       0xffff
+#define PCI_SEG4_PORTIO_OFFSET    0x40000
+#define PCI_SEG5_PORTIO_MIN       0x0
+#define PCI_SEG5_PORTIO_MAX       0xffff
+#define PCI_SEG5_PORTIO_OFFSET    0x50000
+#define PCI_SEG_PORTIO_LIMIT      PCI_SEG5_PORTIO_MAX + PCI_SEG5_PORTIO_OFFSET
 
 // PCIe Controller configuration
 #define NUM_PCIE_CONTROLLER       FixedPcdGet32 (PcdNumPciController)
diff --git a/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c
new file mode 100755
index 000000000000..17db44a8b510
--- /dev/null
+++ b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c
@@ -0,0 +1,628 @@
+/** @file
+  Produces the CPU I/O 2 Protocol.
+
+  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
+  Copyright 2018-2020 NXP
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Pcie.h>
+#include <Protocol/CpuIo2.h>
+
+#define MAX_IO_PORT_ADDRESS PCI_SEG_PORTIO_LIMIT
+
+//
+// Handle for the CPU I/O 2 Protocol
+//
+STATIC EFI_HANDLE  mHandle = NULL;
+
+//
+// Lookup table for increment values based on transfer widths
+//
+STATIC CONST UINT8 mInStride[] = {
+  1, // EfiCpuIoWidthUint8
+  2, // EfiCpuIoWidthUint16
+  4, // EfiCpuIoWidthUint32
+  8, // EfiCpuIoWidthUint64
+  0, // EfiCpuIoWidthFifoUint8
+  0, // EfiCpuIoWidthFifoUint16
+  0, // EfiCpuIoWidthFifoUint32
+  0, // EfiCpuIoWidthFifoUint64
+  1, // EfiCpuIoWidthFillUint8
+  2, // EfiCpuIoWidthFillUint16
+  4, // EfiCpuIoWidthFillUint32
+  8  // EfiCpuIoWidthFillUint64
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+STATIC CONST UINT8 mOutStride[] = {
+  1, // EfiCpuIoWidthUint8
+  2, // EfiCpuIoWidthUint16
+  4, // EfiCpuIoWidthUint32
+  8, // EfiCpuIoWidthUint64
+  1, // EfiCpuIoWidthFifoUint8
+  2, // EfiCpuIoWidthFifoUint16
+  4, // EfiCpuIoWidthFifoUint32
+  8, // EfiCpuIoWidthFifoUint64
+  0, // EfiCpuIoWidthFillUint8
+  0, // EfiCpuIoWidthFillUint16
+  0, // EfiCpuIoWidthFillUint32
+  0  // EfiCpuIoWidthFillUint64
+};
+
+/**
+  Check parameters to a CPU I/O 2 Protocol service request.
+
+  The I/O operations are carried out exactly as requested. The caller is responsible
+  for satisfying any alignment and I/O width restrictions that a PI System on a
+  platform might require. For example on some platforms, width requests of
+  EfiCpuIoWidthUint64 do not work.
+
+  @param[in] MmioOperation  TRUE for an MMIO operation, FALSE for I/O Port operation.
+  @param[in] Width          Signifies the width of the I/O or Memory operation.
+  @param[in] Address        The base address of the I/O operation.
+  @param[in] Count          The number of I/O operations to perform. The number of
+                            bytes moved is Width size * Count, starting at Address.
+  @param[in] Buffer         For read operations, the destination buffer to store the results.
+                            For write operations, the source buffer from which to write data.
+
+  @retval EFI_SUCCESS            The parameters for this request pass the checks.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
+  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
+                                 and Count is not valid for this PI system.
+
+**/
+STATIC
+EFI_STATUS
+CpuIoCheckParameter (
+  IN BOOLEAN                    MmioOperation,
+  IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                     Address,
+  IN UINTN                      Count,
+  IN VOID                       *Buffer
+  )
+{
+  UINT64  MaxCount;
+  UINT64  Limit;
+
+  //
+  // Check to see if Buffer is NULL
+  //
+  if (Buffer == NULL) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check to see if Width is in the valid range
+  //
+  if ((UINT32)Width >= EfiCpuIoWidthMaximum) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // For FIFO type, the target address won't increase during the access,
+  // so treat Count as 1
+  //
+  if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+    Count = 1;
+  }
+
+  //
+  // Check to see if Width is in the valid range for I/O Port operations
+  //
+  Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
+  if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check to see if Address is aligned
+  //
+  if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
+    ASSERT (FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check to see if any address associated with this transfer exceeds the maximum
+  // allowed address.  The maximum address implied by the parameters passed in is
+  // Address + Size * Count.  If the following condition is met, then the transfer
+  // is not supported.
+  //
+  //    Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
+  //
+  // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
+  // can also be the maximum integer value supported by the CPU, this range
+  // check must be adjusted to avoid all oveflow conditions.
+  //
+  Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
+  if (Count == 0) {
+    if (Address > Limit) {
+      ASSERT (FALSE);
+      return EFI_UNSUPPORTED;
+    }
+  } else {
+    MaxCount = RShiftU64 (Limit, Width);
+    if (MaxCount < (Count - 1)) {
+      ASSERT (FALSE);
+      return EFI_UNSUPPORTED;
+    }
+    if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
+      ASSERT (FALSE);
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  //
+  // Check to see if Buffer is aligned
+  //
+  if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width])  - 1))) != 0) {
+    ASSERT (FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Reads memory-mapped registers.
+
+  The I/O operations are carried out exactly as requested. The caller is responsible
+  for satisfying any alignment and I/O width restrictions that a PI System on a
+  platform might require. For example on some platforms, width requests of
+  EfiCpuIoWidthUint64 do not work.
+
+  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+  each of the Count operations that is performed.
+
+  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+  incremented for each of the Count operations that is performed. The read or
+  write operation is performed Count times on the same Address.
+
+  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+  incremented for each of the Count operations that is performed. The read or
+  write operation is performed Count times from the first element of Buffer.
+
+  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+  @param[in]  Width    Signifies the width of the I/O or Memory operation.
+  @param[in]  Address  The base address of the I/O operation.
+  @param[in]  Count    The number of I/O operations to perform. The number of
+                       bytes moved is Width size * Count, starting at Address.
+  @param[out] Buffer   For read operations, the destination buffer to store the results.
+                       For write operations, the source buffer from which to write data.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PI system.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
+  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
+                                 and Count is not valid for this PI system.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+  IN  EFI_CPU_IO2_PROTOCOL       *This,
+  IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                     Address,
+  IN  UINTN                      Count,
+  OUT VOID                       *Buffer
+  )
+{
+  EFI_STATUS                 Status;
+  UINT8                      InStride;
+  UINT8                      OutStride;
+  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
+  UINT8                      *Uint8Buffer;
+
+  Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Select loop based on the width of the transfer
+  //
+  InStride = mInStride[Width];
+  OutStride = mOutStride[Width];
+  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+    if (OperationWidth == EfiCpuIoWidthUint8) {
+      *Uint8Buffer = MmioRead8 ((UINTN)Address);
+    } else if (OperationWidth == EfiCpuIoWidthUint16) {
+      *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+    } else if (OperationWidth == EfiCpuIoWidthUint32) {
+      *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+    } else if (OperationWidth == EfiCpuIoWidthUint64) {
+      *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Writes memory-mapped registers.
+
+  The I/O operations are carried out exactly as requested. The caller is responsible
+  for satisfying any alignment and I/O width restrictions that a PI System on a
+  platform might require. For example on some platforms, width requests of
+  EfiCpuIoWidthUint64 do not work.
+
+  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+  each of the Count operations that is performed.
+
+  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+  incremented for each of the Count operations that is performed. The read or
+  write operation is performed Count times on the same Address.
+
+  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+  incremented for each of the Count operations that is performed. The read or
+  write operation is performed Count times from the first element of Buffer.
+
+  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+  @param[in]  Width    Signifies the width of the I/O or Memory operation.
+  @param[in]  Address  The base address of the I/O operation.
+  @param[in]  Count    The number of I/O operations to perform. The number of
+                       bytes moved is Width size * Count, starting at Address.
+  @param[in]  Buffer   For read operations, the destination buffer to store the results.
+                       For write operations, the source buffer from which to write data.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PI system.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
+  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
+                                 and Count is not valid for this PI system.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+  IN EFI_CPU_IO2_PROTOCOL       *This,
+  IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                     Address,
+  IN UINTN                      Count,
+  IN VOID                       *Buffer
+  )
+{
+  EFI_STATUS                 Status;
+  UINT8                      InStride;
+  UINT8                      OutStride;
+  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
+  UINT8                      *Uint8Buffer;
+
+  Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Select loop based on the width of the transfer
+  //
+  InStride = mInStride[Width];
+  OutStride = mOutStride[Width];
+  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+    if (OperationWidth == EfiCpuIoWidthUint8) {
+      MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+    } else if (OperationWidth == EfiCpuIoWidthUint16) {
+      MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+    } else if (OperationWidth == EfiCpuIoWidthUint32) {
+      MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+    } else if (OperationWidth == EfiCpuIoWidthUint64) {
+      MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+TranslateIoAddress (
+  IN  OUT UINT64                 *Address
+  )
+{
+  UINT64 Start;
+  UINT64 End;
+  UINT64 Shift;
+  UINT64 SegIoHostAddressBase;
+
+  SegIoHostAddressBase = PCI_SEG0_PHY_IO_BASE;
+  Start = PCI_SEG0_PORTIO_MIN + PCI_SEG0_PORTIO_OFFSET;
+  End   = PCI_SEG0_PORTIO_MAX + PCI_SEG0_PORTIO_OFFSET;
+  Shift = SegIoHostAddressBase - PCI_SEG0_PORTIO_OFFSET;
+
+  if (*Address >= Start && *Address <= End) {
+    *Address += Shift;
+    return EFI_SUCCESS;
+  }
+
+  Start = PCI_SEG1_PORTIO_MIN + PCI_SEG1_PORTIO_OFFSET;
+  End   = PCI_SEG1_PORTIO_MAX + PCI_SEG1_PORTIO_OFFSET;
+  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 1)) - PCI_SEG1_PORTIO_OFFSET;
+
+  if (*Address >= Start && *Address <= End) {
+    *Address += Shift;
+    return EFI_SUCCESS;
+  }
+
+  Start = PCI_SEG2_PORTIO_MIN + PCI_SEG2_PORTIO_OFFSET;
+  End   = PCI_SEG2_PORTIO_MAX + PCI_SEG2_PORTIO_OFFSET;
+  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 2)) - PCI_SEG2_PORTIO_OFFSET;
+
+  if (*Address >= Start && *Address <= End) {
+    *Address += Shift;
+    return EFI_SUCCESS;
+  }
+
+  Start = PCI_SEG3_PORTIO_MIN + PCI_SEG3_PORTIO_OFFSET;
+  End   = PCI_SEG3_PORTIO_MAX + PCI_SEG3_PORTIO_OFFSET;
+  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 3)) - PCI_SEG3_PORTIO_OFFSET;
+
+  if (*Address >= Start && *Address <= End) {
+    *Address += Shift;
+    return EFI_SUCCESS;
+  }
+
+  Start = PCI_SEG4_PORTIO_MIN + PCI_SEG4_PORTIO_OFFSET;
+  End   = PCI_SEG4_PORTIO_MAX + PCI_SEG4_PORTIO_OFFSET;
+  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 4)) - PCI_SEG4_PORTIO_OFFSET;
+
+  if (*Address >= Start && *Address <= End) {
+    *Address += Shift;
+    return EFI_SUCCESS;
+  }
+
+  Start = PCI_SEG5_PORTIO_MIN + PCI_SEG5_PORTIO_OFFSET;
+  End   = PCI_SEG5_PORTIO_MAX + PCI_SEG5_PORTIO_OFFSET;
+  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 5)) - PCI_SEG5_PORTIO_OFFSET;
+
+  if (*Address >= Start && *Address <= End) {
+    *Address += Shift;
+    return EFI_SUCCESS;
+  }
+  ASSERT (FALSE);
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+  Reads I/O registers.
+
+  The I/O operations are carried out exactly as requested. The caller is responsible
+  for satisfying any alignment and I/O width restrictions that a PI System on a
+  platform might require. For example on some platforms, width requests of
+  EfiCpuIoWidthUint64 do not work.
+
+  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+  each of the Count operations that is performed.
+
+  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+  incremented for each of the Count operations that is performed. The read or
+  write operation is performed Count times on the same Address.
+
+  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+  incremented for each of the Count operations that is performed. The read or
+  write operation is performed Count times from the first element of Buffer.
+
+  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+  @param[in]  Width    Signifies the width of the I/O or Memory operation.
+  @param[in]  Address  The base address of the I/O operation.
+  @param[in]  Count    The number of I/O operations to perform. The number of
+                       bytes moved is Width size * Count, starting at Address.
+  @param[out] Buffer   For read operations, the destination buffer to store the results.
+                       For write operations, the source buffer from which to write data.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PI system.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
+  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
+                                 and Count is not valid for this PI system.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+  IN  EFI_CPU_IO2_PROTOCOL       *This,
+  IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                     Address,
+  IN  UINTN                      Count,
+  OUT VOID                       *Buffer
+  )
+{
+  EFI_STATUS                 Status;
+  UINT8                      InStride;
+  UINT8                      OutStride;
+  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
+  UINT8                      *Uint8Buffer;
+
+  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = TranslateIoAddress (&Address);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Select loop based on the width of the transfer
+  //
+  InStride = mInStride[Width];
+  OutStride = mOutStride[Width];
+  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
+
+  for (Uint8Buffer = Buffer; Count > 0;
+       Address += InStride, Uint8Buffer += OutStride, Count--) {
+    if (OperationWidth == EfiCpuIoWidthUint8) {
+      *Uint8Buffer = MmioRead8 ((UINTN)Address);
+    } else if (OperationWidth == EfiCpuIoWidthUint16) {
+      *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+    } else if (OperationWidth == EfiCpuIoWidthUint32) {
+      *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Write I/O registers.
+
+  The I/O operations are carried out exactly as requested. The caller is responsible
+  for satisfying any alignment and I/O width restrictions that a PI System on a
+  platform might require. For example on some platforms, width requests of
+  EfiCpuIoWidthUint64 do not work.
+
+  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
+  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
+  each of the Count operations that is performed.
+
+  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
+  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
+  incremented for each of the Count operations that is performed. The read or
+  write operation is performed Count times on the same Address.
+
+  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
+  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
+  incremented for each of the Count operations that is performed. The read or
+  write operation is performed Count times from the first element of Buffer.
+
+  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
+  @param[in]  Width    Signifies the width of the I/O or Memory operation.
+  @param[in]  Address  The base address of the I/O operation.
+  @param[in]  Count    The number of I/O operations to perform. The number of
+                       bytes moved is Width size * Count, starting at Address.
+  @param[in]  Buffer   For read operations, the destination buffer to store the results.
+                       For write operations, the source buffer from which to write data.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PI system.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
+  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
+                                 and Count is not valid for this PI system.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+  IN EFI_CPU_IO2_PROTOCOL       *This,
+  IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                     Address,
+  IN UINTN                      Count,
+  IN VOID                       *Buffer
+  )
+{
+  EFI_STATUS                 Status;
+  UINT8                      InStride;
+  UINT8                      OutStride;
+  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
+  UINT8                      *Uint8Buffer;
+
+  //
+  // Make sure the parameters are valid
+  //
+  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = TranslateIoAddress (&Address);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Select loop based on the width of the transfer
+  //
+  InStride = mInStride[Width];
+  OutStride = mOutStride[Width];
+  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
+
+  for (Uint8Buffer = (UINT8 *)Buffer; Count > 0;
+       Address += InStride, Uint8Buffer += OutStride, Count--) {
+    if (OperationWidth == EfiCpuIoWidthUint8) {
+      MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+    } else if (OperationWidth == EfiCpuIoWidthUint16) {
+      MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+    } else if (OperationWidth == EfiCpuIoWidthUint32) {
+      MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+//
+// CPU I/O 2 Protocol instance
+//
+STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 = {
+  {
+    CpuMemoryServiceRead,
+    CpuMemoryServiceWrite
+  },
+  {
+    CpuIoServiceRead,
+    CpuIoServiceWrite
+  }
+};
+
+
+/**
+  The user Entry Point for module CpuIo2Dxe. The user code starts with this function.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+PciCpuIo2Initialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS Status;
+
+  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mHandle,
+                  &gEfiCpuIo2ProtocolGuid, &mCpuIo2,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
-- 
2.7.4


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

* [PATCH edk2-platforms 14/16] Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (12 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 13/16] Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:42   ` Ard Biesheuvel
  2020-05-21 23:02 ` [PATCH edk2-platforms 15/16] Platform/NXP: LS1043aRdbPkg: Enable PCIE support Wasim Khan
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Enable NetworkPkg for LS1043aRdb Platform.

Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc | 11 +++++++++++
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf |  5 +++++
 2 files changed, 16 insertions(+)

diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
index d45fd67c03b5..8f7f9d171587 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
@@ -22,6 +22,13 @@ [Defines]
   OUTPUT_DIRECTORY               = Build/LS1043aRdbPkg
   FLASH_DEFINITION               = Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
 
+  #
+  # Network definition
+  #
+  DEFINE NETWORK_TLS_ENABLE             = FALSE
+  DEFINE NETWORK_HTTP_BOOT_ENABLE       = FALSE
+  DEFINE NETWORK_ISCSI_ENABLE           = FALSE
+
 !include Silicon/NXP/NxpQoriqLs.dsc.inc
 !include Silicon/NXP/LS1043A/LS1043A.dsc.inc
 
@@ -54,4 +61,8 @@ [Components.common]
   Silicon/NXP/Drivers/I2cDxe/I2cDxe.inf
   Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.inf
 
+  #
+  # Networking stack
+  #
+!include NetworkPkg/Network.dsc.inc
  ##
diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
index 931d0bb14f9b..596922221e8c 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
@@ -119,6 +119,11 @@ [FV.FvMain]
   INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
 
   #
+  # Networking stack
+  #
+!include NetworkPkg/Network.fdf.inc
+
+  #
   # FAT filesystem + GPT/MBR partitioning
   #
   INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
-- 
2.7.4


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

* [PATCH edk2-platforms 15/16] Platform/NXP: LS1043aRdbPkg: Enable PCIE support
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (13 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 14/16] Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-21 23:02 ` [PATCH edk2-platforms 16/16] Platform/NXP: LS1043aRdbPkg : Increase fv image size Wasim Khan
  2020-05-22  9:46 ` [PATCH edk2-platforms 00/16] Add PCIe Support Ard Biesheuvel
  16 siblings, 0 replies; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Enable generic PCIe drivers and Wire up PciHostBridgeLib,
PciSegmentLib and PciCpuIo2Dxe.

Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc | 9 +++++++++
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf | 7 +++++++
 2 files changed, 16 insertions(+)

diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
index 8f7f9d171587..6d07d5164002 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
@@ -35,6 +35,8 @@ [Defines]
 [LibraryClasses.common]
   ArmPlatformLib|Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
   RealTimeClockLib|Silicon/Maxim/Library/Ds1307RtcLib/Ds1307RtcLib.inf
+  PciSegmentLib|Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
+  PciHostBridgeLib|Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
 
 [PcdsFixedAtBuild.common]
   #
@@ -62,6 +64,13 @@ [Components.common]
   Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.inf
 
   #
+  # PCI
+  #
+  Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
+  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+
+  #
   # Networking stack
   #
 !include NetworkPkg/Network.dsc.inc
diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
index 596922221e8c..81142f217a63 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
@@ -124,6 +124,13 @@ [FV.FvMain]
 !include NetworkPkg/Network.fdf.inc
 
   #
+  # PCI
+  #
+  INF Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
+  INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+  INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+
+  #
   # FAT filesystem + GPT/MBR partitioning
   #
   INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
-- 
2.7.4


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

* [PATCH edk2-platforms 16/16] Platform/NXP: LS1043aRdbPkg : Increase fv image size
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (14 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 15/16] Platform/NXP: LS1043aRdbPkg: Enable PCIE support Wasim Khan
@ 2020-05-21 23:02 ` Wasim Khan
  2020-05-22  9:44   ` Ard Biesheuvel
  2020-05-22  9:46 ` [PATCH edk2-platforms 00/16] Add PCIe Support Ard Biesheuvel
  16 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan @ 2020-05-21 23:02 UTC (permalink / raw)
  To: devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi, ard.biesheuvel,
	leif, jon
  Cc: Wasim Khan

From: Wasim Khan <wasim.khan@nxp.com>

Increase fv image size to pass debug build.

Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
---
 Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
index 81142f217a63..1c160e349eb9 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
@@ -24,10 +24,12 @@
 
 [FD.LS1043ARDB_EFI]
 BaseAddress   = 0x82000000|gArmTokenSpaceGuid.PcdFdBaseAddress  #The base address of the FLASH Device.
-Size          = 0x00140000|gArmTokenSpaceGuid.PcdFdSize         #The size in bytes of the FLASH Device
+Size          = 0x00180000|gArmTokenSpaceGuid.PcdFdSize         #The size in bytes of the FLASH Device
 ErasePolarity = 1
+
+# This one is tricky, it must be: BlockSize * NumBlocks = Size
 BlockSize     = 0x40000
-NumBlocks     = 0x5
+NumBlocks     = 0x6
 
 ################################################################################
 #
@@ -44,7 +46,7 @@ [FD.LS1043ARDB_EFI]
 # RegionType <FV, DATA, or FILE>
 #
 ################################################################################
-0x00000000|0x00140000
+0x00000000|0x00180000
 gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize
 FV = FVMAIN_COMPACT
 
-- 
2.7.4


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

* Re: [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs.
  2020-05-21 23:02 ` [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs Wasim Khan
@ 2020-05-22  9:12   ` Ard Biesheuvel
  2020-05-24 18:31     ` Wasim Khan (OSS)
  0 siblings, 1 reply; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:12 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> Add PCIe related PCDs.
> 
> Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>

Please drop this signoff. This is not the correct way to acknowledge 
(co-)authorship.

> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   Silicon/NXP/NxpQoriqLs.dec | 9 +++++++++
>   1 file changed, 9 insertions(+)
> 
> diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
> index 0722f59ef4f6..bafdfd9f4298 100644
> --- a/Silicon/NXP/NxpQoriqLs.dec
> +++ b/Silicon/NXP/NxpQoriqLs.dec
> @@ -27,3 +27,12 @@ [Guids.common]
>   [PcdsFeatureFlag]
>     gNxpQoriqLsTokenSpaceGuid.PcdI2cErratumA009203|FALSE|BOOLEAN|0x00000315
>     gNxpQoriqLsTokenSpaceGuid.PcdDcfgBigEndian|FALSE|BOOLEAN|0x00000316
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian|FALSE|BOOLEAN|0x00000317
> +
> +[PcdsFixedAtBuild.common]
> +  # Pcds for PCI Express
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr|0x0|UINT64|0x00000500
> +  gNxpQoriqLsTokenSpaceGuid.PcdNumPciController|0|UINT32|0x00000501
> +  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase|0x0|UINT32|0x00000502
> +  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg|0x0|UINT32|0x00000503
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciDebug|FALSE|BOOLEAN|0x00000504
> 


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

* Re: [PATCH edk2-platforms 03/16] Silicon/NXP: Implement PciHostBridgeLib support
  2020-05-21 23:02 ` [PATCH edk2-platforms 03/16] Silicon/NXP: Implement PciHostBridgeLib support Wasim Khan
@ 2020-05-22  9:20   ` Ard Biesheuvel
  0 siblings, 0 replies; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:20 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> Implement PciHostBridgeLib that exposes the PCIe root complexes to
> the generic PCI host bridge driver.
> 
> Setup PCIe Layerscape Controller and setup CFG, IO,
> MMIO and MMIO64 iATU windows.
> 
> Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  40 ++
>   Silicon/NXP/Include/Pcie.h                         |  85 +++
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 568 +++++++++++++++++++++
>   3 files changed, 693 insertions(+)
>   create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
>   create mode 100755 Silicon/NXP/Include/Pcie.h
>   create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> 
> diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> new file mode 100644
> index 000000000000..5ddb96e4fa6a
> --- /dev/null
> +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> @@ -0,0 +1,40 @@
> +## @file
> +#  PCI Host Bridge Library instance for NXP ARM SOC
> +#
> +#  Copyright 2018-2020 NXP
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = PciHostBridgeLib
> +  FILE_GUID                      = f4c99bcc-5c95-49ad-b0f3-fc5b611dc9c1
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciHostBridgeLib
> +
> +[Sources]
> +  PciHostBridgeLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec

Do you need this?

> +  Silicon/NXP/NxpQoriqLs.dec
> +
> +[LibraryClasses]
> +  DebugLib
> +  DevicePathLib
> +  IoAccessLib
> +  MemoryAllocationLib
> +  PcdLib
> +
> +[FeaturePcd]
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian
> +
> +[FixedPcd]
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
> +  gNxpQoriqLsTokenSpaceGuid.PcdNumPciController
> +  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase
> +  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg
> diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
> new file mode 100755
> index 000000000000..d5b5a3884e0a
> --- /dev/null
> +++ b/Silicon/NXP/Include/Pcie.h
> @@ -0,0 +1,85 @@
> +/** @file
> +  PCI memory configuration for NXP
> +
> +  Copyright 2018-2020 NXP
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef __PCI_H__
> +#define __PCI_H__
> +

Please don't use leading __ for header include guards

> +#define PCI_SEG0_NUM              0
> +#define PCI_SEG1_NUM              1
> +#define PCI_SEG2_NUM              2
> +#define PCI_SEG3_NUM              3
> +#define PCI_SEG4_NUM              4
> +#define PCI_SEG5_NUM              5
> +#define PCI_SEG0_MMIO_MEMBASE     FixedPcdGet64 (PcdPciExp1BaseAddr)
> +#define PCI_SEG0_DBI_BASE         0x03400000
> +
> +#define PCI_LINK_DOWN             0x0
> +#define PCI_LINK_UP               0x1
> +
> +// Segment configuration
> +#define PCI_SEG_BUSNUM_MIN        0x0
> +#define PCI_SEG_BUSNUM_MAX        0xff
> +#define PCI_SEG_PORTIO_MIN        0x0
> +#define PCI_SEG_PORTIO_MAX        0xffff
> +#define SEG_CFG_SIZE              0x00001000
> +#define SEG_MEM_BASE              0x40000000
> +#define SEG_MEM_SIZE              0xC0000000
> +#define SEG_MEM_LIMIT             SEG_MEM_BASE + (SEG_MEM_SIZE -1)
> +#define SEG_IO_BASE               0x10000000
> +#define SEG_MEM64_BASE            0x400000000
> +#define PCI_BASE_DIFF             0x800000000
> +#define PCI_DBI_SIZE_DIFF         0x100000
> +#define PCI_SEG0_PHY_CFG0_BASE    PCI_SEG0_MMIO_MEMBASE
> +#define PCI_SEG0_PHY_CFG1_BASE    PCI_SEG0_PHY_CFG0_BASE + SEG_CFG_SIZE
> +#define PCI_SEG0_PHY_MEM_BASE     PCI_SEG0_MMIO_MEMBASE + SEG_MEM_BASE
> +#define PCI_SEG0_PHY_MEM64_BASE   PCI_SEG0_MMIO_MEMBASE + SEG_MEM64_BASE
> +#define PCI_SEG0_PHY_IO_BASE      PCI_SEG0_MMIO_MEMBASE + SEG_IO_BASE
> +
> +// PCIe Controller configuration
> +#define NUM_PCIE_CONTROLLER       FixedPcdGet32 (PcdNumPciController)
> +#define PCI_LUT_DBG               FixedPcdGet32 (PcdPcieLutDbg)
> +#define PCI_LUT_BASE              FixedPcdGet32 (PcdPcieLutBase)
> +#define LTSSM_PCIE_L0             0x11
> +
> +#define PCI_CLASS_BRIDGE_PCI      0x0604
> +#define PCI_CLASS_DEVICE          0x8
> +#define PCI_DBI_RO_WR_EN          0x8bc
> +#define CLASS_CODE_MASK           0xffff
> +#define CLASS_CODE_SHIFT          0x10
> +
> +// PCIe Layerscape Controller
> +#define IATU_VIEWPORT_OFF                            0x900
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0            0x904
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0            0x908
> +#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 IATU_VIEWPORT_OUTBOUND                       0x0
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN  BIT31
> +
> +// ATU Programming
> +#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_INDEX0        0x0
> +#define IATU_REGION_INDEX1        0x1
> +#define IATU_REGION_INDEX2        0x2
> +#define IATU_REGION_INDEX3        0x3
> +#define IATU_REGION_INDEX4        0x4
> +#define IATU_REGION_INDEX5        0x5
> +#define IATU_REGION_INDEX6        0x6
> +#define IATU_REGION_INDEX7        0x7
> +#define SEG_CFG_BUS               0x00000000
> +#define SEG_MEM_BUS               0x40000000
> +#define SEG_IO_SIZE               0x10000
> +#define SEG_IO_BUS                0x0
> +
> +#endif
> diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> new file mode 100644
> index 000000000000..cf872370c7cd
> --- /dev/null
> +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> @@ -0,0 +1,568 @@
> +/** @file
> +  PCI Host Bridge Library instance for NXP SoCs
> +
> +  Copyright 2018-2020 NXP
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <PiDxe.h>
> +#include <IndustryStandard/Pci22.h>
> +#include <Library/IoAccessLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>

Please keep these alphabetically sorted

> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Pcie.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 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
> +      PCI_SEG0_NUM
> +    },
> +
> +    {
> +      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
> +      PCI_SEG1_NUM
> +    },
> +
> +    {
> +      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
> +      PCI_SEG2_NUM
> +    },
> +
> +    {
> +      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
> +      PCI_SEG3_NUM
> +    },
> +
> +    {
> +      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
> +      PCI_SEG4_NUM
> +    },
> +
> +    {
> +      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
> +      PCI_SEG5_NUM
> +    },
> +
> +    {
> +      END_DEVICE_PATH_TYPE,
> +      END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +      {
> +        END_DEVICE_PATH_LENGTH,
> +        0
> +      }
> +    }
> +  }
> +};
> +
> +STATIC
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> +  L"Mem", L"I/O", L"Bus"
> +};
> +
> +#define PCI_ALLOCATION_ATTRIBUTES       EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | \
> +                                        EFI_PCI_HOST_BRIDGE_MEM64_DECODE
> +
> +#define PCI_SUPPORT_ATTRIBUTES          EFI_PCI_ATTRIBUTE_ISA_IO_16 | \
> +                                        EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \
> +                                        EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
> +                                        EFI_PCI_ATTRIBUTE_VGA_IO_16  | \
> +                                        EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
> +
> +PCI_ROOT_BRIDGE mPciRootBridges[NUM_PCIE_CONTROLLER];
> +
> +/**
> +   Helper function to check PCIe link state
> +
> +   @param Pcie Address of PCIe host controller.
> +
> +**/
> +STATIC
> +INTN
> +PcieLinkUp (
> +  IN EFI_PHYSICAL_ADDRESS Pcie,
> +  IN UINT32 Idx
> +  )
> +{
> +  MMIO_OPERATIONS *PcieOps;
> +  UINT32 State;
> +  UINT32 LtssmMask;
> +
> +  LtssmMask = 0x3f;
> +
> +  PcieOps = GetMmioOperations (FeaturePcdGet (PcdPciLutBigEndian));
> +  State = PcieOps->Read32 ((UINTN)Pcie + PCI_LUT_BASE + PCI_LUT_DBG) & LtssmMask;
> +
> +  if (State < LTSSM_PCIE_L0) {
> +    DEBUG ((DEBUG_INFO,"PCIE%d : reg @ 0x%lx, no link: LTSSM=0x%02x\n",
> +            Idx + 1, Pcie, State));
> +    return PCI_LINK_DOWN;
> +  }
> +
> +  return PCI_LINK_UP;
> +}
> +
> +/**
> +  Function to set-up PCIe outbound window
> +
> +  @param Dbi     Address of PCIe host controller.
> +  @param Idx     Index of iATU outbound window.
> +  @param Type    Type(Cfg0/Cfg1/Mem/IO) of iATU outbound window.
> +  @param Phys    PCIe controller phy address for outbound window.
> +  @param BusAdr  PCIe controller bus address for outbound window.
> +  @param Size    Window size
> +
> +**/
> +STATIC
> +VOID
> +PcieOutboundSet (
> +  IN EFI_PHYSICAL_ADDRESS Dbi,
> +  IN UINT32 Idx,
> +  IN UINT32 Type,
> +  IN UINT64 Phys,
> +  IN UINT64 BusAddr,
> +  IN UINT64 Size
> +  )
> +{
> +  // PCIe Layerscape : Outbound Window
> +  MmioWrite32 (Dbi + IATU_VIEWPORT_OFF,
> +                (UINT32)(IATU_VIEWPORT_OUTBOUND | Idx));
> +
> +  MmioWrite32 (Dbi + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
> +                (UINT32)Phys);
> +
> +  MmioWrite32 (Dbi + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
> +                (UINT32)(Phys >> 32));
> +
> +  MmioWrite32 (Dbi + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
> +                (UINT32)(Phys + Size - BIT0));
> +
> +  MmioWrite32 (Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> +                (UINT32)BusAddr);
> +
> +  MmioWrite32 (Dbi + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
> +                (UINT32)(BusAddr >> 32));
> +
> +  MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
> +                (UINT32)Type);
> +
> +  MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> +                IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
> +}
> +
> +/**
> +  Function to set-up iATU windows for Layerscape PCIe controller
> +
> +  @param Pcie      Address of PCIe host controller
> +  @param Cfg0Base  PCIe controller phy address Type0 Configuration Space.
> +  @param Cfg1Base  PCIe controller phy address Type1 Configuration Space.
> +  @param MemBase   PCIe controller phy address Memory Space.
> +  @param Mem64Base PCIe controller phy address MMIO64 Space.
> +  @param IoBase    PCIe controller phy address IO Space.
> +**/
> +STATIC
> +VOID
> +PcieLsSetupAtu (
> +  IN EFI_PHYSICAL_ADDRESS Pcie,
> +  IN EFI_PHYSICAL_ADDRESS Cfg0Base,
> +  IN EFI_PHYSICAL_ADDRESS Cfg1Base,
> +  IN EFI_PHYSICAL_ADDRESS MemBase,
> +  IN EFI_PHYSICAL_ADDRESS Mem64Base,
> +  IN EFI_PHYSICAL_ADDRESS IoBase
> +  )
> +{
> +  UINT64 Cfg0BaseAddr;
> +  UINT64 Cfg1BaseAddr;
> +  UINT64 Cfg0BusAddress;
> +  UINT64 Cfg1BusAddress;
> +  UINT64 Cfg0Size;
> +  UINT64 Cfg1Size;
> +
> +  Cfg0BaseAddr = Cfg0Base;
> +  Cfg1BaseAddr = Cfg1Base;
> +  Cfg0BusAddress = SEG_CFG_BUS;
> +  Cfg1BusAddress = SEG_CFG_BUS;
> +  Cfg0Size = SEG_CFG_SIZE;
> +  Cfg1Size = SEG_CFG_SIZE;
> +
> +  // iATU : OUTBOUND WINDOW 1 : CFG0
> +  PcieOutboundSet (Pcie,
> +    IATU_REGION_INDEX0,
> +    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0,
> +    Cfg0BaseAddr,
> +    Cfg0BusAddress,
> +    Cfg0Size);
> +
> +  // iATU : OUTBOUND WINDOW 2 : CFG1
> +  PcieOutboundSet (Pcie,
> +    IATU_REGION_INDEX1,
> +    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1,
> +    Cfg1BaseAddr,
> +    Cfg1BusAddress,
> +    Cfg1Size);
> +
> +  // iATU : OUTBOUND WINDOW 3 : MEM
> +  PcieOutboundSet (Pcie,
> +    IATU_REGION_INDEX2,
> +    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> +    MemBase,
> +    SEG_MEM_BUS,
> +    SEG_MEM_SIZE);
> +
> +  // iATU : OUTBOUND WINDOW 4 : MMIO64
> +  PcieOutboundSet (Pcie,
> +    IATU_REGION_INDEX3,
> +    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> +    Mem64Base,
> +    Mem64Base,
> +    SIZE_4GB);
> +  Mem64Base += SIZE_4GB;
> +
> +  // iATU : OUTBOUND WINDOW 5 : MMIO64
> +  PcieOutboundSet (Pcie,
> +    IATU_REGION_INDEX4,
> +    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> +    Mem64Base,
> +    Mem64Base,
> +    SIZE_4GB);
> +  Mem64Base += SIZE_4GB;
> +
> +  // iATU : OUTBOUND WINDOW 6 : MMIO64
> +  PcieOutboundSet (Pcie,
> +    IATU_REGION_INDEX5,
> +    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> +    Mem64Base,
> +    Mem64Base,
> +    SIZE_4GB
> +    );
> +  Mem64Base += SIZE_4GB;
> +
> +  // iATU : OUTBOUND WINDOW 7 : MMIO64
> +  PcieOutboundSet (Pcie,
> +    IATU_REGION_INDEX6,
> +    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
> +    Mem64Base,
> +    Mem64Base,
> +    SIZE_4GB
> +    );
> +

This logic only works correctly if the window is exactly 16 GB in size. 
You should at least put an ASSERT() somewhere, but even better would be 
to make this code work as expected for any window size

> +  // iATU : OUTBOUND WINDOW 8: IO
> +  PcieOutboundSet (Pcie,
> +    IATU_REGION_INDEX7,
> +    IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO,
> +    IoBase,
> +    SEG_IO_BUS,
> +    SEG_IO_SIZE
> +    );
> +}
> +/**
> +  Helper function to set-up PCIe controller
> +
> +  @param Pcie       Address of PCIe host controller
> +  @param Cfg0Base   PCIe controller phy address Type0 Configuration Space.
> +  @param Cfg1Base   PCIe controller phy address Type1 Configuration Space.
> +  @param MemBase    PCIe controller phy address Memory Space.
> +  @param Mem64Base  PCIe controller phy address MMIO64 Space.
> +  @param IoBase     PCIe controller phy address IO Space.
> +
> +**/
> +STATIC
> +VOID
> +PcieSetupCntrl (
> +  IN EFI_PHYSICAL_ADDRESS Pcie,
> +  IN EFI_PHYSICAL_ADDRESS Cfg0Base,
> +  IN EFI_PHYSICAL_ADDRESS Cfg1Base,
> +  IN EFI_PHYSICAL_ADDRESS MemBase,
> +  IN EFI_PHYSICAL_ADDRESS Mem64Base,
> +  IN EFI_PHYSICAL_ADDRESS IoBase
> +  )
> +{
> +  UINT32 Val;
> +
> +  // PCIe Layerscape Controller Setup
> +  PcieLsSetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base, IoBase);
> +
> +  // Program Class code for Layerscape PCIe controller
> +  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 1);
> +  Val = MmioRead32 ((UINTN)Pcie + PCI_CLASS_DEVICE);
> +  Val &= ~(CLASS_CODE_MASK << CLASS_CODE_SHIFT);
> +  Val |= (PCI_CLASS_BRIDGE_PCI << CLASS_CODE_SHIFT);
> +  MmioWrite32 ((UINTN)Pcie + PCI_CLASS_DEVICE, Val);
> +  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 0);
> +}
> +
> +/**
> +  Return all the root bridge instances in an array.
> +
> +  @param Count  Return the count of root bridge instances.
> +
> +  @return All the root bridge instances in an array.
> +
> +**/
> +PCI_ROOT_BRIDGE *
> +EFIAPI
> +PciHostBridgeGetRootBridges (
> +  OUT UINTN     *Count
> +  )
> +{
> +  UINTN         Idx;
> +  UINTN         Loop;
> +  UINT64        PciPhyMemAddr[NUM_PCIE_CONTROLLER];
> +  UINT64        PciPhyMem64Addr[NUM_PCIE_CONTROLLER];
> +  UINT64        PciPhyCfg0Addr[NUM_PCIE_CONTROLLER];
> +  UINT64        PciPhyCfg1Addr[NUM_PCIE_CONTROLLER];
> +  UINT64        PciPhyIoAddr[NUM_PCIE_CONTROLLER];
> +  UINT64        Regs[NUM_PCIE_CONTROLLER];
> +  INTN          LinkUp;
> +
> +  for  (Idx = 0, Loop = 0; Idx < NUM_PCIE_CONTROLLER; Idx++) {
> +    PciPhyMemAddr[Idx] = PCI_SEG0_PHY_MEM_BASE + (PCI_BASE_DIFF * Idx);
> +    PciPhyMem64Addr[Idx] = PCI_SEG0_PHY_MEM64_BASE + (PCI_BASE_DIFF * Idx);
> +    PciPhyCfg0Addr[Idx] = PCI_SEG0_PHY_CFG0_BASE + (PCI_BASE_DIFF * Idx);
> +    PciPhyCfg1Addr[Idx] = PCI_SEG0_PHY_CFG1_BASE + (PCI_BASE_DIFF * Idx);
> +    PciPhyIoAddr [Idx] =  PCI_SEG0_PHY_IO_BASE + (PCI_BASE_DIFF * Idx);
> +    Regs[Idx] =  PCI_SEG0_DBI_BASE + (PCI_DBI_SIZE_DIFF * Idx);
> +
> +    // Check PCIe Link
> +    LinkUp = PcieLinkUp(Regs[Idx], Idx);
> +
> +    if (!LinkUp) {
> +      continue;
> +    }
> +    DEBUG ((DEBUG_INFO, "PCIE%d Passed Linkup Phase\n", Idx + 1));
> +    // Set up PCIe Controller and ATU windows
> +    PcieSetupCntrl (Regs[Idx],
> +                    PciPhyCfg0Addr[Idx],
> +                    PciPhyCfg1Addr[Idx],
> +                    PciPhyMemAddr[Idx],
> +                    PciPhyMem64Addr[Idx],
> +                    PciPhyIoAddr[Idx]);
> +
> +    mPciRootBridges[Loop].Segment               = Idx;
> +    mPciRootBridges[Loop].Supports              = PCI_SUPPORT_ATTRIBUTES;
> +    mPciRootBridges[Loop].Attributes            = PCI_SUPPORT_ATTRIBUTES;
> +    mPciRootBridges[Loop].DmaAbove4G            = TRUE;
> +    mPciRootBridges[Loop].NoExtendedConfigSpace = FALSE;
> +    mPciRootBridges[Loop].ResourceAssigned      = FALSE;
> +    mPciRootBridges[Loop].AllocationAttributes  = PCI_ALLOCATION_ATTRIBUTES;
> +
> +    mPciRootBridges[Loop].Bus.Base              = PCI_SEG_BUSNUM_MIN;
> +    mPciRootBridges[Loop].Bus.Limit             = PCI_SEG_BUSNUM_MAX;
> +
> +    mPciRootBridges[Loop].Io.Base               = PCI_SEG_PORTIO_MIN;
> +    mPciRootBridges[Loop].Io.Limit              = PCI_SEG_PORTIO_MAX;
> +    mPciRootBridges[Loop].Io.Translation        = MAX_UINT64 -
> +                                                  (SEG_IO_SIZE * Idx) + 1;
> +
> +    mPciRootBridges[Loop].Mem.Base              = SEG_MEM_BASE;
> +    mPciRootBridges[Loop].Mem.Limit             = SEG_MEM_LIMIT;
> +    mPciRootBridges[Loop].Mem.Translation       = MAX_UINT64 -
> +                                                  (PCI_SEG0_MMIO_MEMBASE +
> +                                                  (PCI_BASE_DIFF *
> +                                                  Idx)) + 1;
> +
> +    mPciRootBridges[Loop].MemAbove4G.Base       = PciPhyMem64Addr[Idx];
> +    mPciRootBridges[Loop].MemAbove4G.Limit      = PciPhyMem64Addr[Idx] +
> +                                                  (SIZE_16GB - 1);
> +
> +    mPciRootBridges[Loop].PMem.Base             = MAX_UINT64;
> +    mPciRootBridges[Loop].PMem.Limit            = 0;
> +    mPciRootBridges[Loop].PMemAbove4G.Base      = MAX_UINT64;
> +    mPciRootBridges[Loop].PMemAbove4G.Limit     = 0;
> +    mPciRootBridges[Loop].DevicePath            = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Idx];
> +    Loop++;
> +  }
> +
> +  if (Loop == 0) {
> +    return NULL;
> +  }
> +
> +  *Count = Loop;
> +  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;

I know this is copy/paste from elsewhere but please insert a newline here

> +  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
> +                   );
> +  }
> +
> +  return;
> +}
> 


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

* Re: [PATCH edk2-platforms 04/16] Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS Ctrl
  2020-05-21 23:02 ` [PATCH edk2-platforms 04/16] Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS Ctrl Wasim Khan
@ 2020-05-22  9:22   ` Ard Biesheuvel
  0 siblings, 0 replies; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:22 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> PCIe layerscape controller supports CFG Shift feature. It can be
> enabled by setting BIT[28] of iATU Control 2 Register.
> Check PcdPciCfgShiftEnable to enable 'CFG Shift feature' in
> PCIe controller.
> if enable, PCIe layerscape controller shifts BDF from bits[27:12] to
> bits[31:16] and supports Enhanced Configuration Address Mapping (ECAM)
> mechanism.
> 
> PCIe layerscape controller is ECAM complaint for bus[0x1-0xff].
> So create outbound CFG windows from 1MB-256MB (255 buses) for
> type0/type1 configuration access.
> PCIe layerscape controller is Non-ECAM complaint for bus 0.It does
> not support device > 0 on bus 0. PciSegmentLib should handles this
> limitation.
> 
> Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   Silicon/NXP/NxpQoriqLs.dec                         |  3 ++
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  3 ++
>   Silicon/NXP/Include/Pcie.h                         |  3 ++
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 35 +++++++++++++++++-----
>   4 files changed, 36 insertions(+), 8 deletions(-)
> 
> diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
> index bafdfd9f4298..293fd773fd3d 100644
> --- a/Silicon/NXP/NxpQoriqLs.dec
> +++ b/Silicon/NXP/NxpQoriqLs.dec
> @@ -36,3 +36,6 @@ [PcdsFixedAtBuild.common]
>     gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase|0x0|UINT32|0x00000502
>     gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg|0x0|UINT32|0x00000503
>     gNxpQoriqLsTokenSpaceGuid.PcdPciDebug|FALSE|BOOLEAN|0x00000504
> +
> +[PcdsDynamic.common]
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable|FALSE|BOOLEAN|0x00000600
> diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> index 5ddb96e4fa6a..98cfb6aee6b0 100644
> --- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> @@ -38,3 +38,6 @@ [FixedPcd]
>     gNxpQoriqLsTokenSpaceGuid.PcdNumPciController
>     gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase
>     gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg
> +
> +[Pcd]
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
> diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
> index d5b5a3884e0a..ae85190180e8 100755
> --- a/Silicon/NXP/Include/Pcie.h
> +++ b/Silicon/NXP/Include/Pcie.h
> @@ -63,6 +63,7 @@
>   #define IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0        0x91C
>   #define IATU_VIEWPORT_OUTBOUND                       0x0
>   #define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN  BIT31
> +#define IATU_ENABLE_CFG_SHIFT_FEATURE                BIT28
>   
>   // ATU Programming
>   #define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM   0x0
> @@ -82,4 +83,6 @@
>   #define SEG_IO_SIZE               0x10000
>   #define SEG_IO_BUS                0x0
>   
> +#define CFG_SHIFT_ENABLE          (PcdGetBool (PcdPciCfgShiftEnable))
> +
>   #endif
> diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> index cf872370c7cd..f92863c60868 100644
> --- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> @@ -259,8 +259,17 @@ PcieOutboundSet (
>     MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
>                   (UINT32)Type);
>   
> -  MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> -                IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
> +  if (CFG_SHIFT_ENABLE &&
> +     ((Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0) ||
> +     (Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1))) {
> +       MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> +         (IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN |
> +         IATU_ENABLE_CFG_SHIFT_FEATURE)
> +         );
> +  } else {
> +    MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> +                  IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
> +  }
>   }
>   
>   /**
> @@ -291,12 +300,22 @@ PcieLsSetupAtu (
>     UINT64 Cfg0Size;
>     UINT64 Cfg1Size;
>   
> -  Cfg0BaseAddr = Cfg0Base;
> -  Cfg1BaseAddr = Cfg1Base;
> -  Cfg0BusAddress = SEG_CFG_BUS;
> -  Cfg1BusAddress = SEG_CFG_BUS;
> -  Cfg0Size = SEG_CFG_SIZE;
> -  Cfg1Size = SEG_CFG_SIZE;
> +  if (CFG_SHIFT_ENABLE) {
> +    DEBUG ((DEBUG_INFO, "PCIe: CFG Shit Method Enabled \n"));

Please add the missing 'f'

> +    Cfg0BaseAddr = Cfg0Base + SIZE_1MB;
> +    Cfg1BaseAddr = Cfg0Base + SIZE_2MB;
> +    Cfg0BusAddress = SIZE_1MB;
> +    Cfg1BusAddress = SIZE_2MB;
> +    Cfg0Size = SIZE_1MB;
> +    Cfg1Size = (SIZE_256MB - SIZE_1MB); // 255MB

This logic would be much more self-explanatory if you used a symbolic 
constant 'ECAM_BUS_SIZE' instead of SIZE_1MB (and add a comment that 
type 0 CFG TLPs only go to bus #1)

> +  } else {
> +    Cfg0BaseAddr = Cfg0Base;
> +    Cfg1BaseAddr = Cfg1Base;
> +    Cfg0BusAddress = SEG_CFG_BUS;
> +    Cfg1BusAddress = SEG_CFG_BUS;
> +    Cfg0Size = SEG_CFG_SIZE;
> +    Cfg1Size = SEG_CFG_SIZE;
> +  }
>   
>     // iATU : OUTBOUND WINDOW 1 : CFG0
>     PcieOutboundSet (Pcie,
> 



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

* Re: [PATCH edk2-platforms 05/16] Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU Windows
  2020-05-21 23:02 ` [PATCH edk2-platforms 05/16] Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU Windows Wasim Khan
@ 2020-05-22  9:24   ` Ard Biesheuvel
  2020-05-24 18:31     ` Wasim Khan (OSS)
  0 siblings, 1 reply; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:24 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> Setup PCIe LayerscapeGen4 controller and setup CFG, IO,
> MMIO and MMIO64 iATU windows.
> Check for PcdPciLsGen4Ctrl to enable LsGen4 PCIe
> controller.
> 
> Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>

How much overlap is there between these controllers? Does it really make 
sense to use the same PciHostBridgeLib implementation and parameterize 
the hell out of it?


> ---
>   Silicon/NXP/NxpQoriqLs.dec                         |   1 +
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |   1 +
>   Silicon/NXP/Include/Pcie.h                         | 120 ++++++++++
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 255 +++++++++++++++++----
>   4 files changed, 336 insertions(+), 41 deletions(-)
> 
> diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
> index 293fd773fd3d..8271d19ed8e5 100644
> --- a/Silicon/NXP/NxpQoriqLs.dec
> +++ b/Silicon/NXP/NxpQoriqLs.dec
> @@ -39,3 +39,4 @@ [PcdsFixedAtBuild.common]
>   
>   [PcdsDynamic.common]
>     gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable|FALSE|BOOLEAN|0x00000600
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl|FALSE|BOOLEAN|0x00000601
> diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> index 98cfb6aee6b0..b777acdc103f 100644
> --- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> @@ -41,3 +41,4 @@ [FixedPcd]
>   
>   [Pcd]
>     gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl
> diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
> index ae85190180e8..4c41c3585a8b 100755
> --- a/Silicon/NXP/Include/Pcie.h
> +++ b/Silicon/NXP/Include/Pcie.h
> @@ -84,5 +84,125 @@
>   #define SEG_IO_BUS                0x0
>   
>   #define CFG_SHIFT_ENABLE          (PcdGetBool (PcdPciCfgShiftEnable))
> +#define PCI_LS_GEN4_CTRL          (PcdGetBool (PcdPciLsGen4Ctrl))
>   
> +// PCIe Layerscape Gen4 Controller
> +#define GPEX_CLASSCODE                          0x474
> +#define GPEX_CLASSCODE_SHIFT                    16
> +#define GPEX_CLASSCODE_MASK                     0xffff
> +#define PAB_AXI_PIO_CTRL(Idx)                   (0x840 + 0x10 * Idx)
> +#define APIO_EN                                 0x1
> +#define MEM_WIN_EN                              0x1 << 1
> +#define IO_WIN_EN                               0x1 << 2
> +#define CFG_WIN_EN                              0x1 << 3
> +#define PAB_PEX_PIO_CTRL(Idx)                   (0x8c0 + 0x10 * Idx)
> +#define PPIO_EN                                 (0x1 << 0)
> +#define PAB_PEX_PIO_STAT(Idx)                   (0x8c4 + 0x10 * Idx)
> +#define PAB_PEX_PIO_MT_STAT(Idx)                (0x8c8 + 0x10 * Idx)
> +#define PEX_AMAP_CTRL_TYPE_SHIFT                0x1
> +#define PEX_AMAP_CTRL_EN_SHIFT                  0x0
> +#define PEX_AMAP_CTRL_TYPE_MASK                 0x3
> +#define PEX_AMAP_CTRL_EN_MASK                   0x1
> +#define PAB_PEX_AMAP_CTRL(Idx)                  (0x4ba0 + 0x10 * Idx)
> +#define PAB_EXT_PEX_AMAP_SIZE(Idx)              (0xbef0 + 0x04 * Idx)
> +#define PAB_PEX_AMAP_AXI_WIN(Idx)               (0x4ba4 + 0x10 * Idx)
> +#define PAB_EXT_PEX_AMAP_AXI_WIN(Idx)           (0xb4a0 + 0x04 * Idx)
> +#define PAB_PEX_AMAP_PEX_WIN_L(Idx)             (0x4ba8 + 0x10 * Idx)
> +#define PAB_PEX_AMAP_PEX_WIN_H(Idx)             (0x4bac + 0x10 * Idx)
> +#define PAB_CTRL                                0x808
> +#define PAB_CTRL_APIO_EN                        0x1
> +#define PAB_CTRL_PPIO_EN                        (0x1 << 1)
> +#define PAB_CTRL_PAGE_SEL_SHIFT                 13
> +#define PAB_CTRL_PAGE_SEL_MASK                  0x3f
> +#define INDIRECT_ADDR_BNDRY                     0xc00
> +#define PAGE_IDX_SHIFT                          10
> +#define PAGE_ADDR_MASK                          0x3ff
> +#define PAB_AXI_AMAP_CTRL(Idx)                  (0xba0 + 0x10 * Idx)
> +#define PAB_EXT_AXI_AMAP_SIZE(Idx)              (0xbaf0 + 0x4 * Idx)
> +#define PAB_AXI_AMAP_AXI_WIN(Idx)               (0xba4 + 0x10 * Idx)
> +#define PAB_EXT_AXI_AMAP_AXI_WIN(Idx)           (0x80a0 + 0x4 * Idx)
> +#define PAB_AXI_AMAP_PEX_WIN_L(Idx)             (0xba8 + 0x10 * Idx)
> +#define PAB_AXI_AMAP_PEX_WIN_H(Idx)             (0xbac + 0x10 * Idx)
> +#define PAB_AXI_TYPE_CFG                        0x00
> +#define PAB_AXI_TYPE_IO                         0x01
> +#define PAB_AXI_TYPE_MEM                        0x02
> +#define AXI_AMAP_CTRL_EN                        0x1
> +#define AXI_AMAP_CTRL_TYPE_SHIFT                1
> +#define AXI_AMAP_CTRL_TYPE_MASK                 0x3
> +#define AXI_AMAP_CTRL_SIZE_SHIFT                10
> +#define AXI_AMAP_CTRL_SIZE_MASK                 0x3fffff
> +
> +
> +#define OFFSET_TO_PAGE_IDX(Off)                 ((Off >> PAGE_IDX_SHIFT) \
> +                                                & PAB_CTRL_PAGE_SEL_MASK)
> +
> +#define OFFSET_TO_PAGE_ADDR(Off)                ((Off & PAGE_ADDR_MASK) \
> +                                                | INDIRECT_ADDR_BNDRY)
> +/**
> +  Function to set page for LsGen4 Ctrl
> +
> +  @param  Dbi    GPEX host controller address.
> +  @param  PgIdx  The page index to select
> +
> +**/
> +STATIC inline VOID PciLsGen4SetPg (
> +  IN EFI_PHYSICAL_ADDRESS Dbi,
> +  IN UINT8 PgIdx
> +  )
> +{
> +  UINT32 Val;
> +  Val = MmioRead32 (Dbi + PAB_CTRL);
> +  Val &= ~(PAB_CTRL_PAGE_SEL_MASK << PAB_CTRL_PAGE_SEL_SHIFT);
> +  Val |= (PgIdx & PAB_CTRL_PAGE_SEL_MASK) << PAB_CTRL_PAGE_SEL_SHIFT;
> +  MmioWrite32 (Dbi + PAB_CTRL, Val);
> +}
> +
> +/**
> +  Function to read LsGen4 PCIe controller config space
> +  LsGen4 PCIe controller requires page number to be set
> +  in Bridge Control Register(PAB) for offset > 3KB.
> +
> +  @param  Dbi     GPEX host controller address.
> +  @param  Offset  Offset to read from
> +
> +**/
> +STATIC inline INTN PciLsGen4Read32 (
> +  IN EFI_PHYSICAL_ADDRESS Dbi,
> +  IN UINT32 Offset
> +  )
> +{
> +  if (Offset < INDIRECT_ADDR_BNDRY) {
> +    PciLsGen4SetPg (Dbi, 0);
> +    return MmioRead32 (Dbi + Offset);
> +  } else {
> +    // If Offset > 3KB, paging mechanism is used
> +    // Select page index and offset within the page
> +    PciLsGen4SetPg (Dbi, OFFSET_TO_PAGE_IDX (Offset));
> +    return MmioRead32 (Dbi + OFFSET_TO_PAGE_ADDR (Offset));
> +  }
> +}
> +
> +/**
> +  Function to write to LsGen4 PCIe controller config space
> +  LsGen4 PCIe controller requires page number to be set
> +  in Bridge Control Register(PAB) for offset > 3KB.
> +
> +  @param  Dbi     GPEX host controller address
> +  @param  Offset  Offset to read from
> +
> +**/
> +STATIC inline VOID PciLsGen4Write32 (
> +  IN EFI_PHYSICAL_ADDRESS Dbi,
> +  IN UINT32 Offset,
> +  IN UINT32 Value
> +  )
> +{
> +  if (Offset < INDIRECT_ADDR_BNDRY) {
> +    PciLsGen4SetPg (Dbi, 0);
> +    MmioWrite32 (Dbi + Offset, Value);
> +  } else {
> +    PciLsGen4SetPg (Dbi, OFFSET_TO_PAGE_IDX (Offset));
> +    MmioWrite32 (Dbi + OFFSET_TO_PAGE_ADDR (Offset), Value);
> +  }
> +}
>   #endif
> diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> index f92863c60868..d9944313da21 100644
> --- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> @@ -201,7 +201,11 @@ PcieLinkUp (
>     UINT32 State;
>     UINT32 LtssmMask;
>   
> -  LtssmMask = 0x3f;
> +  if (PCI_LS_GEN4_CTRL) {
> +    LtssmMask = 0x7f;
> +  } else {
> +    LtssmMask = 0x3f;
> +  }
>   
>     PcieOps = GetMmioOperations (FeaturePcdGet (PcdPciLutBigEndian));
>     State = PcieOps->Read32 ((UINTN)Pcie + PCI_LUT_BASE + PCI_LUT_DBG) & LtssmMask;
> @@ -237,38 +241,58 @@ PcieOutboundSet (
>     IN UINT64 Size
>     )
>   {
> -  // PCIe Layerscape : Outbound Window
> -  MmioWrite32 (Dbi + IATU_VIEWPORT_OFF,
> -                (UINT32)(IATU_VIEWPORT_OUTBOUND | Idx));
> +  UINT32 Val;
>   
> -  MmioWrite32 (Dbi + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
> -                (UINT32)Phys);
> -
> -  MmioWrite32 (Dbi + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
> -                (UINT32)(Phys >> 32));
> -
> -  MmioWrite32 (Dbi + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
> -                (UINT32)(Phys + Size - BIT0));
> -
> -  MmioWrite32 (Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> -                (UINT32)BusAddr);
> -
> -  MmioWrite32 (Dbi + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
> -                (UINT32)(BusAddr >> 32));
> -
> -  MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
> -                (UINT32)Type);
> -
> -  if (CFG_SHIFT_ENABLE &&
> -     ((Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0) ||
> -     (Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1))) {
> -       MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> -         (IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN |
> -         IATU_ENABLE_CFG_SHIFT_FEATURE)
> -         );
> +  if (PCI_LS_GEN4_CTRL) {
> +    // PCIe Layerscape Gen4: Outbound Window
> +    Size = ~(Size -1 );
> +    Val = PciLsGen4Read32 ((UINTN)Dbi, PAB_AXI_AMAP_CTRL (Idx));
> +    Val &= ~((AXI_AMAP_CTRL_TYPE_MASK << AXI_AMAP_CTRL_TYPE_SHIFT) |
> +              (AXI_AMAP_CTRL_SIZE_MASK << AXI_AMAP_CTRL_SIZE_SHIFT) |
> +              AXI_AMAP_CTRL_EN);
> +    Val |= ((Type & AXI_AMAP_CTRL_TYPE_MASK) << AXI_AMAP_CTRL_TYPE_SHIFT) |
> +             (((UINT32)Size >> AXI_AMAP_CTRL_SIZE_SHIFT) <<
> +             AXI_AMAP_CTRL_SIZE_SHIFT) | AXI_AMAP_CTRL_EN;
> +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_CTRL (Idx), Val);
> +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_AXI_WIN (Idx), (UINT32)Phys);
> +    PciLsGen4Write32 ((UINTN)Dbi, PAB_EXT_AXI_AMAP_AXI_WIN (Idx), Phys >> 32);
> +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_L (Idx), (UINT32)BusAddr);
> +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_H (Idx), BusAddr >> 32);
> +    PciLsGen4Write32 ((UINTN)Dbi, PAB_EXT_AXI_AMAP_SIZE (Idx), Size >> 32);
>     } else {
> -    MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> -                  IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
> +    // PCIe Layerscape : Outbound Window
> +    MmioWrite32 (Dbi + IATU_VIEWPORT_OFF,
> +                  (UINT32)(IATU_VIEWPORT_OUTBOUND | Idx));
> +
> +    MmioWrite32 (Dbi + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
> +                  (UINT32)Phys);
> +
> +    MmioWrite32 (Dbi + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
> +                  (UINT32)(Phys >> 32));
> +
> +    MmioWrite32 (Dbi + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
> +                  (UINT32)(Phys + Size - BIT0));
> +
> +    MmioWrite32 (Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> +                  (UINT32)BusAddr);
> +
> +    MmioWrite32 (Dbi + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
> +                  (UINT32)(BusAddr >> 32));
> +
> +    MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
> +                  (UINT32)Type);
> +
> +    if (CFG_SHIFT_ENABLE &&
> +       ((Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0) ||
> +       (Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1))) {
> +         MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> +           (IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN |
> +           IATU_ENABLE_CFG_SHIFT_FEATURE)
> +           );
> +    } else {
> +      MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> +                    IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
> +    }
>     }
>   }
>   
> @@ -387,6 +411,124 @@ PcieLsSetupAtu (
>       SEG_IO_SIZE
>       );
>   }
> +
> +/**
> +  Function to set-up ATU windows for PCIe LayerscapeGen4 controller
> +
> +  @param Pcie      Address of PCIe host controller
> +  @param Cfg0Base  PCIe controller phy address Type0 Configuration Space.
> +  @param Cfg1Base  PCIe controller phy address Type1 Configuration Space.
> +  @param MemBase   PCIe controller phy address Memory Space.
> +  @param Mem64Base PCIe controller phy address MMIO64 Space.
> +  @param IoBase    PCIe controller phy address IO Space.
> +**/
> +STATIC
> +VOID
> +PcieLsGen4SetupAtu (
> +  IN EFI_PHYSICAL_ADDRESS Pcie,
> +  IN EFI_PHYSICAL_ADDRESS Cfg0Base,
> +  IN EFI_PHYSICAL_ADDRESS Cfg1Base,
> +  IN EFI_PHYSICAL_ADDRESS MemBase,
> +  IN EFI_PHYSICAL_ADDRESS Mem64Base,
> +  IN EFI_PHYSICAL_ADDRESS IoBase
> +  )
> +{
> +  // ATU : OUTBOUND WINDOW 1 : CFG0
> +  PcieOutboundSet (Pcie, IATU_REGION_INDEX0,
> +                         PAB_AXI_TYPE_CFG,
> +                         Cfg0Base,
> +                         SEG_CFG_BUS,
> +                         SEG_CFG_SIZE);
> +
> +  // ATU : OUTBOUND WINDOW 2 : IO
> +  PcieOutboundSet (Pcie, IATU_REGION_INDEX1,
> +                         PAB_AXI_TYPE_IO,
> +                         IoBase,
> +                         SEG_IO_BUS,
> +                         SEG_IO_SIZE);
> +
> +  // ATU : OUTBOUND WINDOW 3 : MEM
> +  PcieOutboundSet (Pcie, IATU_REGION_INDEX2,
> +                         PAB_AXI_TYPE_MEM,
> +                         MemBase,
> +                         SEG_MEM_BUS,
> +                         SEG_MEM_SIZE);
> +
> +  // ATU : OUTBOUND WINDOW 4 : MMIO64
> +  PcieOutboundSet (Pcie, IATU_REGION_INDEX3,
> +                            PAB_AXI_TYPE_MEM,
> +                            Mem64Base,
> +                            Mem64Base,
> +                            SIZE_4GB);
> +  Mem64Base += SIZE_4GB;
> +
> +  // ATU : OUTBOUND WINDOW 5 : MMIO64
> +  PcieOutboundSet (Pcie, IATU_REGION_INDEX4,
> +                            PAB_AXI_TYPE_MEM,
> +                            Mem64Base,
> +                            Mem64Base,
> +                            SIZE_4GB);
> +  Mem64Base += SIZE_4GB;
> +
> +  // ATU : OUTBOUND WINDOW 6 : MMIO64
> +  PcieOutboundSet (Pcie, IATU_REGION_INDEX5,
> +                            PAB_AXI_TYPE_MEM,
> +                            Mem64Base,
> +                            Mem64Base,
> +                            SIZE_4GB);
> +  Mem64Base += SIZE_4GB;
> +
> +  // ATU : OUTBOUND WINDOW 7 : MMIO64
> +  PcieOutboundSet (Pcie, IATU_REGION_INDEX6,
> +                            PAB_AXI_TYPE_MEM,
> +                            Mem64Base,
> +                            Mem64Base,
> +                            SIZE_4GB);
> +}
> +
> +/**
> +  Function to set-up PCIe inbound window
> +
> +  @param Pcie    Address of PCIe host controller.
> +  @param Idx     Index of inbound window.
> +  @param Type    Type(Cfg/Mem/IO) of iATU outbound window.
> +  @param Phys    PCIe controller phy address for inbound window.
> +  @param BusAdr  PCIe controller bus address for inbound window.
> +  @param Size    Window size
> +
> +**/
> +
> +STATIC
> +VOID
> +PciSetupInBoundWin (
> +  IN EFI_PHYSICAL_ADDRESS Pcie,
> +  IN UINT32 Idx,
> +  IN UINT32  Type,
> +  IN UINT64 Phys,
> +  IN UINT64 BusAddr,
> +  IN UINT64 Size)
> +{
> +  UINT32 Val;
> +  UINT64 WinSize;
> +
> +  if (PCI_LS_GEN4_CTRL) {
> +    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_PEX_AMAP_CTRL(Idx));
> +    Val &= ~(PEX_AMAP_CTRL_TYPE_MASK << PEX_AMAP_CTRL_TYPE_SHIFT);
> +    Val &= ~(PEX_AMAP_CTRL_EN_MASK << PEX_AMAP_CTRL_EN_SHIFT);
> +    Val = (Val | (Type << PEX_AMAP_CTRL_TYPE_SHIFT));
> +    Val = (Val | (1 << PEX_AMAP_CTRL_EN_SHIFT));
> +
> +    WinSize = ~(Size - 1);
> +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_CTRL(Idx),
> +                       (Val | (UINT32)WinSize));
> +    PciLsGen4Write32 ((UINTN)Pcie, PAB_EXT_PEX_AMAP_SIZE(Idx), (WinSize>>32));
> +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_AXI_WIN(Idx), (UINT32)Phys);
> +    PciLsGen4Write32 ((UINTN)Pcie, PAB_EXT_PEX_AMAP_AXI_WIN(Idx), (Phys>>32));
> +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_PEX_WIN_L(Idx), (UINT32)BusAddr);
> +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_PEX_WIN_H(Idx), (BusAddr >>32));
> +  }
> +}
> +
>   /**
>     Helper function to set-up PCIe controller
>   
> @@ -411,16 +553,47 @@ PcieSetupCntrl (
>   {
>     UINT32 Val;
>   
> -  // PCIe Layerscape Controller Setup
> -  PcieLsSetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base, IoBase);
> -
> -  // Program Class code for Layerscape PCIe controller
> -  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 1);
> -  Val = MmioRead32 ((UINTN)Pcie + PCI_CLASS_DEVICE);
> -  Val &= ~(CLASS_CODE_MASK << CLASS_CODE_SHIFT);
> -  Val |= (PCI_CLASS_BRIDGE_PCI << CLASS_CODE_SHIFT);
> -  MmioWrite32 ((UINTN)Pcie + PCI_CLASS_DEVICE, Val);
> -  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 0);
> +  if (PCI_LS_GEN4_CTRL) {
> +    // PCIe LsGen4 Controller Setup
> +
> +    //Fix Class Code
> +    Val = PciLsGen4Read32 ((UINTN)Pcie, GPEX_CLASSCODE);
> +    Val &= ~(GPEX_CLASSCODE_MASK << GPEX_CLASSCODE_SHIFT);
> +    Val |= PCI_CLASS_BRIDGE_PCI << GPEX_CLASSCODE_SHIFT;
> +    PciLsGen4Write32 ((UINTN)Pcie, GPEX_CLASSCODE, Val);
> +
> +    // Enable APIO and Memory/IO/CFG Windows
> +    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_PIO_CTRL (0));
> +    Val |= APIO_EN | MEM_WIN_EN | IO_WIN_EN | CFG_WIN_EN;
> +    PciLsGen4Write32 ((UINTN)Pcie, PAB_AXI_PIO_CTRL (0), Val);
> +
> +    // LsGen4 Inbound Window Setup
> +    PciSetupInBoundWin (Pcie, 0, PAB_AXI_TYPE_MEM, 0 , 0, SIZE_1TB);
> +
> +    // LsGen4 Outbound Window Setup
> +    PcieLsGen4SetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base, IoBase);
> +
> +    // Enable AMBA & PEX PIO
> +    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_CTRL);
> +    Val |= PAB_CTRL_APIO_EN | PAB_CTRL_PPIO_EN;
> +    PciLsGen4Write32 ((UINTN)Pcie, PAB_CTRL, Val);
> +
> +    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_PEX_PIO_CTRL(0));
> +    Val |= PPIO_EN;
> +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_PIO_CTRL(0), Val);
> +
> +  } else {
> +    // PCIe Layerscape Controller Setup
> +    PcieLsSetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base, IoBase);
> +
> +    // Program Class code for Layerscape PCIe controller
> +    MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 1);
> +    Val = MmioRead32 ((UINTN)Pcie + PCI_CLASS_DEVICE);
> +    Val &= ~(CLASS_CODE_MASK << CLASS_CODE_SHIFT);
> +    Val |= (PCI_CLASS_BRIDGE_PCI << CLASS_CODE_SHIFT);
> +    MmioWrite32 ((UINTN)Pcie + PCI_CLASS_DEVICE, Val);
> +    MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 0);
> +  }
>   }
>   
>   /**
> 


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

* Re: [PATCH edk2-platforms 09/16] Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller
  2020-05-21 23:02 ` [PATCH edk2-platforms 09/16] Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller Wasim Khan
@ 2020-05-22  9:29   ` Ard Biesheuvel
  2020-05-24 18:32     ` Wasim Khan (OSS)
  0 siblings, 1 reply; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:29 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> We have different PCI config space region for bus 0 (Controller space) and
> bus[0x1-0xff] on NXP SoCs with PCIe LS controller.
> Add PciSegmentLib for PCIe LS controller.
> 
> For config transactions for Bus0:
>    - Config transaction address = PCIe controller address + offset
> 
> For config transactions for Bus[0x1-0xff]:
>    - PCIe IP requires target BDF to be written at bit[31:16] of PCIe
>      type0/type1 outbound window.
>    - Config transaction address = PCIe config space address + offset
> 
> Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  32 ++
>   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 612 +++++++++++++++++++++
>   2 files changed, 644 insertions(+)
>   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
>   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> 
> diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> new file mode 100755
> index 000000000000..a36e79239b33
> --- /dev/null
> +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> @@ -0,0 +1,32 @@
> +## @file
> +#  PCI Segment Library for NXP SoCs with multiple RCs
> +#
> +#  Copyright 2018-2020 NXP
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = PciSegmentLib
> +  FILE_GUID                      = c9f59261-5a60-4a4c-82f6-1f520442e100
> +  MODULE_TYPE                    = DXE_DRIVER

Can this be BASE ?

> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciSegmentLib|DXE_DRIVER
> +  CONSTRUCTOR                    = PciSegLibInit
> +
> +[Sources]
> +  PciSegmentLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/NxpQoriqLs.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  DebugLib
> +  IoLib
> +  PcdLib
> +
> +[FixedPcd]
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
> diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> new file mode 100755
> index 000000000000..ecd36971b753
> --- /dev/null
> +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> @@ -0,0 +1,612 @@
> +/** @file
> +  PCI Segment Library for NXP SoCs with multiple RCs
> +
> +  Copyright 2018-2020 NXP
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +#include <PiDxe.h>
> +#include <Base.h>
> +#include <IndustryStandard/Pci22.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Pcie.h>
> +
> +typedef enum {
> +  PciCfgWidthUint8      = 0,
> +  PciCfgWidthUint16,
> +  PciCfgWidthUint32,
> +  PciCfgWidthMax
> +} PCI_CFG_WIDTH;
> +
> +/**
> +  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)
> +
> +STATIC
> +UINT64
> +PciLsCfgTarget (
> +  IN  EFI_PHYSICAL_ADDRESS Dbi,
> +  IN  UINT64               Address,
> +  IN  UINT16               Segment,
> +  IN  UINT8                Bus,
> +  IN  UINT16               Offset
> +  )
> +{
> +  UINT32 Target;
> +
> +  Target = ((((Address >> 20) & 0xFF) << 24) |
> +           (((Address >> 15) & 0x1F) << 19) |
> +           (((Address >> 12) & 0x7) << 16));

You can drop the outer () here

> +
> +  if (Bus > 1) {
> +    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF, IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX1);
> +  } else {
> +    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF, IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX0);
> +  }
> +
> +  MmioWrite32 ((UINTN)Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0, Target);
> +
> +  if (Bus > 1) {
> +    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment + SEG_CFG_SIZE + Offset;
> +  } else {
> +    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment + Offset;
> +  }

OK, so this is the version for the IP that does not implement ECAM 
shift, right?

> +}
> +
> +/**
> +  Function to return PCIe Physical Address(PCIe view) or Controller
> +  Address(CPU view) for different RCs
> +
> +  @param  Address Address passed from bus layer.
> +  @param  Segment Segment number for Root Complex.
> +  @param  Offset  Config space register offset.
> +  @param  Bus     PCIe Bus number.
> +
> +  @return Return PCIe CPU or Controller address.
> +
> +**/
> +STATIC
> +UINT64
> +PciLsGetConfigBase (
> +  IN  UINT64      Address,
> +  IN  UINT16      Segment,
> +  IN  UINT16      Offset,
> +  IN  UINT8       Bus
> +  )
> +{
> +  UINT32 CfgAddr;
> +
> +  CfgAddr = (UINT16)Offset;
> +  if (Bus) {

Please use Bus > 0 here

> +    return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, Address, Segment, Bus, Offset);
> +  } else {
> +    return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
> +  }
> +}
> +
> +/**
> +  Function to return PCIe Physical Address(PCIe view) or Controller
> +  Address(CPU view) for different RCs
> +
> +  @param  Address Address passed from bus layer.
> +  @param  Segment Segment number for Root Complex.
> +  @param  Offset  Config space register offset.
> +
> +  @return Return PCIe CPU or Controller address.
> +
> +**/
> +STATIC
> +UINT64
> +PciSegmentLibGetConfigBase (
> +  IN  UINT64      Address,
> +  IN  UINT16      Segment,
> +  IN  UINT16      Offset
> +  )
> +{
> +  UINT8  Bus;
> +
> +  Bus = ((UINT32)Address >> 20) & 0xff;
> +  return PciLsGetConfigBase (Address, Segment, Offset, Bus);
> +}
> +
> +/**
> +  Internal worker function to read a PCI configuration register.
> +
> +  @param  Address The address that encodes the Segment, 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;
> +  UINT16    Offset;
> +  UINT16    Segment;
> +
> +  Segment = (Address >> 32);
> +  Offset = (Address & 0xfff );
> +
> +  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
> +
> +  // ignore devices > 0 on bus 0
> +  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
> +    return MAX_UINT32;
> +  }
> +
> +  // ignore device > 0 on bus 1
> +  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
> +    return MAX_UINT32;
> +  }
> +
> +  switch (Width) {
> +  case PciCfgWidthUint8:
> +    return MmioRead8 (Base);
> +  case PciCfgWidthUint16:
> +    return MmioRead16 (Base);
> +  case PciCfgWidthUint32:
> +    return MmioRead32 (Base);
> +  default:
> +    ASSERT (FALSE);
> +  }
> +
> +  return CHAR_NULL;
> +}
> +
> +/**
> +  Internal worker function to writes a PCI configuration register.
> +
> +  @param  Address The address that encodes the Segment, 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;
> +  UINT32    Offset;
> +  UINT16    Segment;
> +
> +  Segment = (Address >> 32);
> +  Offset = (Address & 0xfff );
> +
> +  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
> +
> +  // ignore devices > 0 on bus 0
> +  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
> +    return Data;
> +  }
> +
> +  // ignore device > 0 on bus 1
> +  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
> +    return MAX_UINT32;
> +  }
> +
> +  switch (Width) {
> +  case PciCfgWidthUint8:
> +    MmioWrite8 (Base , Data);
> +    break;
> +  case PciCfgWidthUint16:
> +    MmioWrite16 (Base , Data);
> +    break;
> +  case PciCfgWidthUint32:
> +    MmioWrite32 (Base , Data);
> +    break;
> +  default:
> +    ASSERT (FALSE);
> +  }
> +
> +  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.
> +
> +  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);
> +}
> +
> +/**
> +  Reads a 16-bit PCI configuration register.
> +
> +  Reads and returns 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().
> +
> +  @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.
> +
> +  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);
> +}
> +
> +/**
> +  Reads a 32-bit PCI configuration register.
> +
> +  Reads and returns the 32-bit PCI configuration register specified by Address.
> +
> +  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.
> +
> +  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);
> +}
> +
> +/**
> +  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.
> +
> +  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) <= SIZE_4KB);
> +
> +  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 + BIT0;
> +  }
> +
> +  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 + BIT0;
> +  }
> +
> +  while (Size >= sizeof (UINT32)) {
> +    //
> +    // Read as many double words as possible
> +    //
> +    WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));
> +    StartAddress += sizeof (UINT32);
> +    Size -= sizeof (UINT32);
> +    Buffer = (UINT32*)Buffer + BIT0;
> +  }
> +
> +  if (Size >= sizeof (UINT16)) {
> +    //
> +    // Read the last remaining word if exist
> +    //
> +    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + BIT0;
> +  }
> +
> +  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.
> +
> +  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) <= SIZE_4KB);
> +
> +  if (Size == 0) {
> +    return Size;
> +  }
> +
> +  ASSERT (Buffer != NULL);
> +
> +  //
> +  // 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 + BIT0;
> +  }
> +
> +  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 + BIT0;
> +  }
> +
> +  while (Size >= sizeof (UINT32)) {
> +    //
> +    // Write as many double words as possible
> +    //
> +    PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));
> +    StartAddress += sizeof (UINT32);
> +    Size -= sizeof (UINT32);
> +    Buffer = (UINT32*)Buffer + BIT0;
> +  }
> +
> +  if (Size >= sizeof (UINT16)) {
> +    //
> +    // Write the last remaining word if exist
> +    //
> +    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
> +    StartAddress += sizeof (UINT16);
> +    Size -= sizeof (UINT16);
> +    Buffer = (UINT16*)Buffer + BIT0;
> +  }
> +
> +  if (Size >= sizeof (UINT8)) {
> +    //
> +    // Write the last remaining byte if exist
> +    //
> +    PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer);
> +  }
> +
> +  return ReturnValue;
> +}
> +
> +EFI_STATUS
> +PciSegLibInit (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> 


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

* Re: [PATCH edk2-platforms 08/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows
  2020-05-21 23:02 ` [PATCH edk2-platforms 08/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows Wasim Khan
@ 2020-05-22  9:31   ` Ard Biesheuvel
  0 siblings, 0 replies; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:31 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> Dump ATU windows for PCIe Layerscape controller if PcdPciDebug
> is enabled.
> 
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 42 ++++++++++++++++++++++
>   1 file changed, 42 insertions(+)
> 
> diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> index 1de20c621dc0..3ad526218bcf 100644
> --- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> @@ -297,6 +297,44 @@ PcieOutboundSet (
>   }
>   
>   /**
> +  Dump PCIe Layerscape ATU
> +
> +  @param Pcie     Address of PCIe host controller.
> +**/
> +VOID LsDumpAtu (
> +  IN EFI_PHYSICAL_ADDRESS Pcie
> +  )
> +{
> +  UINT32 Cnt;
> +  for (Cnt = 0; Cnt <= IATU_REGION_INDEX7; Cnt++) {
> +    MmioWrite32 ((UINTN)Pcie + IATU_VIEWPORT_OFF,
> +                  (UINT32)(IATU_VIEWPORT_OUTBOUND | Cnt));
> +
> +    DEBUG ((DEBUG_INFO, "iATU%d:\n",Cnt));
> +    DEBUG ((DEBUG_INFO, "\tLOWER PHYS 0x%08x\n",
> +            MmioRead32 ((UINTN)Pcie + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0)));
> +
> +    DEBUG ((DEBUG_INFO, "\tUPPER PHYS 0x%08x\n",
> +            MmioRead32 ((UINTN)Pcie + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0)));
> +
> +    DEBUG ((DEBUG_INFO, "\tLOWER BUS 0x%08x\n",
> +            MmioRead32 ((UINTN)Pcie + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0)));
> +
> +    DEBUG ((DEBUG_INFO, "\tUPPER BUS 0x%08x\n",
> +            MmioRead32 ((UINTN)Pcie + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0)));
> +
> +    DEBUG ((DEBUG_INFO, "\tLIMIT     0x%08x\n",
> +            MmioRead32 ((UINTN)Pcie + IATU_LIMIT_ADDR_OFF_OUTBOUND_0)));
> +
> +    DEBUG ((DEBUG_INFO, "\tCR1       0x%08x\n",
> +            MmioRead32 ((UINTN)Pcie + IATU_REGION_CTRL_1_OFF_OUTBOUND_0)));
> +
> +    DEBUG ((DEBUG_INFO, "\tCR2       0x%08x\n",
> +            MmioRead32 ((UINTN)Pcie + IATU_REGION_CTRL_2_OFF_OUTBOUND_0)));
> +  }
> +}
> +
> +/**
>     Function to set-up iATU windows for Layerscape PCIe controller
>   
>     @param Pcie      Address of PCIe host controller
> @@ -410,6 +448,10 @@ PcieLsSetupAtu (
>       SEG_IO_BUS,
>       SEG_IO_SIZE
>       );
> +
> +  if (FixedPcdGetBool (PcdPciDebug) == TRUE) {
> +    LsDumpAtu (Pcie);
> +  }
>   }
>   
>   /*

We already have DEBUG vs RELEASE builds, and various debug levels. 
Please don't add your own DEBUG PCDs on top of that. Instead, if you 
need code to only be executed in DEBUG builds (like the MmioWrite() 
above), use DEBUG_CODE_BEGIN/END


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

* Re: [PATCH edk2-platforms 07/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows
  2020-05-21 23:02 ` [PATCH edk2-platforms 07/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows Wasim Khan
@ 2020-05-22  9:33   ` Ard Biesheuvel
  0 siblings, 0 replies; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:33 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> Dump ATU windows for PCIe LsGen4 controller if PcdPciDebug
> is enabled.
> 
> Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  1 +
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 34 ++++++++++++++++++++++
>   2 files changed, 35 insertions(+)
> 
> diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> index b777acdc103f..df1590172e15 100644
> --- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> @@ -38,6 +38,7 @@ [FixedPcd]
>     gNxpQoriqLsTokenSpaceGuid.PcdNumPciController
>     gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase
>     gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciDebug
>   
>   [Pcd]
>     gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
> diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> index bacdc29d60d6..1de20c621dc0 100644
> --- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> @@ -413,6 +413,36 @@ PcieLsSetupAtu (
>   }
>   
>   /**
> +  Dump PCIe LsGen4 ATU
> +
> +  @param Pcie     Address of PCIe host controller.
> +**/
> +VOID LsGen4DumpAtu (
> +  IN EFI_PHYSICAL_ADDRESS Pcie
> +  )
> +{
> +  UINT32 Cnt;
> +  for (Cnt = 0; Cnt <= IATU_REGION_INDEX6; Cnt++) {
> +    DEBUG ((DEBUG_INFO,"APIO WINDOW%d:\n", Cnt));
> +    DEBUG ((DEBUG_INFO,"\tLOWER PHYS 0x%08x\n",
> +            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_AXI_WIN (Cnt))));
> +    DEBUG ((DEBUG_INFO,"\tUPPER PHYS 0x%08x\n",
> +            PciLsGen4Read32 ((UINTN)Pcie, PAB_EXT_AXI_AMAP_AXI_WIN (Cnt))));
> +    DEBUG ((DEBUG_INFO,"\tLOWER BUS  0x%08x\n",
> +            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_PEX_WIN_L (Cnt))));
> +    DEBUG ((DEBUG_INFO,"\tUPPER BUS  0x%08x\n",
> +            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_PEX_WIN_H (Cnt))));
> +    DEBUG ((DEBUG_INFO,"\tSIZE      0x%08x\n",
> +            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_CTRL (Cnt)) &
> +            (AXI_AMAP_CTRL_SIZE_MASK << AXI_AMAP_CTRL_SIZE_SHIFT)));
> +    DEBUG ((DEBUG_INFO,"\tEXT_SIZE        0x%08x\n",
> +            PciLsGen4Read32 ((UINTN)Pcie, PAB_EXT_AXI_AMAP_SIZE (Cnt))));
> +    DEBUG ((DEBUG_INFO,"\tCTRL:        0x%08x\n",
> +            PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_AMAP_CTRL (Cnt))));
> +  }
> +}
> +
> +/**
>     Function to set-up ATU windows for PCIe LayerscapeGen4 controller
>   
>     @param Pcie      Address of PCIe host controller
> @@ -484,6 +514,10 @@ PcieLsGen4SetupAtu (
>                               Mem64Base,
>                               Mem64Base,
>                               SIZE_4GB);
> +
> +  if (FixedPcdGetBool (PcdPciDebug) == TRUE) {
> +    LsGen4DumpAtu (Pcie);
> +  }
>   }
>   
>   /**
> 

Same remark: don't add PCDs for DEBUG, just use levels.



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

* Re: [PATCH edk2-platforms 10/16] Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS Controller
  2020-05-21 23:02 ` [PATCH edk2-platforms 10/16] Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS Controller Wasim Khan
@ 2020-05-22  9:36   ` Ard Biesheuvel
  2020-05-24 18:32     ` Wasim Khan (OSS)
  0 siblings, 1 reply; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:36 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> PCIe Layerscape controller can be enabled for ECAM style
> configuration access using CFG SHIFT Feature.
> 
> Check for PcdPciCfgShiftEnable to decide the configuration access
> scheme to be used with PCIe LS controller.
> 
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf |  3 +++
>   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c   | 20 ++++++++++++++++----
>   2 files changed, 19 insertions(+), 4 deletions(-)
> 
> diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> index a36e79239b33..936213dc8a9d 100755
> --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> @@ -30,3 +30,6 @@ [LibraryClasses]
>   
>   [FixedPcd]
>     gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
> +
> +[Pcd]
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
> diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> index ecd36971b753..552a425c6832 100755
> --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> @@ -34,6 +34,8 @@ typedef enum {
>   #define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \
>     ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0)
>   
> +static BOOLEAN CfgShiftEnable;
> +

This is a compile time constant, right? Please try to avoid using 
runtime read/write variables in that case, since it defeats the 
compiler's ability to remove code that is never executed.


>   STATIC
>   UINT64
>   PciLsCfgTarget (
> @@ -88,11 +90,20 @@ PciLsGetConfigBase (
>   {
>     UINT32 CfgAddr;
>   
> -  CfgAddr = (UINT16)Offset;
> -  if (Bus) {
> -    return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, Address, Segment, Bus, Offset);
> +  if (CfgShiftEnable) {
> +    CfgAddr = (UINT32)Address;
> +    if (Bus) {
> +      return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment + CfgAddr;
> +    } else {
> +      return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
> +    }
>     } else {
> -    return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
> +    CfgAddr = (UINT16)Offset;
> +    if (Bus) {
> +      return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, Address, Segment, Bus, Offset);
> +    } else {
> +      return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
> +    }
>     }
>   }
>   
> @@ -608,5 +619,6 @@ PciSegLibInit (
>     IN EFI_SYSTEM_TABLE  *SystemTable
>     )
>   {
> +  CfgShiftEnable = CFG_SHIFT_ENABLE;
>     return EFI_SUCCESS;
>   }
> 


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

* Re: [PATCH edk2-platforms 11/16] Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller
  2020-05-21 23:02 ` [PATCH edk2-platforms 11/16] Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller Wasim Khan
@ 2020-05-22  9:38   ` Ard Biesheuvel
  2020-05-24 18:32     ` Wasim Khan (OSS)
  0 siblings, 1 reply; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:38 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> PCIe Layerscape Gen4 controller is not ECAM complaint and have

compliant

> different PCI config space region for bus 0 (Controller space) and
> bus[0x1-0xff] on NXP SoCs.
> 
> For config transactions for Bus0:
>    - Config transaction address = PCIe controller address + offset
> 
> For config transactions for Bus[0x1-0xff]:
>    - PCIe IP requires target BDF to be written at bit[31:16] of PCIe
>      outbound configuration window.
> 
> PCIe LsGen4 controller uses paging mechanism to access registers.
> To access PCIe CCSR registers which are above 3KB offset, page number
> must be set in Bridge Control Register.
> 
> Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  1 +
>   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 60 +++++++++++++++++++++-
>   2 files changed, 60 insertions(+), 1 deletion(-)
> 
> diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> index 936213dc8a9d..d6d7ea6e3b6b 100755
> --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> @@ -33,3 +33,4 @@ [FixedPcd]
>   
>   [Pcd]
>     gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl
> diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> index 552a425c6832..02a1525ef308 100755
> --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> @@ -35,6 +35,58 @@ typedef enum {
>     ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0)
>   
>   static BOOLEAN CfgShiftEnable;
> +static BOOLEAN PciLsGen4Ctrl;
> +

Another compile time constant?

> +STATIC
> +VOID
> +PcieCfgSetTarget (
> +  IN EFI_PHYSICAL_ADDRESS Dbi,
> +  IN UINT32 Target)
> +{
> +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_L(0), Target);
> +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_H(0), 0);
> +}
> +
> +/**
> +  Function to return PCIe Physical Address(PCIe view) or Controller
> +  Address(CPU view) for NXP Layerscape Gen4 SoC
> +
> +  @param  Address Address passed from bus layer.
> +  @param  Segment Segment number for Root Complex.
> +  @param  Offset  Config space register offset.
> +  @param  Bus     PCIe Bus number.
> +
> +  @return Return PCIe CPU or Controller address.
> +
> +**/
> +STATIC
> +UINT64
> +PciLsGen4GetConfigBase (
> +  IN  UINT64      Address,
> +  IN  UINT16      Segment,
> +  IN  UINT16      Offset,
> +  IN  UINT8       Bus
> +  )
> +{
> +  UINT32 Target;
> +
> +  if (Bus) {

Bus > 0

> +    Target = ((((Address >> 20) & 0xFF) << 24) |
> +             (((Address >> 15) & 0x1F) << 19) |
> +             (((Address >> 12) & 0x7) << 16));

Drop the outer ()

> +
> +    PcieCfgSetTarget ((PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF* Segment), Target);
> +    return PCI_SEG0_MMIO_MEMBASE + Offset + PCI_BASE_DIFF * Segment;
> +  } else {
> +      if (Offset < INDIRECT_ADDR_BNDRY) {
> +        PciLsGen4SetPg (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, 0);
> +        return (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + Offset);
> +      }
> +      PciLsGen4SetPg (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment, OFFSET_TO_PAGE_IDX (Offset));
> +      Offset = OFFSET_TO_PAGE_ADDR (Offset);
> +      return (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + Offset);
> +  }
> +}
>   
>   STATIC
>   UINT64
> @@ -129,7 +181,12 @@ PciSegmentLibGetConfigBase (
>     UINT8  Bus;
>   
>     Bus = ((UINT32)Address >> 20) & 0xff;
> -  return PciLsGetConfigBase (Address, Segment, Offset, Bus);
> +
> +  if (PciLsGen4Ctrl) {
> +    return PciLsGen4GetConfigBase (Address, Segment, Offset, Bus);
> +  } else {
> +    return PciLsGetConfigBase (Address, Segment, Offset, Bus);
> +  }
>   }
>   
>   /**
> @@ -620,5 +677,6 @@ PciSegLibInit (
>     )
>   {
>     CfgShiftEnable = CFG_SHIFT_ENABLE;
> +  PciLsGen4Ctrl = PCI_LS_GEN4_CTRL;
>     return EFI_SUCCESS;
>   }
> 


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

* Re: [PATCH edk2-platforms 12/16] Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264
  2020-05-21 23:02 ` [PATCH edk2-platforms 12/16] Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264 Wasim Khan
@ 2020-05-22  9:39   ` Ard Biesheuvel
  2020-05-24 18:32     ` Wasim Khan (OSS)
  0 siblings, 1 reply; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:39 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> With PCIe LsGen4 controller, clearing the Bus Master Enable bit in
> Command register blocks all outbound transactions to be sent out
> in RC mode.
> 
> According to PCI Express base specification, the Command register’s
> Bus Master Enable bit of a PCI Express RC controller can only
> control the forwarding of memory requests received at its root port
> in the upstream direction. In other words, clearing the Bus Master
> Enable bit must not block all outbound transactions to be sent out
> toward RC’s downstream devices. Due to this erratum, when the
> Command register’s Bus Master Enable bit is cleared, all the outbound
> transactions from the device’s internal bus masters, including but
> not limited to configuration read and write transactions, are
> terminated with the slave error (SLVERR) response status on the PCI
> Express RC controller’s internal AXI bus interface.
> 
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c | 17 +++++++++++++++++
>   1 file changed, 17 insertions(+)
> 
> diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> index 02a1525ef308..c3bc14820ea5 100755
> --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> @@ -39,6 +39,21 @@ static BOOLEAN PciLsGen4Ctrl;
>   
>   STATIC
>   VOID
> +PciLsGen4SetBusMaster (
> +  IN EFI_PHYSICAL_ADDRESS Dbi
> +  )
> +{
> +  UINT32 Val;
> +
> +  /* Make sure the Master Enable bit not cleared */

Please use // style comments

> +  Val = PciLsGen4Read32 ((UINTN)Dbi, PCI_COMMAND_OFFSET);
> +  if (!(Val & EFI_PCI_COMMAND_BUS_MASTER)) {
> +    PciLsGen4Write32 ((UINTN)Dbi, PCI_COMMAND_OFFSET, Val | EFI_PCI_COMMAND_BUS_MASTER);
> +  }
> +}
> +
> +STATIC
> +VOID
>   PcieCfgSetTarget (
>     IN EFI_PHYSICAL_ADDRESS Dbi,
>     IN UINT32 Target)
> @@ -71,6 +86,8 @@ PciLsGen4GetConfigBase (
>     UINT32 Target;
>   
>     if (Bus) {
> +    PciLsGen4SetBusMaster (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF* Segment);
> +

Can't we just set this once and never touch it? Or is that tricky?


>       Target = ((((Address >> 20) & 0xFF) << 24) |
>                (((Address >> 15) & 0x1F) << 19) |
>                (((Address >> 12) & 0x7) << 16));
> 


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

* Re: [PATCH edk2-platforms 13/16] Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver
  2020-05-21 23:02 ` [PATCH edk2-platforms 13/16] Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver Wasim Khan
@ 2020-05-22  9:42   ` Ard Biesheuvel
  0 siblings, 0 replies; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:42 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> NXP SoC has multiple PCIe RCs and there is no fix translation
> offset between I/O port accesses and MMIO accesses.
> Add PciCpuIo2Dxe driver to implement EFI_CPU_IO2_PROTOCOL
> to add the translation for different RCs for IO access.
> 
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>

Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com>

> ---
>   Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf |  40 ++
>   Silicon/NXP/Include/Pcie.h                        |  19 +
>   Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c   | 628 ++++++++++++++++++++++
>   3 files changed, 687 insertions(+)
>   create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
>   create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c
> 
> diff --git a/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
> new file mode 100755
> index 000000000000..0ee470e41d5e
> --- /dev/null
> +++ b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
> @@ -0,0 +1,40 @@
> +## @file
> +#  Produces the CPU I/O 2 Protocol by using the services of the I/O Library.
> +#
> +# Copyright 2018, 2020 NXP
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = PciCpuIo2Dxe
> +  FILE_GUID                      = 7bff18d7-9aae-434b-9c06-f10a7e157eac
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = PciCpuIo2Initialize
> +
> +[Sources]
> +  PciCpuIo2Dxe.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  Silicon/NXP/NxpQoriqLs.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  DebugLib
> +  IoLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +
> +[Pcd]
> +  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
> +  gNxpQoriqLsTokenSpaceGuid.PcdNumPciController
> +
> +[Protocols]
> +  gEfiCpuIo2ProtocolGuid                         ## PRODUCES
> +
> +[Depex]
> +  TRUE
> diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
> index bc35570f79bc..b561d0e3ba11 100755
> --- a/Silicon/NXP/Include/Pcie.h
> +++ b/Silicon/NXP/Include/Pcie.h
> @@ -39,6 +39,25 @@
>   #define PCI_SEG0_PHY_MEM_BASE     PCI_SEG0_MMIO_MEMBASE + SEG_MEM_BASE
>   #define PCI_SEG0_PHY_MEM64_BASE   PCI_SEG0_MMIO_MEMBASE + SEG_MEM64_BASE
>   #define PCI_SEG0_PHY_IO_BASE      PCI_SEG0_MMIO_MEMBASE + SEG_IO_BASE
> +#define PCI_SEG0_PORTIO_MIN       0x0
> +#define PCI_SEG0_PORTIO_MAX       0xffff
> +#define PCI_SEG0_PORTIO_OFFSET    0x0
> +#define PCI_SEG1_PORTIO_MIN       0x0
> +#define PCI_SEG1_PORTIO_MAX       0xffff
> +#define PCI_SEG1_PORTIO_OFFSET    0x10000
> +#define PCI_SEG2_PORTIO_MIN       0x0
> +#define PCI_SEG2_PORTIO_MAX       0xffff
> +#define PCI_SEG2_PORTIO_OFFSET    0x20000
> +#define PCI_SEG3_PORTIO_MIN       0x0
> +#define PCI_SEG3_PORTIO_MAX       0xffff
> +#define PCI_SEG3_PORTIO_OFFSET    0x30000
> +#define PCI_SEG4_PORTIO_MIN       0x0
> +#define PCI_SEG4_PORTIO_MAX       0xffff
> +#define PCI_SEG4_PORTIO_OFFSET    0x40000
> +#define PCI_SEG5_PORTIO_MIN       0x0
> +#define PCI_SEG5_PORTIO_MAX       0xffff
> +#define PCI_SEG5_PORTIO_OFFSET    0x50000
> +#define PCI_SEG_PORTIO_LIMIT      PCI_SEG5_PORTIO_MAX + PCI_SEG5_PORTIO_OFFSET
>   
>   // PCIe Controller configuration
>   #define NUM_PCIE_CONTROLLER       FixedPcdGet32 (PcdNumPciController)
> diff --git a/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c
> new file mode 100755
> index 000000000000..17db44a8b510
> --- /dev/null
> +++ b/Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c
> @@ -0,0 +1,628 @@
> +/** @file
> +  Produces the CPU I/O 2 Protocol.
> +
> +  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
> +  Copyright 2018-2020 NXP
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Pcie.h>
> +#include <Protocol/CpuIo2.h>
> +
> +#define MAX_IO_PORT_ADDRESS PCI_SEG_PORTIO_LIMIT
> +
> +//
> +// Handle for the CPU I/O 2 Protocol
> +//
> +STATIC EFI_HANDLE  mHandle = NULL;
> +
> +//
> +// Lookup table for increment values based on transfer widths
> +//
> +STATIC CONST UINT8 mInStride[] = {
> +  1, // EfiCpuIoWidthUint8
> +  2, // EfiCpuIoWidthUint16
> +  4, // EfiCpuIoWidthUint32
> +  8, // EfiCpuIoWidthUint64
> +  0, // EfiCpuIoWidthFifoUint8
> +  0, // EfiCpuIoWidthFifoUint16
> +  0, // EfiCpuIoWidthFifoUint32
> +  0, // EfiCpuIoWidthFifoUint64
> +  1, // EfiCpuIoWidthFillUint8
> +  2, // EfiCpuIoWidthFillUint16
> +  4, // EfiCpuIoWidthFillUint32
> +  8  // EfiCpuIoWidthFillUint64
> +};
> +
> +//
> +// Lookup table for increment values based on transfer widths
> +//
> +STATIC CONST UINT8 mOutStride[] = {
> +  1, // EfiCpuIoWidthUint8
> +  2, // EfiCpuIoWidthUint16
> +  4, // EfiCpuIoWidthUint32
> +  8, // EfiCpuIoWidthUint64
> +  1, // EfiCpuIoWidthFifoUint8
> +  2, // EfiCpuIoWidthFifoUint16
> +  4, // EfiCpuIoWidthFifoUint32
> +  8, // EfiCpuIoWidthFifoUint64
> +  0, // EfiCpuIoWidthFillUint8
> +  0, // EfiCpuIoWidthFillUint16
> +  0, // EfiCpuIoWidthFillUint32
> +  0  // EfiCpuIoWidthFillUint64
> +};
> +
> +/**
> +  Check parameters to a CPU I/O 2 Protocol service request.
> +
> +  The I/O operations are carried out exactly as requested. The caller is responsible
> +  for satisfying any alignment and I/O width restrictions that a PI System on a
> +  platform might require. For example on some platforms, width requests of
> +  EfiCpuIoWidthUint64 do not work.
> +
> +  @param[in] MmioOperation  TRUE for an MMIO operation, FALSE for I/O Port operation.
> +  @param[in] Width          Signifies the width of the I/O or Memory operation.
> +  @param[in] Address        The base address of the I/O operation.
> +  @param[in] Count          The number of I/O operations to perform. The number of
> +                            bytes moved is Width size * Count, starting at Address.
> +  @param[in] Buffer         For read operations, the destination buffer to store the results.
> +                            For write operations, the source buffer from which to write data.
> +
> +  @retval EFI_SUCCESS            The parameters for this request pass the checks.
> +  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
> +  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
> +  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
> +  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
> +                                 and Count is not valid for this PI system.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +CpuIoCheckParameter (
> +  IN BOOLEAN                    MmioOperation,
> +  IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
> +  IN UINT64                     Address,
> +  IN UINTN                      Count,
> +  IN VOID                       *Buffer
> +  )
> +{
> +  UINT64  MaxCount;
> +  UINT64  Limit;
> +
> +  //
> +  // Check to see if Buffer is NULL
> +  //
> +  if (Buffer == NULL) {
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Check to see if Width is in the valid range
> +  //
> +  if ((UINT32)Width >= EfiCpuIoWidthMaximum) {
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // For FIFO type, the target address won't increase during the access,
> +  // so treat Count as 1
> +  //
> +  if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
> +    Count = 1;
> +  }
> +
> +  //
> +  // Check to see if Width is in the valid range for I/O Port operations
> +  //
> +  Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
> +  if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {
> +    ASSERT (FALSE);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Check to see if Address is aligned
> +  //
> +  if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
> +    ASSERT (FALSE);
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Check to see if any address associated with this transfer exceeds the maximum
> +  // allowed address.  The maximum address implied by the parameters passed in is
> +  // Address + Size * Count.  If the following condition is met, then the transfer
> +  // is not supported.
> +  //
> +  //    Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
> +  //
> +  // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
> +  // can also be the maximum integer value supported by the CPU, this range
> +  // check must be adjusted to avoid all oveflow conditions.
> +  //
> +  Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
> +  if (Count == 0) {
> +    if (Address > Limit) {
> +      ASSERT (FALSE);
> +      return EFI_UNSUPPORTED;
> +    }
> +  } else {
> +    MaxCount = RShiftU64 (Limit, Width);
> +    if (MaxCount < (Count - 1)) {
> +      ASSERT (FALSE);
> +      return EFI_UNSUPPORTED;
> +    }
> +    if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
> +      ASSERT (FALSE);
> +      return EFI_UNSUPPORTED;
> +    }
> +  }
> +
> +  //
> +  // Check to see if Buffer is aligned
> +  //
> +  if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width])  - 1))) != 0) {
> +    ASSERT (FALSE);
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Reads memory-mapped registers.
> +
> +  The I/O operations are carried out exactly as requested. The caller is responsible
> +  for satisfying any alignment and I/O width restrictions that a PI System on a
> +  platform might require. For example on some platforms, width requests of
> +  EfiCpuIoWidthUint64 do not work.
> +
> +  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
> +  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
> +  each of the Count operations that is performed.
> +
> +  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
> +  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
> +  incremented for each of the Count operations that is performed. The read or
> +  write operation is performed Count times on the same Address.
> +
> +  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
> +  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
> +  incremented for each of the Count operations that is performed. The read or
> +  write operation is performed Count times from the first element of Buffer.
> +
> +  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
> +  @param[in]  Width    Signifies the width of the I/O or Memory operation.
> +  @param[in]  Address  The base address of the I/O operation.
> +  @param[in]  Count    The number of I/O operations to perform. The number of
> +                       bytes moved is Width size * Count, starting at Address.
> +  @param[out] Buffer   For read operations, the destination buffer to store the results.
> +                       For write operations, the source buffer from which to write data.
> +
> +  @retval EFI_SUCCESS            The data was read from or written to the PI system.
> +  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
> +  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
> +  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
> +  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
> +                                 and Count is not valid for this PI system.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +CpuMemoryServiceRead (
> +  IN  EFI_CPU_IO2_PROTOCOL       *This,
> +  IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
> +  IN  UINT64                     Address,
> +  IN  UINTN                      Count,
> +  OUT VOID                       *Buffer
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  UINT8                      InStride;
> +  UINT8                      OutStride;
> +  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
> +  UINT8                      *Uint8Buffer;
> +
> +  Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Select loop based on the width of the transfer
> +  //
> +  InStride = mInStride[Width];
> +  OutStride = mOutStride[Width];
> +  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
> +  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
> +    if (OperationWidth == EfiCpuIoWidthUint8) {
> +      *Uint8Buffer = MmioRead8 ((UINTN)Address);
> +    } else if (OperationWidth == EfiCpuIoWidthUint16) {
> +      *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
> +    } else if (OperationWidth == EfiCpuIoWidthUint32) {
> +      *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
> +    } else if (OperationWidth == EfiCpuIoWidthUint64) {
> +      *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Writes memory-mapped registers.
> +
> +  The I/O operations are carried out exactly as requested. The caller is responsible
> +  for satisfying any alignment and I/O width restrictions that a PI System on a
> +  platform might require. For example on some platforms, width requests of
> +  EfiCpuIoWidthUint64 do not work.
> +
> +  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
> +  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
> +  each of the Count operations that is performed.
> +
> +  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
> +  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
> +  incremented for each of the Count operations that is performed. The read or
> +  write operation is performed Count times on the same Address.
> +
> +  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
> +  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
> +  incremented for each of the Count operations that is performed. The read or
> +  write operation is performed Count times from the first element of Buffer.
> +
> +  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
> +  @param[in]  Width    Signifies the width of the I/O or Memory operation.
> +  @param[in]  Address  The base address of the I/O operation.
> +  @param[in]  Count    The number of I/O operations to perform. The number of
> +                       bytes moved is Width size * Count, starting at Address.
> +  @param[in]  Buffer   For read operations, the destination buffer to store the results.
> +                       For write operations, the source buffer from which to write data.
> +
> +  @retval EFI_SUCCESS            The data was read from or written to the PI system.
> +  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
> +  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
> +  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
> +  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
> +                                 and Count is not valid for this PI system.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +CpuMemoryServiceWrite (
> +  IN EFI_CPU_IO2_PROTOCOL       *This,
> +  IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
> +  IN UINT64                     Address,
> +  IN UINTN                      Count,
> +  IN VOID                       *Buffer
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  UINT8                      InStride;
> +  UINT8                      OutStride;
> +  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
> +  UINT8                      *Uint8Buffer;
> +
> +  Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Select loop based on the width of the transfer
> +  //
> +  InStride = mInStride[Width];
> +  OutStride = mOutStride[Width];
> +  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
> +  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
> +    if (OperationWidth == EfiCpuIoWidthUint8) {
> +      MmioWrite8 ((UINTN)Address, *Uint8Buffer);
> +    } else if (OperationWidth == EfiCpuIoWidthUint16) {
> +      MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
> +    } else if (OperationWidth == EfiCpuIoWidthUint32) {
> +      MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
> +    } else if (OperationWidth == EfiCpuIoWidthUint64) {
> +      MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +TranslateIoAddress (
> +  IN  OUT UINT64                 *Address
> +  )
> +{
> +  UINT64 Start;
> +  UINT64 End;
> +  UINT64 Shift;
> +  UINT64 SegIoHostAddressBase;
> +
> +  SegIoHostAddressBase = PCI_SEG0_PHY_IO_BASE;
> +  Start = PCI_SEG0_PORTIO_MIN + PCI_SEG0_PORTIO_OFFSET;
> +  End   = PCI_SEG0_PORTIO_MAX + PCI_SEG0_PORTIO_OFFSET;
> +  Shift = SegIoHostAddressBase - PCI_SEG0_PORTIO_OFFSET;
> +
> +  if (*Address >= Start && *Address <= End) {
> +    *Address += Shift;
> +    return EFI_SUCCESS;
> +  }
> +
> +  Start = PCI_SEG1_PORTIO_MIN + PCI_SEG1_PORTIO_OFFSET;
> +  End   = PCI_SEG1_PORTIO_MAX + PCI_SEG1_PORTIO_OFFSET;
> +  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 1)) - PCI_SEG1_PORTIO_OFFSET;
> +
> +  if (*Address >= Start && *Address <= End) {
> +    *Address += Shift;
> +    return EFI_SUCCESS;
> +  }
> +
> +  Start = PCI_SEG2_PORTIO_MIN + PCI_SEG2_PORTIO_OFFSET;
> +  End   = PCI_SEG2_PORTIO_MAX + PCI_SEG2_PORTIO_OFFSET;
> +  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 2)) - PCI_SEG2_PORTIO_OFFSET;
> +
> +  if (*Address >= Start && *Address <= End) {
> +    *Address += Shift;
> +    return EFI_SUCCESS;
> +  }
> +
> +  Start = PCI_SEG3_PORTIO_MIN + PCI_SEG3_PORTIO_OFFSET;
> +  End   = PCI_SEG3_PORTIO_MAX + PCI_SEG3_PORTIO_OFFSET;
> +  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 3)) - PCI_SEG3_PORTIO_OFFSET;
> +
> +  if (*Address >= Start && *Address <= End) {
> +    *Address += Shift;
> +    return EFI_SUCCESS;
> +  }
> +
> +  Start = PCI_SEG4_PORTIO_MIN + PCI_SEG4_PORTIO_OFFSET;
> +  End   = PCI_SEG4_PORTIO_MAX + PCI_SEG4_PORTIO_OFFSET;
> +  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 4)) - PCI_SEG4_PORTIO_OFFSET;
> +
> +  if (*Address >= Start && *Address <= End) {
> +    *Address += Shift;
> +    return EFI_SUCCESS;
> +  }
> +
> +  Start = PCI_SEG5_PORTIO_MIN + PCI_SEG5_PORTIO_OFFSET;
> +  End   = PCI_SEG5_PORTIO_MAX + PCI_SEG5_PORTIO_OFFSET;
> +  Shift = (SegIoHostAddressBase + (PCI_BASE_DIFF * 5)) - PCI_SEG5_PORTIO_OFFSET;
> +
> +  if (*Address >= Start && *Address <= End) {
> +    *Address += Shift;
> +    return EFI_SUCCESS;
> +  }
> +  ASSERT (FALSE);
> +  return EFI_INVALID_PARAMETER;
> +}
> +
> +/**
> +  Reads I/O registers.
> +
> +  The I/O operations are carried out exactly as requested. The caller is responsible
> +  for satisfying any alignment and I/O width restrictions that a PI System on a
> +  platform might require. For example on some platforms, width requests of
> +  EfiCpuIoWidthUint64 do not work.
> +
> +  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
> +  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
> +  each of the Count operations that is performed.
> +
> +  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
> +  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
> +  incremented for each of the Count operations that is performed. The read or
> +  write operation is performed Count times on the same Address.
> +
> +  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
> +  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
> +  incremented for each of the Count operations that is performed. The read or
> +  write operation is performed Count times from the first element of Buffer.
> +
> +  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
> +  @param[in]  Width    Signifies the width of the I/O or Memory operation.
> +  @param[in]  Address  The base address of the I/O operation.
> +  @param[in]  Count    The number of I/O operations to perform. The number of
> +                       bytes moved is Width size * Count, starting at Address.
> +  @param[out] Buffer   For read operations, the destination buffer to store the results.
> +                       For write operations, the source buffer from which to write data.
> +
> +  @retval EFI_SUCCESS            The data was read from or written to the PI system.
> +  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
> +  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
> +  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
> +  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
> +                                 and Count is not valid for this PI system.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +CpuIoServiceRead (
> +  IN  EFI_CPU_IO2_PROTOCOL       *This,
> +  IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
> +  IN  UINT64                     Address,
> +  IN  UINTN                      Count,
> +  OUT VOID                       *Buffer
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  UINT8                      InStride;
> +  UINT8                      OutStride;
> +  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
> +  UINT8                      *Uint8Buffer;
> +
> +  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = TranslateIoAddress (&Address);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Select loop based on the width of the transfer
> +  //
> +  InStride = mInStride[Width];
> +  OutStride = mOutStride[Width];
> +  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
> +
> +  for (Uint8Buffer = Buffer; Count > 0;
> +       Address += InStride, Uint8Buffer += OutStride, Count--) {
> +    if (OperationWidth == EfiCpuIoWidthUint8) {
> +      *Uint8Buffer = MmioRead8 ((UINTN)Address);
> +    } else if (OperationWidth == EfiCpuIoWidthUint16) {
> +      *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
> +    } else if (OperationWidth == EfiCpuIoWidthUint32) {
> +      *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Write I/O registers.
> +
> +  The I/O operations are carried out exactly as requested. The caller is responsible
> +  for satisfying any alignment and I/O width restrictions that a PI System on a
> +  platform might require. For example on some platforms, width requests of
> +  EfiCpuIoWidthUint64 do not work.
> +
> +  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
> +  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
> +  each of the Count operations that is performed.
> +
> +  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
> +  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
> +  incremented for each of the Count operations that is performed. The read or
> +  write operation is performed Count times on the same Address.
> +
> +  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
> +  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
> +  incremented for each of the Count operations that is performed. The read or
> +  write operation is performed Count times from the first element of Buffer.
> +
> +  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
> +  @param[in]  Width    Signifies the width of the I/O or Memory operation.
> +  @param[in]  Address  The base address of the I/O operation.
> +  @param[in]  Count    The number of I/O operations to perform. The number of
> +                       bytes moved is Width size * Count, starting at Address.
> +  @param[in]  Buffer   For read operations, the destination buffer to store the results.
> +                       For write operations, the source buffer from which to write data.
> +
> +  @retval EFI_SUCCESS            The data was read from or written to the PI system.
> +  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
> +  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
> +  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
> +  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
> +                                 and Count is not valid for this PI system.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +CpuIoServiceWrite (
> +  IN EFI_CPU_IO2_PROTOCOL       *This,
> +  IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
> +  IN UINT64                     Address,
> +  IN UINTN                      Count,
> +  IN VOID                       *Buffer
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  UINT8                      InStride;
> +  UINT8                      OutStride;
> +  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
> +  UINT8                      *Uint8Buffer;
> +
> +  //
> +  // Make sure the parameters are valid
> +  //
> +  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = TranslateIoAddress (&Address);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Select loop based on the width of the transfer
> +  //
> +  InStride = mInStride[Width];
> +  OutStride = mOutStride[Width];
> +  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
> +
> +  for (Uint8Buffer = (UINT8 *)Buffer; Count > 0;
> +       Address += InStride, Uint8Buffer += OutStride, Count--) {
> +    if (OperationWidth == EfiCpuIoWidthUint8) {
> +      MmioWrite8 ((UINTN)Address, *Uint8Buffer);
> +    } else if (OperationWidth == EfiCpuIoWidthUint16) {
> +      MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
> +    } else if (OperationWidth == EfiCpuIoWidthUint32) {
> +      MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +//
> +// CPU I/O 2 Protocol instance
> +//
> +STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 = {
> +  {
> +    CpuMemoryServiceRead,
> +    CpuMemoryServiceWrite
> +  },
> +  {
> +    CpuIoServiceRead,
> +    CpuIoServiceWrite
> +  }
> +};
> +
> +
> +/**
> +  The user Entry Point for module CpuIo2Dxe. The user code starts with this function.
> +
> +  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
> +  @param[in] SystemTable    A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS       The entry point is executed successfully.
> +  @retval other             Some error occurs when executing this entry point.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +PciCpuIo2Initialize (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &mHandle,
> +                  &gEfiCpuIo2ProtocolGuid, &mCpuIo2,
> +                  NULL
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> 


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

* Re: [PATCH edk2-platforms 14/16] Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg
  2020-05-21 23:02 ` [PATCH edk2-platforms 14/16] Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg Wasim Khan
@ 2020-05-22  9:42   ` Ard Biesheuvel
  0 siblings, 0 replies; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:42 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> Enable NetworkPkg for LS1043aRdb Platform.
> 
> Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

Drop the signoff please. If Meenakshi wrote the patch, make them the 
author not the submitter.

> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> ---
>   Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc | 11 +++++++++++
>   Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf |  5 +++++
>   2 files changed, 16 insertions(+)
> 
> diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
> index d45fd67c03b5..8f7f9d171587 100644
> --- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
> +++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
> @@ -22,6 +22,13 @@ [Defines]
>     OUTPUT_DIRECTORY               = Build/LS1043aRdbPkg
>     FLASH_DEFINITION               = Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
>   
> +  #
> +  # Network definition
> +  #
> +  DEFINE NETWORK_TLS_ENABLE             = FALSE
> +  DEFINE NETWORK_HTTP_BOOT_ENABLE       = FALSE
> +  DEFINE NETWORK_ISCSI_ENABLE           = FALSE
> +
>   !include Silicon/NXP/NxpQoriqLs.dsc.inc
>   !include Silicon/NXP/LS1043A/LS1043A.dsc.inc
>   
> @@ -54,4 +61,8 @@ [Components.common]
>     Silicon/NXP/Drivers/I2cDxe/I2cDxe.inf
>     Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.inf
>   
> +  #
> +  # Networking stack
> +  #
> +!include NetworkPkg/Network.dsc.inc
>    ##
> diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
> index 931d0bb14f9b..596922221e8c 100644
> --- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
> +++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
> @@ -119,6 +119,11 @@ [FV.FvMain]
>     INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
>   
>     #
> +  # Networking stack
> +  #
> +!include NetworkPkg/Network.fdf.inc
> +
> +  #
>     # FAT filesystem + GPT/MBR partitioning
>     #
>     INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
> 


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

* Re: [PATCH edk2-platforms 16/16] Platform/NXP: LS1043aRdbPkg : Increase fv image size
  2020-05-21 23:02 ` [PATCH edk2-platforms 16/16] Platform/NXP: LS1043aRdbPkg : Increase fv image size Wasim Khan
@ 2020-05-22  9:44   ` Ard Biesheuvel
  0 siblings, 0 replies; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:44 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> Increase fv image size to pass debug build.
> 
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>

Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>

> ---
>   Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf | 8 +++++---
>   1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
> index 81142f217a63..1c160e349eb9 100644
> --- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
> +++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
> @@ -24,10 +24,12 @@
>   
>   [FD.LS1043ARDB_EFI]
>   BaseAddress   = 0x82000000|gArmTokenSpaceGuid.PcdFdBaseAddress  #The base address of the FLASH Device.
> -Size          = 0x00140000|gArmTokenSpaceGuid.PcdFdSize         #The size in bytes of the FLASH Device
> +Size          = 0x00180000|gArmTokenSpaceGuid.PcdFdSize         #The size in bytes of the FLASH Device
>   ErasePolarity = 1
> +
> +# This one is tricky, it must be: BlockSize * NumBlocks = Size
>   BlockSize     = 0x40000
> -NumBlocks     = 0x5
> +NumBlocks     = 0x6
>   
>   ################################################################################
>   #
> @@ -44,7 +46,7 @@ [FD.LS1043ARDB_EFI]
>   # RegionType <FV, DATA, or FILE>
>   #
>   ################################################################################
> -0x00000000|0x00140000
> +0x00000000|0x00180000
>   gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize
>   FV = FVMAIN_COMPACT
>   
> 


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

* Re: [PATCH edk2-platforms 00/16] Add PCIe Support
  2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
                   ` (15 preceding siblings ...)
  2020-05-21 23:02 ` [PATCH edk2-platforms 16/16] Platform/NXP: LS1043aRdbPkg : Increase fv image size Wasim Khan
@ 2020-05-22  9:46 ` Ard Biesheuvel
  2020-05-22 10:58   ` Leif Lindholm
  16 siblings, 1 reply; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-22  9:46 UTC (permalink / raw)
  To: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	leif, jon
  Cc: Wasim Khan

On 5/22/20 1:02 AM, Wasim Khan wrote:
> From: Wasim Khan <wasim.khan@nxp.com>
> 
> Add PCIe Support for NXP Layerscape SoC which supports
> different PCIe controllers.
> Use generic PCIe drivers and wire up PciHostBridgeLib,
> PciSegmentLib and PciCpuIo2Dxe driver for controller
> specific implementation.
> 

Thanks. This is looking good. Please take a look at the feedback, and 
give others some time to respond as well.

In the meantime, I think we can simply merge #14 and #16 right away 
(unless Leif has any objections)


> Wasim Khan (16):
>    Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs.
>    Silicon/NXP: LS1043A: Define PCIe related PCDs
>    Silicon/NXP: Implement PciHostBridgeLib support
>    Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS
>      Ctrl
>    Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU
>      Windows
>    Silicon/NXP: PciHostBridgeLib: add Workaround for A-011451
>    Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows
>    Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows
>    Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller
>    Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS
>      Controller
>    Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller
>    Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264
>    Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver
>    Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg
>    Platform/NXP: LS1043aRdbPkg: Enable PCIE support
>    Platform/NXP: LS1043aRdbPkg : Increase fv image size
> 
>   Silicon/NXP/NxpQoriqLs.dec                         |  13 +
>   Silicon/NXP/LS1043A/LS1043A.dsc.inc                |   8 +
>   Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc       |  20 +
>   Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf       |  20 +-
>   Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf  |  40 +
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  45 ++
>   .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  36 +
>   Silicon/NXP/Include/Pcie.h                         | 231 ++++++
>   Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c    | 628 +++++++++++++++
>   .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 842 +++++++++++++++++++++
>   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 699 +++++++++++++++++
>   11 files changed, 2579 insertions(+), 3 deletions(-)
>   create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
>   create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
>   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
>   create mode 100755 Silicon/NXP/Include/Pcie.h
>   create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c
>   create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
>   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> 


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

* Re: [PATCH edk2-platforms 00/16] Add PCIe Support
  2020-05-22  9:46 ` [PATCH edk2-platforms 00/16] Add PCIe Support Ard Biesheuvel
@ 2020-05-22 10:58   ` Leif Lindholm
  2020-05-24 18:32     ` Wasim Khan (OSS)
  0 siblings, 1 reply; 42+ messages in thread
From: Leif Lindholm @ 2020-05-22 10:58 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Wasim Khan, devel, meenakshi.aggarwal, vabhav.sharma, V.Sethi,
	jon, Wasim Khan

On Fri, May 22, 2020 at 11:46:07 +0200, Ard Biesheuvel wrote:
> On 5/22/20 1:02 AM, Wasim Khan wrote:
> > From: Wasim Khan <wasim.khan@nxp.com>
> > 
> > Add PCIe Support for NXP Layerscape SoC which supports
> > different PCIe controllers.
> > Use generic PCIe drivers and wire up PciHostBridgeLib,
> > PciSegmentLib and PciCpuIo2Dxe driver for controller
> > specific implementation.
> > 
> 
> Thanks. This is looking good. Please take a look at the feedback, and give
> others some time to respond as well.
> 
> In the meantime, I think we can simply merge #14 and #16 right away (unless
> Leif has any objections)

(Looking at those two out of order.)
16, sure.
14 - is there any reason to do so before there is PCI to connect
network devices through?

/
    Leif

> 
> > Wasim Khan (16):
> >    Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs.
> >    Silicon/NXP: LS1043A: Define PCIe related PCDs
> >    Silicon/NXP: Implement PciHostBridgeLib support
> >    Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS
> >      Ctrl
> >    Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU
> >      Windows
> >    Silicon/NXP: PciHostBridgeLib: add Workaround for A-011451
> >    Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows
> >    Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows
> >    Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller
> >    Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS
> >      Controller
> >    Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller
> >    Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264
> >    Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver
> >    Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg
> >    Platform/NXP: LS1043aRdbPkg: Enable PCIE support
> >    Platform/NXP: LS1043aRdbPkg : Increase fv image size
> > 
> >   Silicon/NXP/NxpQoriqLs.dec                         |  13 +
> >   Silicon/NXP/LS1043A/LS1043A.dsc.inc                |   8 +
> >   Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc       |  20 +
> >   Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf       |  20 +-
> >   Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf  |  40 +
> >   .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  45 ++
> >   .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  36 +
> >   Silicon/NXP/Include/Pcie.h                         | 231 ++++++
> >   Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c    | 628 +++++++++++++++
> >   .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 842 +++++++++++++++++++++
> >   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 699 +++++++++++++++++
> >   11 files changed, 2579 insertions(+), 3 deletions(-)
> >   create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
> >   create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> >   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> >   create mode 100755 Silicon/NXP/Include/Pcie.h
> >   create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c
> >   create mode 100644 Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> >   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > 
> 

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

* Re: [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs.
  2020-05-22  9:12   ` Ard Biesheuvel
@ 2020-05-24 18:31     ` Wasim Khan (OSS)
  2020-05-26  6:16       ` Ard Biesheuvel
  0 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan (OSS) @ 2020-05-24 18:31 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Wasim Khan (OSS), devel@edk2.groups.io, Meenakshi Aggarwal,
	Vabhav Sharma, Varun Sethi, leif@nuviainc.com, jon@solid-run.com



> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Sent: Friday, May 22, 2020 2:42 PM
> To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> leif@nuviainc.com; jon@solid-run.com
> Cc: Wasim Khan <wasim.khan@nxp.com>
> Subject: Re: [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add
> PCIe related PCDs.
> 
> On 5/22/20 1:02 AM, Wasim Khan wrote:
> > From: Wasim Khan <wasim.khan@nxp.com>
> >
> > Add PCIe related PCDs.
> >
> > Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> 
> Please drop this signoff. This is not the correct way to acknowledge (co-
> )authorship.

Co-authored-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Co-authored-by: Wasim Khan <wasim.khan@nxp.com>
Signed-off-by: Wasim Khan <wasim.khan@nxp.com>

Is this OK ?

> 
> > Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> > ---
> >   Silicon/NXP/NxpQoriqLs.dec | 9 +++++++++
> >   1 file changed, 9 insertions(+)
> >
> > diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
> > index 0722f59ef4f6..bafdfd9f4298 100644
> > --- a/Silicon/NXP/NxpQoriqLs.dec
> > +++ b/Silicon/NXP/NxpQoriqLs.dec
> > @@ -27,3 +27,12 @@ [Guids.common]
> >   [PcdsFeatureFlag]
> >
> gNxpQoriqLsTokenSpaceGuid.PcdI2cErratumA009203|FALSE|BOOLEAN|0x0000
> 0315
> >
> >
> gNxpQoriqLsTokenSpaceGuid.PcdDcfgBigEndian|FALSE|BOOLEAN|0x00000316
> > +
> > +
> gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian|FALSE|BOOLEAN|0x0000031
> > + 7
> > +
> > +[PcdsFixedAtBuild.common]
> > +  # Pcds for PCI Express
> > +
> gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr|0x0|UINT64|0x00000500
> > +  gNxpQoriqLsTokenSpaceGuid.PcdNumPciController|0|UINT32|0x00000501
> > +  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase|0x0|UINT32|0x00000502
> > +  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg|0x0|UINT32|0x00000503
> > +  gNxpQoriqLsTokenSpaceGuid.PcdPciDebug|FALSE|BOOLEAN|0x00000504
> >


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

* Re: [PATCH edk2-platforms 05/16] Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU Windows
  2020-05-22  9:24   ` Ard Biesheuvel
@ 2020-05-24 18:31     ` Wasim Khan (OSS)
  0 siblings, 0 replies; 42+ messages in thread
From: Wasim Khan (OSS) @ 2020-05-24 18:31 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: devel@edk2.groups.io, Meenakshi Aggarwal, Vabhav Sharma,
	Varun Sethi, leif@nuviainc.com, jon@solid-run.com



> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Sent: Friday, May 22, 2020 2:55 PM
> To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> leif@nuviainc.com; jon@solid-run.com
> Cc: Wasim Khan <wasim.khan@nxp.com>
> Subject: Re: [PATCH edk2-platforms 05/16] Silicon/NXP: PciHostBridgeLib: Setup
> PCIe LsGen4 Controller and ATU Windows
> 
> On 5/22/20 1:02 AM, Wasim Khan wrote:
> > From: Wasim Khan <wasim.khan@nxp.com>
> >
> > Setup PCIe LayerscapeGen4 controller and setup CFG, IO, MMIO and
> > MMIO64 iATU windows.
> > Check for PcdPciLsGen4Ctrl to enable LsGen4 PCIe controller.
> >
> > Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> > Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> 
> How much overlap is there between these controllers? Does it really make sense
> to use the same PciHostBridgeLib implementation and parameterize the hell out
> of it?
> 

Majorly the Window configuration part is different as both controller has different registers set. 
Most of the common code is same, that’s why we want to keep a single PciHostBrigeLib.
Also, for the LX2160-Rev1 and LX2160-Rev2 PCIe controller is different, so to use the same Binary on both versions, we use single Library and based on SoC version at run time , we enable the underneath controller. 


> 
> > ---
> >   Silicon/NXP/NxpQoriqLs.dec                         |   1 +
> >   .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |   1 +
> >   Silicon/NXP/Include/Pcie.h                         | 120 ++++++++++
> >   .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 255 +++++++++++++++++-
> ---
> >   4 files changed, 336 insertions(+), 41 deletions(-)
> >
> > diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
> > index 293fd773fd3d..8271d19ed8e5 100644
> > --- a/Silicon/NXP/NxpQoriqLs.dec
> > +++ b/Silicon/NXP/NxpQoriqLs.dec
> > @@ -39,3 +39,4 @@ [PcdsFixedAtBuild.common]
> >
> >   [PcdsDynamic.common]
> >
> >
> gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable|FALSE|BOOLEAN|0x000006
> 0
> > 0
> > +
> gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl|FALSE|BOOLEAN|0x00000601
> > diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> > b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> > index 98cfb6aee6b0..b777acdc103f 100644
> > --- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> > +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> > @@ -41,3 +41,4 @@ [FixedPcd]
> >
> >   [Pcd]
> >     gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
> > +  gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl
> > diff --git a/Silicon/NXP/Include/Pcie.h b/Silicon/NXP/Include/Pcie.h
> > index ae85190180e8..4c41c3585a8b 100755
> > --- a/Silicon/NXP/Include/Pcie.h
> > +++ b/Silicon/NXP/Include/Pcie.h
> > @@ -84,5 +84,125 @@
> >   #define SEG_IO_BUS                0x0
> >
> >   #define CFG_SHIFT_ENABLE          (PcdGetBool (PcdPciCfgShiftEnable))
> > +#define PCI_LS_GEN4_CTRL          (PcdGetBool (PcdPciLsGen4Ctrl))
> >
> > +// PCIe Layerscape Gen4 Controller
> > +#define GPEX_CLASSCODE                          0x474
> > +#define GPEX_CLASSCODE_SHIFT                    16
> > +#define GPEX_CLASSCODE_MASK                     0xffff
> > +#define PAB_AXI_PIO_CTRL(Idx)                   (0x840 + 0x10 * Idx)
> > +#define APIO_EN                                 0x1
> > +#define MEM_WIN_EN                              0x1 << 1
> > +#define IO_WIN_EN                               0x1 << 2
> > +#define CFG_WIN_EN                              0x1 << 3
> > +#define PAB_PEX_PIO_CTRL(Idx)                   (0x8c0 + 0x10 * Idx)
> > +#define PPIO_EN                                 (0x1 << 0)
> > +#define PAB_PEX_PIO_STAT(Idx)                   (0x8c4 + 0x10 * Idx)
> > +#define PAB_PEX_PIO_MT_STAT(Idx)                (0x8c8 + 0x10 * Idx)
> > +#define PEX_AMAP_CTRL_TYPE_SHIFT                0x1
> > +#define PEX_AMAP_CTRL_EN_SHIFT                  0x0
> > +#define PEX_AMAP_CTRL_TYPE_MASK                 0x3
> > +#define PEX_AMAP_CTRL_EN_MASK                   0x1
> > +#define PAB_PEX_AMAP_CTRL(Idx)                  (0x4ba0 + 0x10 * Idx)
> > +#define PAB_EXT_PEX_AMAP_SIZE(Idx)              (0xbef0 + 0x04 * Idx)
> > +#define PAB_PEX_AMAP_AXI_WIN(Idx)               (0x4ba4 + 0x10 * Idx)
> > +#define PAB_EXT_PEX_AMAP_AXI_WIN(Idx)           (0xb4a0 + 0x04 * Idx)
> > +#define PAB_PEX_AMAP_PEX_WIN_L(Idx)             (0x4ba8 + 0x10 * Idx)
> > +#define PAB_PEX_AMAP_PEX_WIN_H(Idx)             (0x4bac + 0x10 * Idx)
> > +#define PAB_CTRL                                0x808
> > +#define PAB_CTRL_APIO_EN                        0x1
> > +#define PAB_CTRL_PPIO_EN                        (0x1 << 1)
> > +#define PAB_CTRL_PAGE_SEL_SHIFT                 13
> > +#define PAB_CTRL_PAGE_SEL_MASK                  0x3f
> > +#define INDIRECT_ADDR_BNDRY                     0xc00
> > +#define PAGE_IDX_SHIFT                          10
> > +#define PAGE_ADDR_MASK                          0x3ff
> > +#define PAB_AXI_AMAP_CTRL(Idx)                  (0xba0 + 0x10 * Idx)
> > +#define PAB_EXT_AXI_AMAP_SIZE(Idx)              (0xbaf0 + 0x4 * Idx)
> > +#define PAB_AXI_AMAP_AXI_WIN(Idx)               (0xba4 + 0x10 * Idx)
> > +#define PAB_EXT_AXI_AMAP_AXI_WIN(Idx)           (0x80a0 + 0x4 * Idx)
> > +#define PAB_AXI_AMAP_PEX_WIN_L(Idx)             (0xba8 + 0x10 * Idx)
> > +#define PAB_AXI_AMAP_PEX_WIN_H(Idx)             (0xbac + 0x10 * Idx)
> > +#define PAB_AXI_TYPE_CFG                        0x00
> > +#define PAB_AXI_TYPE_IO                         0x01
> > +#define PAB_AXI_TYPE_MEM                        0x02
> > +#define AXI_AMAP_CTRL_EN                        0x1
> > +#define AXI_AMAP_CTRL_TYPE_SHIFT                1
> > +#define AXI_AMAP_CTRL_TYPE_MASK                 0x3
> > +#define AXI_AMAP_CTRL_SIZE_SHIFT                10
> > +#define AXI_AMAP_CTRL_SIZE_MASK                 0x3fffff
> > +
> > +
> > +#define OFFSET_TO_PAGE_IDX(Off)                 ((Off >> PAGE_IDX_SHIFT) \
> > +                                                &
> > +PAB_CTRL_PAGE_SEL_MASK)
> > +
> > +#define OFFSET_TO_PAGE_ADDR(Off)                ((Off & PAGE_ADDR_MASK) \
> > +                                                |
> > +INDIRECT_ADDR_BNDRY)
> > +/**
> > +  Function to set page for LsGen4 Ctrl
> > +
> > +  @param  Dbi    GPEX host controller address.
> > +  @param  PgIdx  The page index to select
> > +
> > +**/
> > +STATIC inline VOID PciLsGen4SetPg (
> > +  IN EFI_PHYSICAL_ADDRESS Dbi,
> > +  IN UINT8 PgIdx
> > +  )
> > +{
> > +  UINT32 Val;
> > +  Val = MmioRead32 (Dbi + PAB_CTRL);
> > +  Val &= ~(PAB_CTRL_PAGE_SEL_MASK << PAB_CTRL_PAGE_SEL_SHIFT);
> > +  Val |= (PgIdx & PAB_CTRL_PAGE_SEL_MASK) <<
> PAB_CTRL_PAGE_SEL_SHIFT;
> > +  MmioWrite32 (Dbi + PAB_CTRL, Val);
> > +}
> > +
> > +/**
> > +  Function to read LsGen4 PCIe controller config space
> > +  LsGen4 PCIe controller requires page number to be set
> > +  in Bridge Control Register(PAB) for offset > 3KB.
> > +
> > +  @param  Dbi     GPEX host controller address.
> > +  @param  Offset  Offset to read from
> > +
> > +**/
> > +STATIC inline INTN PciLsGen4Read32 (
> > +  IN EFI_PHYSICAL_ADDRESS Dbi,
> > +  IN UINT32 Offset
> > +  )
> > +{
> > +  if (Offset < INDIRECT_ADDR_BNDRY) {
> > +    PciLsGen4SetPg (Dbi, 0);
> > +    return MmioRead32 (Dbi + Offset);
> > +  } else {
> > +    // If Offset > 3KB, paging mechanism is used
> > +    // Select page index and offset within the page
> > +    PciLsGen4SetPg (Dbi, OFFSET_TO_PAGE_IDX (Offset));
> > +    return MmioRead32 (Dbi + OFFSET_TO_PAGE_ADDR (Offset));
> > +  }
> > +}
> > +
> > +/**
> > +  Function to write to LsGen4 PCIe controller config space
> > +  LsGen4 PCIe controller requires page number to be set
> > +  in Bridge Control Register(PAB) for offset > 3KB.
> > +
> > +  @param  Dbi     GPEX host controller address
> > +  @param  Offset  Offset to read from
> > +
> > +**/
> > +STATIC inline VOID PciLsGen4Write32 (
> > +  IN EFI_PHYSICAL_ADDRESS Dbi,
> > +  IN UINT32 Offset,
> > +  IN UINT32 Value
> > +  )
> > +{
> > +  if (Offset < INDIRECT_ADDR_BNDRY) {
> > +    PciLsGen4SetPg (Dbi, 0);
> > +    MmioWrite32 (Dbi + Offset, Value);
> > +  } else {
> > +    PciLsGen4SetPg (Dbi, OFFSET_TO_PAGE_IDX (Offset));
> > +    MmioWrite32 (Dbi + OFFSET_TO_PAGE_ADDR (Offset), Value);
> > +  }
> > +}
> >   #endif
> > diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> > b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> > index f92863c60868..d9944313da21 100644
> > --- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> > +++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> > @@ -201,7 +201,11 @@ PcieLinkUp (
> >     UINT32 State;
> >     UINT32 LtssmMask;
> >
> > -  LtssmMask = 0x3f;
> > +  if (PCI_LS_GEN4_CTRL) {
> > +    LtssmMask = 0x7f;
> > +  } else {
> > +    LtssmMask = 0x3f;
> > +  }
> >
> >     PcieOps = GetMmioOperations (FeaturePcdGet (PcdPciLutBigEndian));
> >     State = PcieOps->Read32 ((UINTN)Pcie + PCI_LUT_BASE + PCI_LUT_DBG)
> > & LtssmMask; @@ -237,38 +241,58 @@ PcieOutboundSet (
> >     IN UINT64 Size
> >     )
> >   {
> > -  // PCIe Layerscape : Outbound Window
> > -  MmioWrite32 (Dbi + IATU_VIEWPORT_OFF,
> > -                (UINT32)(IATU_VIEWPORT_OUTBOUND | Idx));
> > +  UINT32 Val;
> >
> > -  MmioWrite32 (Dbi + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
> > -                (UINT32)Phys);
> > -
> > -  MmioWrite32 (Dbi + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
> > -                (UINT32)(Phys >> 32));
> > -
> > -  MmioWrite32 (Dbi + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
> > -                (UINT32)(Phys + Size - BIT0));
> > -
> > -  MmioWrite32 (Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> > -                (UINT32)BusAddr);
> > -
> > -  MmioWrite32 (Dbi + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
> > -                (UINT32)(BusAddr >> 32));
> > -
> > -  MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
> > -                (UINT32)Type);
> > -
> > -  if (CFG_SHIFT_ENABLE &&
> > -     ((Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0) ||
> > -     (Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1))) {
> > -       MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> > -         (IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN |
> > -         IATU_ENABLE_CFG_SHIFT_FEATURE)
> > -         );
> > +  if (PCI_LS_GEN4_CTRL) {
> > +    // PCIe Layerscape Gen4: Outbound Window
> > +    Size = ~(Size -1 );
> > +    Val = PciLsGen4Read32 ((UINTN)Dbi, PAB_AXI_AMAP_CTRL (Idx));
> > +    Val &= ~((AXI_AMAP_CTRL_TYPE_MASK << AXI_AMAP_CTRL_TYPE_SHIFT)
> |
> > +              (AXI_AMAP_CTRL_SIZE_MASK << AXI_AMAP_CTRL_SIZE_SHIFT) |
> > +              AXI_AMAP_CTRL_EN);
> > +    Val |= ((Type & AXI_AMAP_CTRL_TYPE_MASK) <<
> AXI_AMAP_CTRL_TYPE_SHIFT) |
> > +             (((UINT32)Size >> AXI_AMAP_CTRL_SIZE_SHIFT) <<
> > +             AXI_AMAP_CTRL_SIZE_SHIFT) | AXI_AMAP_CTRL_EN;
> > +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_CTRL (Idx), Val);
> > +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_AXI_WIN (Idx),
> (UINT32)Phys);
> > +    PciLsGen4Write32 ((UINTN)Dbi, PAB_EXT_AXI_AMAP_AXI_WIN (Idx), Phys
> >> 32);
> > +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_L (Idx),
> (UINT32)BusAddr);
> > +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_H (Idx),
> BusAddr >> 32);
> > +    PciLsGen4Write32 ((UINTN)Dbi, PAB_EXT_AXI_AMAP_SIZE (Idx), Size
> > + >> 32);
> >     } else {
> > -    MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> > -                  IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
> > +    // PCIe Layerscape : Outbound Window
> > +    MmioWrite32 (Dbi + IATU_VIEWPORT_OFF,
> > +                  (UINT32)(IATU_VIEWPORT_OUTBOUND | Idx));
> > +
> > +    MmioWrite32 (Dbi + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
> > +                  (UINT32)Phys);
> > +
> > +    MmioWrite32 (Dbi + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
> > +                  (UINT32)(Phys >> 32));
> > +
> > +    MmioWrite32 (Dbi + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
> > +                  (UINT32)(Phys + Size - BIT0));
> > +
> > +    MmioWrite32 (Dbi + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> > +                  (UINT32)BusAddr);
> > +
> > +    MmioWrite32 (Dbi + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
> > +                  (UINT32)(BusAddr >> 32));
> > +
> > +    MmioWrite32 (Dbi + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
> > +                  (UINT32)Type);
> > +
> > +    if (CFG_SHIFT_ENABLE &&
> > +       ((Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0) ||
> > +       (Type == IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1))) {
> > +         MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> > +           (IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN |
> > +           IATU_ENABLE_CFG_SHIFT_FEATURE)
> > +           );
> > +    } else {
> > +      MmioWrite32 (Dbi + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> > +                    IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN);
> > +    }
> >     }
> >   }
> >
> > @@ -387,6 +411,124 @@ PcieLsSetupAtu (
> >       SEG_IO_SIZE
> >       );
> >   }
> > +
> > +/**
> > +  Function to set-up ATU windows for PCIe LayerscapeGen4 controller
> > +
> > +  @param Pcie      Address of PCIe host controller
> > +  @param Cfg0Base  PCIe controller phy address Type0 Configuration Space.
> > +  @param Cfg1Base  PCIe controller phy address Type1 Configuration Space.
> > +  @param MemBase   PCIe controller phy address Memory Space.
> > +  @param Mem64Base PCIe controller phy address MMIO64 Space.
> > +  @param IoBase    PCIe controller phy address IO Space.
> > +**/
> > +STATIC
> > +VOID
> > +PcieLsGen4SetupAtu (
> > +  IN EFI_PHYSICAL_ADDRESS Pcie,
> > +  IN EFI_PHYSICAL_ADDRESS Cfg0Base,
> > +  IN EFI_PHYSICAL_ADDRESS Cfg1Base,
> > +  IN EFI_PHYSICAL_ADDRESS MemBase,
> > +  IN EFI_PHYSICAL_ADDRESS Mem64Base,
> > +  IN EFI_PHYSICAL_ADDRESS IoBase
> > +  )
> > +{
> > +  // ATU : OUTBOUND WINDOW 1 : CFG0
> > +  PcieOutboundSet (Pcie, IATU_REGION_INDEX0,
> > +                         PAB_AXI_TYPE_CFG,
> > +                         Cfg0Base,
> > +                         SEG_CFG_BUS,
> > +                         SEG_CFG_SIZE);
> > +
> > +  // ATU : OUTBOUND WINDOW 2 : IO
> > +  PcieOutboundSet (Pcie, IATU_REGION_INDEX1,
> > +                         PAB_AXI_TYPE_IO,
> > +                         IoBase,
> > +                         SEG_IO_BUS,
> > +                         SEG_IO_SIZE);
> > +
> > +  // ATU : OUTBOUND WINDOW 3 : MEM
> > +  PcieOutboundSet (Pcie, IATU_REGION_INDEX2,
> > +                         PAB_AXI_TYPE_MEM,
> > +                         MemBase,
> > +                         SEG_MEM_BUS,
> > +                         SEG_MEM_SIZE);
> > +
> > +  // ATU : OUTBOUND WINDOW 4 : MMIO64  PcieOutboundSet (Pcie,
> > + IATU_REGION_INDEX3,
> > +                            PAB_AXI_TYPE_MEM,
> > +                            Mem64Base,
> > +                            Mem64Base,
> > +                            SIZE_4GB);  Mem64Base += SIZE_4GB;
> > +
> > +  // ATU : OUTBOUND WINDOW 5 : MMIO64  PcieOutboundSet (Pcie,
> > + IATU_REGION_INDEX4,
> > +                            PAB_AXI_TYPE_MEM,
> > +                            Mem64Base,
> > +                            Mem64Base,
> > +                            SIZE_4GB);  Mem64Base += SIZE_4GB;
> > +
> > +  // ATU : OUTBOUND WINDOW 6 : MMIO64  PcieOutboundSet (Pcie,
> > + IATU_REGION_INDEX5,
> > +                            PAB_AXI_TYPE_MEM,
> > +                            Mem64Base,
> > +                            Mem64Base,
> > +                            SIZE_4GB);  Mem64Base += SIZE_4GB;
> > +
> > +  // ATU : OUTBOUND WINDOW 7 : MMIO64
> > +  PcieOutboundSet (Pcie, IATU_REGION_INDEX6,
> > +                            PAB_AXI_TYPE_MEM,
> > +                            Mem64Base,
> > +                            Mem64Base,
> > +                            SIZE_4GB); }
> > +
> > +/**
> > +  Function to set-up PCIe inbound window
> > +
> > +  @param Pcie    Address of PCIe host controller.
> > +  @param Idx     Index of inbound window.
> > +  @param Type    Type(Cfg/Mem/IO) of iATU outbound window.
> > +  @param Phys    PCIe controller phy address for inbound window.
> > +  @param BusAdr  PCIe controller bus address for inbound window.
> > +  @param Size    Window size
> > +
> > +**/
> > +
> > +STATIC
> > +VOID
> > +PciSetupInBoundWin (
> > +  IN EFI_PHYSICAL_ADDRESS Pcie,
> > +  IN UINT32 Idx,
> > +  IN UINT32  Type,
> > +  IN UINT64 Phys,
> > +  IN UINT64 BusAddr,
> > +  IN UINT64 Size)
> > +{
> > +  UINT32 Val;
> > +  UINT64 WinSize;
> > +
> > +  if (PCI_LS_GEN4_CTRL) {
> > +    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_PEX_AMAP_CTRL(Idx));
> > +    Val &= ~(PEX_AMAP_CTRL_TYPE_MASK << PEX_AMAP_CTRL_TYPE_SHIFT);
> > +    Val &= ~(PEX_AMAP_CTRL_EN_MASK << PEX_AMAP_CTRL_EN_SHIFT);
> > +    Val = (Val | (Type << PEX_AMAP_CTRL_TYPE_SHIFT));
> > +    Val = (Val | (1 << PEX_AMAP_CTRL_EN_SHIFT));
> > +
> > +    WinSize = ~(Size - 1);
> > +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_CTRL(Idx),
> > +                       (Val | (UINT32)WinSize));
> > +    PciLsGen4Write32 ((UINTN)Pcie, PAB_EXT_PEX_AMAP_SIZE(Idx),
> (WinSize>>32));
> > +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_AXI_WIN(Idx),
> (UINT32)Phys);
> > +    PciLsGen4Write32 ((UINTN)Pcie, PAB_EXT_PEX_AMAP_AXI_WIN(Idx),
> (Phys>>32));
> > +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_PEX_WIN_L(Idx),
> (UINT32)BusAddr);
> > +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_AMAP_PEX_WIN_H(Idx),
> > +(BusAddr >>32));
> > +  }
> > +}
> > +
> >   /**
> >     Helper function to set-up PCIe controller
> >
> > @@ -411,16 +553,47 @@ PcieSetupCntrl (
> >   {
> >     UINT32 Val;
> >
> > -  // PCIe Layerscape Controller Setup
> > -  PcieLsSetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base,
> > IoBase);
> > -
> > -  // Program Class code for Layerscape PCIe controller
> > -  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 1);
> > -  Val = MmioRead32 ((UINTN)Pcie + PCI_CLASS_DEVICE);
> > -  Val &= ~(CLASS_CODE_MASK << CLASS_CODE_SHIFT);
> > -  Val |= (PCI_CLASS_BRIDGE_PCI << CLASS_CODE_SHIFT);
> > -  MmioWrite32 ((UINTN)Pcie + PCI_CLASS_DEVICE, Val);
> > -  MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 0);
> > +  if (PCI_LS_GEN4_CTRL) {
> > +    // PCIe LsGen4 Controller Setup
> > +
> > +    //Fix Class Code
> > +    Val = PciLsGen4Read32 ((UINTN)Pcie, GPEX_CLASSCODE);
> > +    Val &= ~(GPEX_CLASSCODE_MASK << GPEX_CLASSCODE_SHIFT);
> > +    Val |= PCI_CLASS_BRIDGE_PCI << GPEX_CLASSCODE_SHIFT;
> > +    PciLsGen4Write32 ((UINTN)Pcie, GPEX_CLASSCODE, Val);
> > +
> > +    // Enable APIO and Memory/IO/CFG Windows
> > +    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_AXI_PIO_CTRL (0));
> > +    Val |= APIO_EN | MEM_WIN_EN | IO_WIN_EN | CFG_WIN_EN;
> > +    PciLsGen4Write32 ((UINTN)Pcie, PAB_AXI_PIO_CTRL (0), Val);
> > +
> > +    // LsGen4 Inbound Window Setup
> > +    PciSetupInBoundWin (Pcie, 0, PAB_AXI_TYPE_MEM, 0 , 0, SIZE_1TB);
> > +
> > +    // LsGen4 Outbound Window Setup
> > +    PcieLsGen4SetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base,
> > + IoBase);
> > +
> > +    // Enable AMBA & PEX PIO
> > +    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_CTRL);
> > +    Val |= PAB_CTRL_APIO_EN | PAB_CTRL_PPIO_EN;
> > +    PciLsGen4Write32 ((UINTN)Pcie, PAB_CTRL, Val);
> > +
> > +    Val = PciLsGen4Read32 ((UINTN)Pcie, PAB_PEX_PIO_CTRL(0));
> > +    Val |= PPIO_EN;
> > +    PciLsGen4Write32 ((UINTN)Pcie, PAB_PEX_PIO_CTRL(0), Val);
> > +
> > +  } else {
> > +    // PCIe Layerscape Controller Setup
> > +    PcieLsSetupAtu (Pcie, Cfg0Base, Cfg1Base, MemBase, Mem64Base,
> > + IoBase);
> > +
> > +    // Program Class code for Layerscape PCIe controller
> > +    MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 1);
> > +    Val = MmioRead32 ((UINTN)Pcie + PCI_CLASS_DEVICE);
> > +    Val &= ~(CLASS_CODE_MASK << CLASS_CODE_SHIFT);
> > +    Val |= (PCI_CLASS_BRIDGE_PCI << CLASS_CODE_SHIFT);
> > +    MmioWrite32 ((UINTN)Pcie + PCI_CLASS_DEVICE, Val);
> > +    MmioWrite32 ((UINTN)Pcie + PCI_DBI_RO_WR_EN, 0);  }
> >   }
> >
> >   /**
> >


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

* Re: [PATCH edk2-platforms 09/16] Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller
  2020-05-22  9:29   ` Ard Biesheuvel
@ 2020-05-24 18:32     ` Wasim Khan (OSS)
  2020-05-25  4:30       ` Jon Nettleton
  0 siblings, 1 reply; 42+ messages in thread
From: Wasim Khan (OSS) @ 2020-05-24 18:32 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: devel@edk2.groups.io, Meenakshi Aggarwal, Vabhav Sharma,
	Varun Sethi, leif@nuviainc.com, jon@solid-run.com



> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Sent: Friday, May 22, 2020 3:00 PM
> To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> leif@nuviainc.com; jon@solid-run.com
> Cc: Wasim Khan <wasim.khan@nxp.com>
> Subject: Re: [PATCH edk2-platforms 09/16] Silicon/NXP: Implement
> PciSegmentLib for PCIe Layerscape Controller
> 
> On 5/22/20 1:02 AM, Wasim Khan wrote:
> > From: Wasim Khan <wasim.khan@nxp.com>
> >
> > We have different PCI config space region for bus 0 (Controller space)
> > and bus[0x1-0xff] on NXP SoCs with PCIe LS controller.
> > Add PciSegmentLib for PCIe LS controller.
> >
> > For config transactions for Bus0:
> >    - Config transaction address = PCIe controller address + offset
> >
> > For config transactions for Bus[0x1-0xff]:
> >    - PCIe IP requires target BDF to be written at bit[31:16] of PCIe
> >      type0/type1 outbound window.
> >    - Config transaction address = PCIe config space address + offset
> >
> > Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> > Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> > ---
> >   .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  32 ++
> >   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 612
> +++++++++++++++++++++
> >   2 files changed, 644 insertions(+)
> >   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> >   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> >
> > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > new file mode 100755
> > index 000000000000..a36e79239b33
> > --- /dev/null
> > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > @@ -0,0 +1,32 @@
> > +## @file
> > +#  PCI Segment Library for NXP SoCs with multiple RCs # #  Copyright
> > +2018-2020 NXP # #  SPDX-License-Identifier: BSD-2-Clause-Patent ##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x0001001A
> > +  BASE_NAME                      = PciSegmentLib
> > +  FILE_GUID                      = c9f59261-5a60-4a4c-82f6-1f520442e100
> > +  MODULE_TYPE                    = DXE_DRIVER
> 
> Can this be BASE ?
> 

No, we need constructor function PciSegLibInit() which requires it to be DXE_DRIVER. 

> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = PciSegmentLib|DXE_DRIVER
> > +  CONSTRUCTOR                    = PciSegLibInit
> > +
> > +[Sources]
> > +  PciSegmentLib.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  Silicon/NXP/NxpQoriqLs.dec
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +  DebugLib
> > +  IoLib
> > +  PcdLib
> > +
> > +[FixedPcd]
> > +  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
> > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > new file mode 100755
> > index 000000000000..ecd36971b753
> > --- /dev/null
> > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > @@ -0,0 +1,612 @@
> > +/** @file
> > +  PCI Segment Library for NXP SoCs with multiple RCs
> > +
> > +  Copyright 2018-2020 NXP
> > +
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include <PiDxe.h>
> > +#include <Base.h> #include <IndustryStandard/Pci22.h> #include
> > +<Library/PciSegmentLib.h> #include <Library/BaseLib.h> #include
> > +<Library/DebugLib.h> #include <Library/IoLib.h> #include
> > +<Library/MemoryAllocationLib.h> #include <Library/PcdLib.h> #include
> > +<Pcie.h>
> > +
> > +typedef enum {
> > +  PciCfgWidthUint8      = 0,
> > +  PciCfgWidthUint16,
> > +  PciCfgWidthUint32,
> > +  PciCfgWidthMax
> > +} PCI_CFG_WIDTH;
> > +
> > +/**
> > +  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)
> > +
> > +STATIC
> > +UINT64
> > +PciLsCfgTarget (
> > +  IN  EFI_PHYSICAL_ADDRESS Dbi,
> > +  IN  UINT64               Address,
> > +  IN  UINT16               Segment,
> > +  IN  UINT8                Bus,
> > +  IN  UINT16               Offset
> > +  )
> > +{
> > +  UINT32 Target;
> > +
> > +  Target = ((((Address >> 20) & 0xFF) << 24) |
> > +           (((Address >> 15) & 0x1F) << 19) |
> > +           (((Address >> 12) & 0x7) << 16));
> 
> You can drop the outer () here
> 

OK

> > +
> > +  if (Bus > 1) {
> > +    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF,
> > + IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX1);  } else {
> > +    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF,
> > + IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX0);  }
> > +
> > +  MmioWrite32 ((UINTN)Dbi +
> IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> > + Target);
> > +
> > +  if (Bus > 1) {
> > +    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment +
> > + SEG_CFG_SIZE + Offset;  } else {
> > +    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment + Offset;
> > + }
> 
> OK, so this is the version for the IP that does not implement ECAM shift, right?

No, PCIe Layerscape support both mechanism ECAM & Non-ECAM (with exception of bus 0).
PCIe LSGen4 controller does not support ECAM at all , which is part of patch #11 

> 
> > +}
> > +
> > +/**
> > +  Function to return PCIe Physical Address(PCIe view) or Controller
> > +  Address(CPU view) for different RCs
> > +
> > +  @param  Address Address passed from bus layer.
> > +  @param  Segment Segment number for Root Complex.
> > +  @param  Offset  Config space register offset.
> > +  @param  Bus     PCIe Bus number.
> > +
> > +  @return Return PCIe CPU or Controller address.
> > +
> > +**/
> > +STATIC
> > +UINT64
> > +PciLsGetConfigBase (
> > +  IN  UINT64      Address,
> > +  IN  UINT16      Segment,
> > +  IN  UINT16      Offset,
> > +  IN  UINT8       Bus
> > +  )
> > +{
> > +  UINT32 CfgAddr;
> > +
> > +  CfgAddr = (UINT16)Offset;
> > +  if (Bus) {
> 
> Please use Bus > 0 here

OK

> 
> > +    return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF *
> > +Segment, Address, Segment, Bus, Offset);
> > +  } else {
> > +    return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
> > +  }
> > +}
> > +
> > +/**
> > +  Function to return PCIe Physical Address(PCIe view) or Controller
> > +  Address(CPU view) for different RCs
> > +
> > +  @param  Address Address passed from bus layer.
> > +  @param  Segment Segment number for Root Complex.
> > +  @param  Offset  Config space register offset.
> > +
> > +  @return Return PCIe CPU or Controller address.
> > +
> > +**/
> > +STATIC
> > +UINT64
> > +PciSegmentLibGetConfigBase (
> > +  IN  UINT64      Address,
> > +  IN  UINT16      Segment,
> > +  IN  UINT16      Offset
> > +  )
> > +{
> > +  UINT8  Bus;
> > +
> > +  Bus = ((UINT32)Address >> 20) & 0xff;
> > +  return PciLsGetConfigBase (Address, Segment, Offset, Bus); }
> > +
> > +/**
> > +  Internal worker function to read a PCI configuration register.
> > +
> > +  @param  Address The address that encodes the Segment, 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;
> > +  UINT16    Offset;
> > +  UINT16    Segment;
> > +
> > +  Segment = (Address >> 32);
> > +  Offset = (Address & 0xfff );
> > +
> > +  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
> > +
> > +  // ignore devices > 0 on bus 0
> > +  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
> > +    return MAX_UINT32;
> > +  }
> > +
> > +  // ignore device > 0 on bus 1
> > +  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
> > +    return MAX_UINT32;
> > +  }
> > +
> > +  switch (Width) {
> > +  case PciCfgWidthUint8:
> > +    return MmioRead8 (Base);
> > +  case PciCfgWidthUint16:
> > +    return MmioRead16 (Base);
> > +  case PciCfgWidthUint32:
> > +    return MmioRead32 (Base);
> > +  default:
> > +    ASSERT (FALSE);
> > +  }
> > +
> > +  return CHAR_NULL;
> > +}
> > +
> > +/**
> > +  Internal worker function to writes a PCI configuration register.
> > +
> > +  @param  Address The address that encodes the Segment, 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;
> > +  UINT32    Offset;
> > +  UINT16    Segment;
> > +
> > +  Segment = (Address >> 32);
> > +  Offset = (Address & 0xfff );
> > +
> > +  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
> > +
> > +  // ignore devices > 0 on bus 0
> > +  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
> > +    return Data;
> > +  }
> > +
> > +  // ignore device > 0 on bus 1
> > +  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
> > +    return MAX_UINT32;
> > +  }
> > +
> > +  switch (Width) {
> > +  case PciCfgWidthUint8:
> > +    MmioWrite8 (Base , Data);
> > +    break;
> > +  case PciCfgWidthUint16:
> > +    MmioWrite16 (Base , Data);
> > +    break;
> > +  case PciCfgWidthUint32:
> > +    MmioWrite32 (Base , Data);
> > +    break;
> > +  default:
> > +    ASSERT (FALSE);
> > +  }
> > +
> > +  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.
> > +
> > +  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); }
> > +
> > +/**
> > +  Reads a 16-bit PCI configuration register.
> > +
> > +  Reads and returns 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().
> > +
> > +  @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.
> > +
> > +  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); }
> > +
> > +/**
> > +  Reads a 32-bit PCI configuration register.
> > +
> > +  Reads and returns the 32-bit PCI configuration register specified by Address.
> > +
> > +  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.
> > +
> > +  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); }
> > +
> > +/**
> > +  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.
> > +
> > +  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) <= SIZE_4KB);
> > +
> > +  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 + BIT0;
> > +  }
> > +
> > +  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 + BIT0;
> > +  }
> > +
> > +  while (Size >= sizeof (UINT32)) {
> > +    //
> > +    // Read as many double words as possible
> > +    //
> > +    WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));
> > +    StartAddress += sizeof (UINT32);
> > +    Size -= sizeof (UINT32);
> > +    Buffer = (UINT32*)Buffer + BIT0;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16)) {
> > +    //
> > +    // Read the last remaining word if exist
> > +    //
> > +    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + BIT0;
> > +  }
> > +
> > +  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.
> > +
> > +  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) <= SIZE_4KB);
> > +
> > +  if (Size == 0) {
> > +    return Size;
> > +  }
> > +
> > +  ASSERT (Buffer != NULL);
> > +
> > +  //
> > +  // 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 + BIT0;
> > +  }
> > +
> > +  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 + BIT0;
> > +  }
> > +
> > +  while (Size >= sizeof (UINT32)) {
> > +    //
> > +    // Write as many double words as possible
> > +    //
> > +    PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));
> > +    StartAddress += sizeof (UINT32);
> > +    Size -= sizeof (UINT32);
> > +    Buffer = (UINT32*)Buffer + BIT0;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT16)) {
> > +    //
> > +    // Write the last remaining word if exist
> > +    //
> > +    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
> > +    StartAddress += sizeof (UINT16);
> > +    Size -= sizeof (UINT16);
> > +    Buffer = (UINT16*)Buffer + BIT0;
> > +  }
> > +
> > +  if (Size >= sizeof (UINT8)) {
> > +    //
> > +    // Write the last remaining byte if exist
> > +    //
> > +    PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer);  }
> > +
> > +  return ReturnValue;
> > +}
> > +
> > +EFI_STATUS
> > +PciSegLibInit (
> > +  IN EFI_HANDLE        ImageHandle,
> > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > +  )
> > +{
> > +  return EFI_SUCCESS;
> > +}
> >


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

* Re: [PATCH edk2-platforms 10/16] Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS Controller
  2020-05-22  9:36   ` Ard Biesheuvel
@ 2020-05-24 18:32     ` Wasim Khan (OSS)
  0 siblings, 0 replies; 42+ messages in thread
From: Wasim Khan (OSS) @ 2020-05-24 18:32 UTC (permalink / raw)
  To: Ard Biesheuvel, Wasim Khan (OSS), devel@edk2.groups.io,
	Meenakshi Aggarwal, Vabhav Sharma, Varun Sethi, leif@nuviainc.com,
	jon@solid-run.com



> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Sent: Friday, May 22, 2020 3:06 PM
> To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> leif@nuviainc.com; jon@solid-run.com
> Cc: Wasim Khan <wasim.khan@nxp.com>
> Subject: Re: [PATCH edk2-platforms 10/16] Silicon/NXP: PciSegmentLib: Add
> ECAM config support for PCIe LS Controller
> 
> On 5/22/20 1:02 AM, Wasim Khan wrote:
> > From: Wasim Khan <wasim.khan@nxp.com>
> >
> > PCIe Layerscape controller can be enabled for ECAM style configuration
> > access using CFG SHIFT Feature.
> >
> > Check for PcdPciCfgShiftEnable to decide the configuration access
> > scheme to be used with PCIe LS controller.
> >
> > Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> > ---
> >   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf |  3 +++
> >   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c   | 20
> ++++++++++++++++----
> >   2 files changed, 19 insertions(+), 4 deletions(-)
> >
> > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > index a36e79239b33..936213dc8a9d 100755
> > --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > @@ -30,3 +30,6 @@ [LibraryClasses]
> >
> >   [FixedPcd]
> >     gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
> > +
> > +[Pcd]
> > +  gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
> > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > index ecd36971b753..552a425c6832 100755
> > --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > @@ -34,6 +34,8 @@ typedef enum {
> >   #define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \
> >     ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0)
> >
> > +static BOOLEAN CfgShiftEnable;
> > +
> 
> This is a compile time constant, right? Please try to avoid using runtime
> read/write variables in that case, since it defeats the compiler's ability to
> remove code that is never executed.

We are initializing CfgShiftEnable with PcdPciCfgShiftEnable (dynamic PCD). 
We indent to enable/disable this support at run time so that without recompiling the firmware, we can turn on/off this feature.

> 
> 
> >   STATIC
> >   UINT64
> >   PciLsCfgTarget (
> > @@ -88,11 +90,20 @@ PciLsGetConfigBase (
> >   {
> >     UINT32 CfgAddr;
> >
> > -  CfgAddr = (UINT16)Offset;
> > -  if (Bus) {
> > -    return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF *
> Segment, Address, Segment, Bus, Offset);
> > +  if (CfgShiftEnable) {
> > +    CfgAddr = (UINT32)Address;
> > +    if (Bus) {
> > +      return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment +
> CfgAddr;
> > +    } else {
> > +      return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
> > +    }
> >     } else {
> > -    return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
> > +    CfgAddr = (UINT16)Offset;
> > +    if (Bus) {
> > +      return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF *
> Segment, Address, Segment, Bus, Offset);
> > +    } else {
> > +      return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
> > +    }
> >     }
> >   }
> >
> > @@ -608,5 +619,6 @@ PciSegLibInit (
> >     IN EFI_SYSTEM_TABLE  *SystemTable
> >     )
> >   {
> > +  CfgShiftEnable = CFG_SHIFT_ENABLE;
> >     return EFI_SUCCESS;
> >   }
> >


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

* Re: [PATCH edk2-platforms 11/16] Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller
  2020-05-22  9:38   ` Ard Biesheuvel
@ 2020-05-24 18:32     ` Wasim Khan (OSS)
  0 siblings, 0 replies; 42+ messages in thread
From: Wasim Khan (OSS) @ 2020-05-24 18:32 UTC (permalink / raw)
  To: Ard Biesheuvel, Wasim Khan (OSS), devel@edk2.groups.io,
	Meenakshi Aggarwal, Vabhav Sharma, Varun Sethi, leif@nuviainc.com,
	jon@solid-run.com



> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Sent: Friday, May 22, 2020 3:08 PM
> To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> leif@nuviainc.com; jon@solid-run.com
> Cc: Wasim Khan <wasim.khan@nxp.com>
> Subject: Re: [PATCH edk2-platforms 11/16] Silicon/NXP: PciSegmentLib: Add
> support PCIe LsGen4 Controller
> 
> On 5/22/20 1:02 AM, Wasim Khan wrote:
> > From: Wasim Khan <wasim.khan@nxp.com>
> >
> > PCIe Layerscape Gen4 controller is not ECAM complaint and have
> 
> compliant

OK

> 
> > different PCI config space region for bus 0 (Controller space) and
> > bus[0x1-0xff] on NXP SoCs.
> >
> > For config transactions for Bus0:
> >    - Config transaction address = PCIe controller address + offset
> >
> > For config transactions for Bus[0x1-0xff]:
> >    - PCIe IP requires target BDF to be written at bit[31:16] of PCIe
> >      outbound configuration window.
> >
> > PCIe LsGen4 controller uses paging mechanism to access registers.
> > To access PCIe CCSR registers which are above 3KB offset, page number
> > must be set in Bridge Control Register.
> >
> > Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> > Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> > ---
> >   .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  1 +
> >   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 60
> +++++++++++++++++++++-
> >   2 files changed, 60 insertions(+), 1 deletion(-)
> >
> > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > index 936213dc8a9d..d6d7ea6e3b6b 100755
> > --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > @@ -33,3 +33,4 @@ [FixedPcd]
> >
> >   [Pcd]
> >     gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable
> > +  gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl
> > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > index 552a425c6832..02a1525ef308 100755
> > --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > @@ -35,6 +35,58 @@ typedef enum {
> >     ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0)
> >
> >   static BOOLEAN CfgShiftEnable;
> > +static BOOLEAN PciLsGen4Ctrl;
> > +
> 
> Another compile time constant?

We are initializing PciLsGen4Ctrl with PcdPciLsGen4Ctrl (dynamic PCD).
Based on SoC version, PcdPciLsGen4Ctrl will be set to true for LSGen4 controller (default false). 
Support to update these PCDs will come later (Actual use case will be with LX2160 SoC).

> 
> > +STATIC
> > +VOID
> > +PcieCfgSetTarget (
> > +  IN EFI_PHYSICAL_ADDRESS Dbi,
> > +  IN UINT32 Target)
> > +{
> > +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_L(0), Target);
> > +    PciLsGen4Write32 ((UINTN)Dbi, PAB_AXI_AMAP_PEX_WIN_H(0), 0); }
> > +
> > +/**
> > +  Function to return PCIe Physical Address(PCIe view) or Controller
> > +  Address(CPU view) for NXP Layerscape Gen4 SoC
> > +
> > +  @param  Address Address passed from bus layer.
> > +  @param  Segment Segment number for Root Complex.
> > +  @param  Offset  Config space register offset.
> > +  @param  Bus     PCIe Bus number.
> > +
> > +  @return Return PCIe CPU or Controller address.
> > +
> > +**/
> > +STATIC
> > +UINT64
> > +PciLsGen4GetConfigBase (
> > +  IN  UINT64      Address,
> > +  IN  UINT16      Segment,
> > +  IN  UINT16      Offset,
> > +  IN  UINT8       Bus
> > +  )
> > +{
> > +  UINT32 Target;
> > +
> > +  if (Bus) {
> 
> Bus > 0
> 
> > +    Target = ((((Address >> 20) & 0xFF) << 24) |
> > +             (((Address >> 15) & 0x1F) << 19) |
> > +             (((Address >> 12) & 0x7) << 16));
> 
> Drop the outer ()
> 
> > +
> > +    PcieCfgSetTarget ((PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF* Segment),
> Target);
> > +    return PCI_SEG0_MMIO_MEMBASE + Offset + PCI_BASE_DIFF * Segment;
> > +  } else {
> > +      if (Offset < INDIRECT_ADDR_BNDRY) {
> > +        PciLsGen4SetPg (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment,
> 0);
> > +        return (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + Offset);
> > +      }
> > +      PciLsGen4SetPg (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment,
> OFFSET_TO_PAGE_IDX (Offset));
> > +      Offset = OFFSET_TO_PAGE_ADDR (Offset);
> > +      return (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment +
> > +Offset);
> > +  }
> > +}
> >
> >   STATIC
> >   UINT64
> > @@ -129,7 +181,12 @@ PciSegmentLibGetConfigBase (
> >     UINT8  Bus;
> >
> >     Bus = ((UINT32)Address >> 20) & 0xff;
> > -  return PciLsGetConfigBase (Address, Segment, Offset, Bus);
> > +
> > +  if (PciLsGen4Ctrl) {
> > +    return PciLsGen4GetConfigBase (Address, Segment, Offset, Bus);  }
> > + else {
> > +    return PciLsGetConfigBase (Address, Segment, Offset, Bus);  }
> >   }
> >
> >   /**
> > @@ -620,5 +677,6 @@ PciSegLibInit (
> >     )
> >   {
> >     CfgShiftEnable = CFG_SHIFT_ENABLE;
> > +  PciLsGen4Ctrl = PCI_LS_GEN4_CTRL;
> >     return EFI_SUCCESS;
> >   }
> >


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

* Re: [PATCH edk2-platforms 12/16] Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264
  2020-05-22  9:39   ` Ard Biesheuvel
@ 2020-05-24 18:32     ` Wasim Khan (OSS)
  0 siblings, 0 replies; 42+ messages in thread
From: Wasim Khan (OSS) @ 2020-05-24 18:32 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: devel@edk2.groups.io, Meenakshi Aggarwal, Vabhav Sharma,
	Varun Sethi, leif@nuviainc.com, jon@solid-run.com



> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Sent: Friday, May 22, 2020 3:10 PM
> To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> leif@nuviainc.com; jon@solid-run.com
> Cc: Wasim Khan <wasim.khan@nxp.com>
> Subject: Re: [PATCH edk2-platforms 12/16] Silicon/NXP: PciSegmentLib:
> LsGen4Ctrl: Add Workaround for A-011264
> 
> On 5/22/20 1:02 AM, Wasim Khan wrote:
> > From: Wasim Khan <wasim.khan@nxp.com>
> >
> > With PCIe LsGen4 controller, clearing the Bus Master Enable bit in
> > Command register blocks all outbound transactions to be sent out in RC
> > mode.
> >
> > According to PCI Express base specification, the Command register’s
> > Bus Master Enable bit of a PCI Express RC controller can only control
> > the forwarding of memory requests received at its root port in the
> > upstream direction. In other words, clearing the Bus Master Enable bit
> > must not block all outbound transactions to be sent out toward RC’s
> > downstream devices. Due to this erratum, when the Command register’s
> > Bus Master Enable bit is cleared, all the outbound transactions from
> > the device’s internal bus masters, including but not limited to
> > configuration read and write transactions, are terminated with the
> > slave error (SLVERR) response status on the PCI Express RC
> > controller’s internal AXI bus interface.
> >
> > Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> > ---
> >   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c | 17
> +++++++++++++++++
> >   1 file changed, 17 insertions(+)
> >
> > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > index 02a1525ef308..c3bc14820ea5 100755
> > --- a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > @@ -39,6 +39,21 @@ static BOOLEAN PciLsGen4Ctrl;
> >
> >   STATIC
> >   VOID
> > +PciLsGen4SetBusMaster (
> > +  IN EFI_PHYSICAL_ADDRESS Dbi
> > +  )
> > +{
> > +  UINT32 Val;
> > +
> > +  /* Make sure the Master Enable bit not cleared */
> 
> Please use // style comments

OK

> 
> > +  Val = PciLsGen4Read32 ((UINTN)Dbi, PCI_COMMAND_OFFSET);
> > +  if (!(Val & EFI_PCI_COMMAND_BUS_MASTER)) {
> > +    PciLsGen4Write32 ((UINTN)Dbi, PCI_COMMAND_OFFSET, Val |
> > +EFI_PCI_COMMAND_BUS_MASTER);
> > +  }
> > +}
> > +
> > +STATIC
> > +VOID
> >   PcieCfgSetTarget (
> >     IN EFI_PHYSICAL_ADDRESS Dbi,
> >     IN UINT32 Target)
> > @@ -71,6 +86,8 @@ PciLsGen4GetConfigBase (
> >     UINT32 Target;
> >
> >     if (Bus) {
> > +    PciLsGen4SetBusMaster (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF*
> > + Segment);
> > +
> 
> Can't we just set this once and never touch it? Or is that tricky?

Yes, it's a bit tricky . I checked that we are getting multiple calls when BusMaster is zero.
As per the Errata, we must ensure that Bus Master is never zero so I am always checking the Bus Master bit , and set to 1 , when zero.

> 
> 
> >       Target = ((((Address >> 20) & 0xFF) << 24) |
> >                (((Address >> 15) & 0x1F) << 19) |
> >                (((Address >> 12) & 0x7) << 16));
> >


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

* Re: [PATCH edk2-platforms 00/16] Add PCIe Support
  2020-05-22 10:58   ` Leif Lindholm
@ 2020-05-24 18:32     ` Wasim Khan (OSS)
  0 siblings, 0 replies; 42+ messages in thread
From: Wasim Khan (OSS) @ 2020-05-24 18:32 UTC (permalink / raw)
  To: Leif Lindholm, Ard Biesheuvel
  Cc: Wasim Khan (OSS), devel@edk2.groups.io, Meenakshi Aggarwal,
	Vabhav Sharma, Varun Sethi, jon@solid-run.com



> -----Original Message-----
> From: Leif Lindholm <leif@nuviainc.com>
> Sent: Friday, May 22, 2020 4:29 PM
> To: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Cc: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>; jon@solid-
> run.com; Wasim Khan <wasim.khan@nxp.com>
> Subject: Re: [PATCH edk2-platforms 00/16] Add PCIe Support
> 
> On Fri, May 22, 2020 at 11:46:07 +0200, Ard Biesheuvel wrote:
> > On 5/22/20 1:02 AM, Wasim Khan wrote:
> > > From: Wasim Khan <wasim.khan@nxp.com>
> > >
> > > Add PCIe Support for NXP Layerscape SoC which supports different
> > > PCIe controllers.
> > > Use generic PCIe drivers and wire up PciHostBridgeLib, PciSegmentLib
> > > and PciCpuIo2Dxe driver for controller specific implementation.
> > >
> >
> > Thanks. This is looking good. Please take a look at the feedback, and
> > give others some time to respond as well.
> >

Thank you so much Ard for your review and comments. 
I have incorporated all your comments and waiting to push the V2 once I close on the some open items. 


> > In the meantime, I think we can simply merge #14 and #16 right away
> > (unless Leif has any objections)
> 
> (Looking at those two out of order.)
> 16, sure.
> 14 - is there any reason to do so before there is PCI to connect network devices
> through?
> 
> /
>     Leif
> 
> >
> > > Wasim Khan (16):
> > >    Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs.
> > >    Silicon/NXP: LS1043A: Define PCIe related PCDs
> > >    Silicon/NXP: Implement PciHostBridgeLib support
> > >    Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS
> > >      Ctrl
> > >    Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU
> > >      Windows
> > >    Silicon/NXP: PciHostBridgeLib: add Workaround for A-011451
> > >    Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows
> > >    Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows
> > >    Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller
> > >    Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS
> > >      Controller
> > >    Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller
> > >    Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264
> > >    Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver
> > >    Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg
> > >    Platform/NXP: LS1043aRdbPkg: Enable PCIE support
> > >    Platform/NXP: LS1043aRdbPkg : Increase fv image size
> > >
> > >   Silicon/NXP/NxpQoriqLs.dec                         |  13 +
> > >   Silicon/NXP/LS1043A/LS1043A.dsc.inc                |   8 +
> > >   Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc       |  20 +
> > >   Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf       |  20 +-
> > >   Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf  |  40 +
> > >   .../Library/PciHostBridgeLib/PciHostBridgeLib.inf  |  45 ++
> > >   .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  36 +
> > >   Silicon/NXP/Include/Pcie.h                         | 231 ++++++
> > >   Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c    | 628
> +++++++++++++++
> > >   .../Library/PciHostBridgeLib/PciHostBridgeLib.c    | 842
> +++++++++++++++++++++
> > >   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 699
> +++++++++++++++++
> > >   11 files changed, 2579 insertions(+), 3 deletions(-)
> > >   create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf
> > >   create mode 100644
> Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> > >   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > >   create mode 100755 Silicon/NXP/Include/Pcie.h
> > >   create mode 100755 Silicon/NXP/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c
> > >   create mode 100644
> Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
> > >   create mode 100755
> > > Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > >
> >

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

* Re: [PATCH edk2-platforms 09/16] Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller
  2020-05-24 18:32     ` Wasim Khan (OSS)
@ 2020-05-25  4:30       ` Jon Nettleton
  2020-05-25 15:21         ` Wasim Khan (OSS)
  0 siblings, 1 reply; 42+ messages in thread
From: Jon Nettleton @ 2020-05-25  4:30 UTC (permalink / raw)
  To: Wasim Khan (OSS)
  Cc: Ard Biesheuvel, devel@edk2.groups.io, Meenakshi Aggarwal,
	Vabhav Sharma, Varun Sethi, leif@nuviainc.com

On Sun, May 24, 2020 at 8:32 PM Wasim Khan (OSS) <wasim.khan@oss.nxp.com> wrote:
>
>
>
> > -----Original Message-----
> > From: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Sent: Friday, May 22, 2020 3:00 PM
> > To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
> > Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> > <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> > leif@nuviainc.com; jon@solid-run.com
> > Cc: Wasim Khan <wasim.khan@nxp.com>
> > Subject: Re: [PATCH edk2-platforms 09/16] Silicon/NXP: Implement
> > PciSegmentLib for PCIe Layerscape Controller
> >
> > On 5/22/20 1:02 AM, Wasim Khan wrote:
> > > From: Wasim Khan <wasim.khan@nxp.com>
> > >
> > > We have different PCI config space region for bus 0 (Controller space)
> > > and bus[0x1-0xff] on NXP SoCs with PCIe LS controller.
> > > Add PciSegmentLib for PCIe LS controller.
> > >
> > > For config transactions for Bus0:
> > >    - Config transaction address = PCIe controller address + offset
> > >
> > > For config transactions for Bus[0x1-0xff]:
> > >    - PCIe IP requires target BDF to be written at bit[31:16] of PCIe
> > >      type0/type1 outbound window.
> > >    - Config transaction address = PCIe config space address + offset
> > >
> > > Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> > > Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> > > ---
> > >   .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  32 ++
> > >   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 612
> > +++++++++++++++++++++
> > >   2 files changed, 644 insertions(+)
> > >   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > >   create mode 100755 Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > >
> > > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > > new file mode 100755
> > > index 000000000000..a36e79239b33
> > > --- /dev/null
> > > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > > @@ -0,0 +1,32 @@
> > > +## @file
> > > +#  PCI Segment Library for NXP SoCs with multiple RCs # #  Copyright
> > > +2018-2020 NXP # #  SPDX-License-Identifier: BSD-2-Clause-Patent ##
> > > +
> > > +[Defines]
> > > +  INF_VERSION                    = 0x0001001A
> > > +  BASE_NAME                      = PciSegmentLib
> > > +  FILE_GUID                      = c9f59261-5a60-4a4c-82f6-1f520442e100
> > > +  MODULE_TYPE                    = DXE_DRIVER
> >
> > Can this be BASE ?
> >
>
> No, we need constructor function PciSegLibInit() which requires it to be DXE_DRIVER.
>
> > > +  VERSION_STRING                 = 1.0
> > > +  LIBRARY_CLASS                  = PciSegmentLib|DXE_DRIVER
> > > +  CONSTRUCTOR                    = PciSegLibInit
> > > +
> > > +[Sources]
> > > +  PciSegmentLib.c
> > > +
> > > +[Packages]
> > > +  MdePkg/MdePkg.dec
> > > +  Silicon/NXP/NxpQoriqLs.dec
> > > +
> > > +[LibraryClasses]
> > > +  BaseLib
> > > +  DebugLib
> > > +  IoLib
> > > +  PcdLib
> > > +
> > > +[FixedPcd]
> > > +  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
> > > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > > new file mode 100755
> > > index 000000000000..ecd36971b753
> > > --- /dev/null
> > > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > > @@ -0,0 +1,612 @@
> > > +/** @file
> > > +  PCI Segment Library for NXP SoCs with multiple RCs
> > > +
> > > +  Copyright 2018-2020 NXP
> > > +
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include <PiDxe.h>
> > > +#include <Base.h> #include <IndustryStandard/Pci22.h> #include
> > > +<Library/PciSegmentLib.h> #include <Library/BaseLib.h> #include
> > > +<Library/DebugLib.h> #include <Library/IoLib.h> #include
> > > +<Library/MemoryAllocationLib.h> #include <Library/PcdLib.h> #include
> > > +<Pcie.h>
> > > +
> > > +typedef enum {
> > > +  PciCfgWidthUint8      = 0,
> > > +  PciCfgWidthUint16,
> > > +  PciCfgWidthUint32,
> > > +  PciCfgWidthMax
> > > +} PCI_CFG_WIDTH;
> > > +
> > > +/**
> > > +  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)
> > > +
> > > +STATIC
> > > +UINT64
> > > +PciLsCfgTarget (
> > > +  IN  EFI_PHYSICAL_ADDRESS Dbi,
> > > +  IN  UINT64               Address,
> > > +  IN  UINT16               Segment,
> > > +  IN  UINT8                Bus,
> > > +  IN  UINT16               Offset
> > > +  )
> > > +{
> > > +  UINT32 Target;
> > > +
> > > +  Target = ((((Address >> 20) & 0xFF) << 24) |
> > > +           (((Address >> 15) & 0x1F) << 19) |
> > > +           (((Address >> 12) & 0x7) << 16));
> >
> > You can drop the outer () here
> >
>
> OK
>
> > > +
> > > +  if (Bus > 1) {
> > > +    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF,
> > > + IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX1);  } else {
> > > +    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF,
> > > + IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX0);  }
> > > +
> > > +  MmioWrite32 ((UINTN)Dbi +
> > IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> > > + Target);
> > > +
> > > +  if (Bus > 1) {
> > > +    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment +
> > > + SEG_CFG_SIZE + Offset;  } else {
> > > +    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment + Offset;
> > > + }
> >
> > OK, so this is the version for the IP that does not implement ECAM shift, right?
>
> No, PCIe Layerscape support both mechanism ECAM & Non-ECAM (with exception of bus 0).
> PCIe LSGen4 controller does not support ECAM at all , which is part of patch #11
>

Well this isn't completely true.  It doesn't support ECAM natively on
the controller, but it can be configured to represent a proper ECAM
view with the config shift model we are using on the Rev 2 silicon.  I
have a functional test patch, but that shouldn't be something to hold
up this patch set.  I will submit that work separately and we can
discuss the implementation at that time.

> >
> > > +}
> > > +
> > > +/**
> > > +  Function to return PCIe Physical Address(PCIe view) or Controller
> > > +  Address(CPU view) for different RCs
> > > +
> > > +  @param  Address Address passed from bus layer.
> > > +  @param  Segment Segment number for Root Complex.
> > > +  @param  Offset  Config space register offset.
> > > +  @param  Bus     PCIe Bus number.
> > > +
> > > +  @return Return PCIe CPU or Controller address.
> > > +
> > > +**/
> > > +STATIC
> > > +UINT64
> > > +PciLsGetConfigBase (
> > > +  IN  UINT64      Address,
> > > +  IN  UINT16      Segment,
> > > +  IN  UINT16      Offset,
> > > +  IN  UINT8       Bus
> > > +  )
> > > +{
> > > +  UINT32 CfgAddr;
> > > +
> > > +  CfgAddr = (UINT16)Offset;
> > > +  if (Bus) {
> >
> > Please use Bus > 0 here
>
> OK
>
> >
> > > +    return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF *
> > > +Segment, Address, Segment, Bus, Offset);
> > > +  } else {
> > > +    return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment + CfgAddr;
> > > +  }
> > > +}
> > > +
> > > +/**
> > > +  Function to return PCIe Physical Address(PCIe view) or Controller
> > > +  Address(CPU view) for different RCs
> > > +
> > > +  @param  Address Address passed from bus layer.
> > > +  @param  Segment Segment number for Root Complex.
> > > +  @param  Offset  Config space register offset.
> > > +
> > > +  @return Return PCIe CPU or Controller address.
> > > +
> > > +**/
> > > +STATIC
> > > +UINT64
> > > +PciSegmentLibGetConfigBase (
> > > +  IN  UINT64      Address,
> > > +  IN  UINT16      Segment,
> > > +  IN  UINT16      Offset
> > > +  )
> > > +{
> > > +  UINT8  Bus;
> > > +
> > > +  Bus = ((UINT32)Address >> 20) & 0xff;
> > > +  return PciLsGetConfigBase (Address, Segment, Offset, Bus); }
> > > +
> > > +/**
> > > +  Internal worker function to read a PCI configuration register.
> > > +
> > > +  @param  Address The address that encodes the Segment, 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;
> > > +  UINT16    Offset;
> > > +  UINT16    Segment;
> > > +
> > > +  Segment = (Address >> 32);
> > > +  Offset = (Address & 0xfff );
> > > +
> > > +  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
> > > +
> > > +  // ignore devices > 0 on bus 0
> > > +  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
> > > +    return MAX_UINT32;
> > > +  }
> > > +
> > > +  // ignore device > 0 on bus 1
> > > +  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
> > > +    return MAX_UINT32;
> > > +  }
> > > +
> > > +  switch (Width) {
> > > +  case PciCfgWidthUint8:
> > > +    return MmioRead8 (Base);
> > > +  case PciCfgWidthUint16:
> > > +    return MmioRead16 (Base);
> > > +  case PciCfgWidthUint32:
> > > +    return MmioRead32 (Base);
> > > +  default:
> > > +    ASSERT (FALSE);
> > > +  }
> > > +
> > > +  return CHAR_NULL;
> > > +}
> > > +
> > > +/**
> > > +  Internal worker function to writes a PCI configuration register.
> > > +
> > > +  @param  Address The address that encodes the Segment, 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;
> > > +  UINT32    Offset;
> > > +  UINT16    Segment;
> > > +
> > > +  Segment = (Address >> 32);
> > > +  Offset = (Address & 0xfff );
> > > +
> > > +  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
> > > +
> > > +  // ignore devices > 0 on bus 0
> > > +  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
> > > +    return Data;
> > > +  }
> > > +
> > > +  // ignore device > 0 on bus 1
> > > +  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
> > > +    return MAX_UINT32;
> > > +  }
> > > +
> > > +  switch (Width) {
> > > +  case PciCfgWidthUint8:
> > > +    MmioWrite8 (Base , Data);
> > > +    break;
> > > +  case PciCfgWidthUint16:
> > > +    MmioWrite16 (Base , Data);
> > > +    break;
> > > +  case PciCfgWidthUint32:
> > > +    MmioWrite32 (Base , Data);
> > > +    break;
> > > +  default:
> > > +    ASSERT (FALSE);
> > > +  }
> > > +
> > > +  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.
> > > +
> > > +  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); }
> > > +
> > > +/**
> > > +  Reads a 16-bit PCI configuration register.
> > > +
> > > +  Reads and returns 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().
> > > +
> > > +  @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.
> > > +
> > > +  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); }
> > > +
> > > +/**
> > > +  Reads a 32-bit PCI configuration register.
> > > +
> > > +  Reads and returns the 32-bit PCI configuration register specified by Address.
> > > +
> > > +  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.
> > > +
> > > +  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); }
> > > +
> > > +/**
> > > +  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.
> > > +
> > > +  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) <= SIZE_4KB);
> > > +
> > > +  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 + BIT0;
> > > +  }
> > > +
> > > +  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 + BIT0;
> > > +  }
> > > +
> > > +  while (Size >= sizeof (UINT32)) {
> > > +    //
> > > +    // Read as many double words as possible
> > > +    //
> > > +    WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));
> > > +    StartAddress += sizeof (UINT32);
> > > +    Size -= sizeof (UINT32);
> > > +    Buffer = (UINT32*)Buffer + BIT0;
> > > +  }
> > > +
> > > +  if (Size >= sizeof (UINT16)) {
> > > +    //
> > > +    // Read the last remaining word if exist
> > > +    //
> > > +    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
> > > +    StartAddress += sizeof (UINT16);
> > > +    Size -= sizeof (UINT16);
> > > +    Buffer = (UINT16*)Buffer + BIT0;
> > > +  }
> > > +
> > > +  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.
> > > +
> > > +  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) <= SIZE_4KB);
> > > +
> > > +  if (Size == 0) {
> > > +    return Size;
> > > +  }
> > > +
> > > +  ASSERT (Buffer != NULL);
> > > +
> > > +  //
> > > +  // 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 + BIT0;
> > > +  }
> > > +
> > > +  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 + BIT0;
> > > +  }
> > > +
> > > +  while (Size >= sizeof (UINT32)) {
> > > +    //
> > > +    // Write as many double words as possible
> > > +    //
> > > +    PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));
> > > +    StartAddress += sizeof (UINT32);
> > > +    Size -= sizeof (UINT32);
> > > +    Buffer = (UINT32*)Buffer + BIT0;
> > > +  }
> > > +
> > > +  if (Size >= sizeof (UINT16)) {
> > > +    //
> > > +    // Write the last remaining word if exist
> > > +    //
> > > +    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
> > > +    StartAddress += sizeof (UINT16);
> > > +    Size -= sizeof (UINT16);
> > > +    Buffer = (UINT16*)Buffer + BIT0;
> > > +  }
> > > +
> > > +  if (Size >= sizeof (UINT8)) {
> > > +    //
> > > +    // Write the last remaining byte if exist
> > > +    //
> > > +    PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer);  }
> > > +
> > > +  return ReturnValue;
> > > +}
> > > +
> > > +EFI_STATUS
> > > +PciSegLibInit (
> > > +  IN EFI_HANDLE        ImageHandle,
> > > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > > +  )
> > > +{
> > > +  return EFI_SUCCESS;
> > > +}
> > >
>

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

* Re: [PATCH edk2-platforms 09/16] Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller
  2020-05-25  4:30       ` Jon Nettleton
@ 2020-05-25 15:21         ` Wasim Khan (OSS)
  0 siblings, 0 replies; 42+ messages in thread
From: Wasim Khan (OSS) @ 2020-05-25 15:21 UTC (permalink / raw)
  To: Jon Nettleton, Wasim Khan (OSS)
  Cc: Ard Biesheuvel, devel@edk2.groups.io, Meenakshi Aggarwal,
	Vabhav Sharma, Varun Sethi, leif@nuviainc.com



> -----Original Message-----
> From: Jon Nettleton <jon@solid-run.com>
> Sent: Monday, May 25, 2020 10:00 AM
> To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>; devel@edk2.groups.io;
> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> leif@nuviainc.com
> Subject: Re: [PATCH edk2-platforms 09/16] Silicon/NXP: Implement
> PciSegmentLib for PCIe Layerscape Controller
> 
> On Sun, May 24, 2020 at 8:32 PM Wasim Khan (OSS)
> <wasim.khan@oss.nxp.com> wrote:
> >
> >
> >
> > > -----Original Message-----
> > > From: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > > Sent: Friday, May 22, 2020 3:00 PM
> > > To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
> > > Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
> > > <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
> > > leif@nuviainc.com; jon@solid-run.com
> > > Cc: Wasim Khan <wasim.khan@nxp.com>
> > > Subject: Re: [PATCH edk2-platforms 09/16] Silicon/NXP: Implement
> > > PciSegmentLib for PCIe Layerscape Controller
> > >
> > > On 5/22/20 1:02 AM, Wasim Khan wrote:
> > > > From: Wasim Khan <wasim.khan@nxp.com>
> > > >
> > > > We have different PCI config space region for bus 0 (Controller
> > > > space) and bus[0x1-0xff] on NXP SoCs with PCIe LS controller.
> > > > Add PciSegmentLib for PCIe LS controller.
> > > >
> > > > For config transactions for Bus0:
> > > >    - Config transaction address = PCIe controller address + offset
> > > >
> > > > For config transactions for Bus[0x1-0xff]:
> > > >    - PCIe IP requires target BDF to be written at bit[31:16] of PCIe
> > > >      type0/type1 outbound window.
> > > >    - Config transaction address = PCIe config space address +
> > > > offset
> > > >
> > > > Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> > > > Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> > > > ---
> > > >   .../NXP/Library/PciSegmentLib/PciSegmentLib.inf    |  32 ++
> > > >   Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c  | 612
> > > +++++++++++++++++++++
> > > >   2 files changed, 644 insertions(+)
> > > >   create mode 100755
> Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > > >   create mode 100755
> > > > Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > > >
> > > > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > > > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > > > new file mode 100755
> > > > index 000000000000..a36e79239b33
> > > > --- /dev/null
> > > > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.inf
> > > > @@ -0,0 +1,32 @@
> > > > +## @file
> > > > +#  PCI Segment Library for NXP SoCs with multiple RCs # #
> > > > +Copyright
> > > > +2018-2020 NXP # #  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +##
> > > > +
> > > > +[Defines]
> > > > +  INF_VERSION                    = 0x0001001A
> > > > +  BASE_NAME                      = PciSegmentLib
> > > > +  FILE_GUID                      = c9f59261-5a60-4a4c-82f6-1f520442e100
> > > > +  MODULE_TYPE                    = DXE_DRIVER
> > >
> > > Can this be BASE ?
> > >
> >
> > No, we need constructor function PciSegLibInit() which requires it to be
> DXE_DRIVER.
> >
> > > > +  VERSION_STRING                 = 1.0
> > > > +  LIBRARY_CLASS                  = PciSegmentLib|DXE_DRIVER
> > > > +  CONSTRUCTOR                    = PciSegLibInit
> > > > +
> > > > +[Sources]
> > > > +  PciSegmentLib.c
> > > > +
> > > > +[Packages]
> > > > +  MdePkg/MdePkg.dec
> > > > +  Silicon/NXP/NxpQoriqLs.dec
> > > > +
> > > > +[LibraryClasses]
> > > > +  BaseLib
> > > > +  DebugLib
> > > > +  IoLib
> > > > +  PcdLib
> > > > +
> > > > +[FixedPcd]
> > > > +  gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
> > > > diff --git a/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > > > b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > > > new file mode 100755
> > > > index 000000000000..ecd36971b753
> > > > --- /dev/null
> > > > +++ b/Silicon/NXP/Library/PciSegmentLib/PciSegmentLib.c
> > > > @@ -0,0 +1,612 @@
> > > > +/** @file
> > > > +  PCI Segment Library for NXP SoCs with multiple RCs
> > > > +
> > > > +  Copyright 2018-2020 NXP
> > > > +
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include
> > > > +<PiDxe.h> #include <Base.h> #include <IndustryStandard/Pci22.h>
> > > > +#include <Library/PciSegmentLib.h> #include <Library/BaseLib.h>
> > > > +#include <Library/DebugLib.h> #include <Library/IoLib.h> #include
> > > > +<Library/MemoryAllocationLib.h> #include <Library/PcdLib.h>
> > > > +#include <Pcie.h>
> > > > +
> > > > +typedef enum {
> > > > +  PciCfgWidthUint8      = 0,
> > > > +  PciCfgWidthUint16,
> > > > +  PciCfgWidthUint32,
> > > > +  PciCfgWidthMax
> > > > +} PCI_CFG_WIDTH;
> > > > +
> > > > +/**
> > > > +  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)
> > > > +
> > > > +STATIC
> > > > +UINT64
> > > > +PciLsCfgTarget (
> > > > +  IN  EFI_PHYSICAL_ADDRESS Dbi,
> > > > +  IN  UINT64               Address,
> > > > +  IN  UINT16               Segment,
> > > > +  IN  UINT8                Bus,
> > > > +  IN  UINT16               Offset
> > > > +  )
> > > > +{
> > > > +  UINT32 Target;
> > > > +
> > > > +  Target = ((((Address >> 20) & 0xFF) << 24) |
> > > > +           (((Address >> 15) & 0x1F) << 19) |
> > > > +           (((Address >> 12) & 0x7) << 16));
> > >
> > > You can drop the outer () here
> > >
> >
> > OK
> >
> > > > +
> > > > +  if (Bus > 1) {
> > > > +    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF,
> > > > + IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX1);  } else {
> > > > +    MmioWrite32 ((UINTN)Dbi + IATU_VIEWPORT_OFF,
> > > > + IATU_VIEWPORT_OUTBOUND | IATU_REGION_INDEX0);  }
> > > > +
> > > > +  MmioWrite32 ((UINTN)Dbi +
> > > IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> > > > + Target);
> > > > +
> > > > +  if (Bus > 1) {
> > > > +    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment +
> > > > + SEG_CFG_SIZE + Offset;  } else {
> > > > +    return PCI_SEG0_MMIO_MEMBASE + PCI_BASE_DIFF * Segment +
> > > > + Offset; }
> > >
> > > OK, so this is the version for the IP that does not implement ECAM shift,
> right?
> >
> > No, PCIe Layerscape support both mechanism ECAM & Non-ECAM (with
> exception of bus 0).
> > PCIe LSGen4 controller does not support ECAM at all , which is part of
> > patch #11
> >
> 
> Well this isn't completely true.  It doesn't support ECAM natively on the
> controller, but it can be configured to represent a proper ECAM view with the
> config shift model we are using on the Rev 2 silicon.  I have a functional test
> patch, but that shouldn't be something to hold up this patch set.  I will submit
> that work separately and we can discuss the implementation at that time.

Thanks Jon for brining this point. 
I meant ECAM support at controller level (HW) . Yes, will discuss the implementation. 

> 
> > >
> > > > +}
> > > > +
> > > > +/**
> > > > +  Function to return PCIe Physical Address(PCIe view) or
> > > > +Controller
> > > > +  Address(CPU view) for different RCs
> > > > +
> > > > +  @param  Address Address passed from bus layer.
> > > > +  @param  Segment Segment number for Root Complex.
> > > > +  @param  Offset  Config space register offset.
> > > > +  @param  Bus     PCIe Bus number.
> > > > +
> > > > +  @return Return PCIe CPU or Controller address.
> > > > +
> > > > +**/
> > > > +STATIC
> > > > +UINT64
> > > > +PciLsGetConfigBase (
> > > > +  IN  UINT64      Address,
> > > > +  IN  UINT16      Segment,
> > > > +  IN  UINT16      Offset,
> > > > +  IN  UINT8       Bus
> > > > +  )
> > > > +{
> > > > +  UINT32 CfgAddr;
> > > > +
> > > > +  CfgAddr = (UINT16)Offset;
> > > > +  if (Bus) {
> > >
> > > Please use Bus > 0 here
> >
> > OK
> >
> > >
> > > > +    return PciLsCfgTarget (PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF
> > > > +* Segment, Address, Segment, Bus, Offset);
> > > > +  } else {
> > > > +    return PCI_SEG0_DBI_BASE + PCI_DBI_SIZE_DIFF * Segment +
> > > > +CfgAddr;
> > > > +  }
> > > > +}
> > > > +
> > > > +/**
> > > > +  Function to return PCIe Physical Address(PCIe view) or
> > > > +Controller
> > > > +  Address(CPU view) for different RCs
> > > > +
> > > > +  @param  Address Address passed from bus layer.
> > > > +  @param  Segment Segment number for Root Complex.
> > > > +  @param  Offset  Config space register offset.
> > > > +
> > > > +  @return Return PCIe CPU or Controller address.
> > > > +
> > > > +**/
> > > > +STATIC
> > > > +UINT64
> > > > +PciSegmentLibGetConfigBase (
> > > > +  IN  UINT64      Address,
> > > > +  IN  UINT16      Segment,
> > > > +  IN  UINT16      Offset
> > > > +  )
> > > > +{
> > > > +  UINT8  Bus;
> > > > +
> > > > +  Bus = ((UINT32)Address >> 20) & 0xff;  return
> > > > + PciLsGetConfigBase (Address, Segment, Offset, Bus); }
> > > > +
> > > > +/**
> > > > +  Internal worker function to read a PCI configuration register.
> > > > +
> > > > +  @param  Address The address that encodes the Segment, 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;
> > > > +  UINT16    Offset;
> > > > +  UINT16    Segment;
> > > > +
> > > > +  Segment = (Address >> 32);
> > > > +  Offset = (Address & 0xfff );
> > > > +
> > > > +  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
> > > > +
> > > > +  // ignore devices > 0 on bus 0
> > > > +  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
> > > > +    return MAX_UINT32;
> > > > +  }
> > > > +
> > > > +  // ignore device > 0 on bus 1
> > > > +  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
> > > > +    return MAX_UINT32;
> > > > +  }
> > > > +
> > > > +  switch (Width) {
> > > > +  case PciCfgWidthUint8:
> > > > +    return MmioRead8 (Base);
> > > > +  case PciCfgWidthUint16:
> > > > +    return MmioRead16 (Base);
> > > > +  case PciCfgWidthUint32:
> > > > +    return MmioRead32 (Base);
> > > > +  default:
> > > > +    ASSERT (FALSE);
> > > > +  }
> > > > +
> > > > +  return CHAR_NULL;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Internal worker function to writes a PCI configuration register.
> > > > +
> > > > +  @param  Address The address that encodes the Segment, 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;
> > > > +  UINT32    Offset;
> > > > +  UINT16    Segment;
> > > > +
> > > > +  Segment = (Address >> 32);
> > > > +  Offset = (Address & 0xfff );
> > > > +
> > > > +  Base = PciSegmentLibGetConfigBase (Address, Segment, Offset);
> > > > +
> > > > +  // ignore devices > 0 on bus 0
> > > > +  if ((Address & 0xff00000) == 0 && (Address & 0xf8000) != 0) {
> > > > +    return Data;
> > > > +  }
> > > > +
> > > > +  // ignore device > 0 on bus 1
> > > > +  if ((Address & 0xfe00000) == 0 && (Address & 0xf8000) != 0) {
> > > > +    return MAX_UINT32;
> > > > +  }
> > > > +
> > > > +  switch (Width) {
> > > > +  case PciCfgWidthUint8:
> > > > +    MmioWrite8 (Base , Data);
> > > > +    break;
> > > > +  case PciCfgWidthUint16:
> > > > +    MmioWrite16 (Base , Data);
> > > > +    break;
> > > > +  case PciCfgWidthUint32:
> > > > +    MmioWrite32 (Base , Data);
> > > > +    break;
> > > > +  default:
> > > > +    ASSERT (FALSE);
> > > > +  }
> > > > +
> > > > +  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.
> > > > +
> > > > +  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); }
> > > > +
> > > > +/**
> > > > +  Reads a 16-bit PCI configuration register.
> > > > +
> > > > +  Reads and returns 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().
> > > > +
> > > > +  @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.
> > > > +
> > > > +  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); }
> > > > +
> > > > +/**
> > > > +  Reads a 32-bit PCI configuration register.
> > > > +
> > > > +  Reads and returns the 32-bit PCI configuration register specified by
> Address.
> > > > +
> > > > +  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.
> > > > +
> > > > +  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); }
> > > > +
> > > > +/**
> > > > +  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.
> > > > +
> > > > +  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) <= SIZE_4KB);
> > > > +
> > > > +  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 + BIT0;  }
> > > > +
> > > > +  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 + BIT0;  }
> > > > +
> > > > +  while (Size >= sizeof (UINT32)) {
> > > > +    //
> > > > +    // Read as many double words as possible
> > > > +    //
> > > > +    WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));
> > > > +    StartAddress += sizeof (UINT32);
> > > > +    Size -= sizeof (UINT32);
> > > > +    Buffer = (UINT32*)Buffer + BIT0;  }
> > > > +
> > > > +  if (Size >= sizeof (UINT16)) {
> > > > +    //
> > > > +    // Read the last remaining word if exist
> > > > +    //
> > > > +    WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
> > > > +    StartAddress += sizeof (UINT16);
> > > > +    Size -= sizeof (UINT16);
> > > > +    Buffer = (UINT16*)Buffer + BIT0;  }
> > > > +
> > > > +  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.
> > > > +
> > > > +  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) <= SIZE_4KB);
> > > > +
> > > > +  if (Size == 0) {
> > > > +    return Size;
> > > > +  }
> > > > +
> > > > +  ASSERT (Buffer != NULL);
> > > > +
> > > > +  //
> > > > +  // 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 + BIT0;  }
> > > > +
> > > > +  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 + BIT0;  }
> > > > +
> > > > +  while (Size >= sizeof (UINT32)) {
> > > > +    //
> > > > +    // Write as many double words as possible
> > > > +    //
> > > > +    PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));
> > > > +    StartAddress += sizeof (UINT32);
> > > > +    Size -= sizeof (UINT32);
> > > > +    Buffer = (UINT32*)Buffer + BIT0;  }
> > > > +
> > > > +  if (Size >= sizeof (UINT16)) {
> > > > +    //
> > > > +    // Write the last remaining word if exist
> > > > +    //
> > > > +    PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
> > > > +    StartAddress += sizeof (UINT16);
> > > > +    Size -= sizeof (UINT16);
> > > > +    Buffer = (UINT16*)Buffer + BIT0;  }
> > > > +
> > > > +  if (Size >= sizeof (UINT8)) {
> > > > +    //
> > > > +    // Write the last remaining byte if exist
> > > > +    //
> > > > +    PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer);  }
> > > > +
> > > > +  return ReturnValue;
> > > > +}
> > > > +
> > > > +EFI_STATUS
> > > > +PciSegLibInit (
> > > > +  IN EFI_HANDLE        ImageHandle,
> > > > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > > > +  )
> > > > +{
> > > > +  return EFI_SUCCESS;
> > > > +}
> > > >
> >

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

* Re: [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs.
  2020-05-24 18:31     ` Wasim Khan (OSS)
@ 2020-05-26  6:16       ` Ard Biesheuvel
  0 siblings, 0 replies; 42+ messages in thread
From: Ard Biesheuvel @ 2020-05-26  6:16 UTC (permalink / raw)
  To: Wasim Khan (OSS)
  Cc: devel@edk2.groups.io, Meenakshi Aggarwal, Vabhav Sharma,
	Varun Sethi, leif@nuviainc.com, jon@solid-run.com

On 5/24/20 8:31 PM, Wasim Khan (OSS) wrote:
> 
> 
>> -----Original Message-----
>> From: Ard Biesheuvel <ard.biesheuvel@arm.com>
>> Sent: Friday, May 22, 2020 2:42 PM
>> To: Wasim Khan (OSS) <wasim.khan@oss.nxp.com>; devel@edk2.groups.io;
>> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Vabhav Sharma
>> <vabhav.sharma@nxp.com>; Varun Sethi <V.Sethi@nxp.com>;
>> leif@nuviainc.com; jon@solid-run.com
>> Cc: Wasim Khan <wasim.khan@nxp.com>
>> Subject: Re: [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add
>> PCIe related PCDs.
>>
>> On 5/22/20 1:02 AM, Wasim Khan wrote:
>>> From: Wasim Khan <wasim.khan@nxp.com>
>>>
>>> Add PCIe related PCDs.
>>>
>>> Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
>>
>> Please drop this signoff. This is not the correct way to acknowledge (co-
>> )authorship.
> 
> Co-authored-by: Vabhav Sharma <vabhav.sharma@nxp.com>
> Co-authored-by: Wasim Khan <wasim.khan@nxp.com>
> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
> 
> Is this OK ?
> 

Yes that is fine.

>>
>>> Signed-off-by: Wasim Khan <wasim.khan@nxp.com>
>>> ---
>>>    Silicon/NXP/NxpQoriqLs.dec | 9 +++++++++
>>>    1 file changed, 9 insertions(+)
>>>
>>> diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
>>> index 0722f59ef4f6..bafdfd9f4298 100644
>>> --- a/Silicon/NXP/NxpQoriqLs.dec
>>> +++ b/Silicon/NXP/NxpQoriqLs.dec
>>> @@ -27,3 +27,12 @@ [Guids.common]
>>>    [PcdsFeatureFlag]
>>>
>> gNxpQoriqLsTokenSpaceGuid.PcdI2cErratumA009203|FALSE|BOOLEAN|0x0000
>> 0315
>>>
>>>
>> gNxpQoriqLsTokenSpaceGuid.PcdDcfgBigEndian|FALSE|BOOLEAN|0x00000316
>>> +
>>> +
>> gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian|FALSE|BOOLEAN|0x0000031
>>> + 7
>>> +
>>> +[PcdsFixedAtBuild.common]
>>> +  # Pcds for PCI Express
>>> +
>> gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr|0x0|UINT64|0x00000500
>>> +  gNxpQoriqLsTokenSpaceGuid.PcdNumPciController|0|UINT32|0x00000501
>>> +  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase|0x0|UINT32|0x00000502
>>> +  gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg|0x0|UINT32|0x00000503
>>> +  gNxpQoriqLsTokenSpaceGuid.PcdPciDebug|FALSE|BOOLEAN|0x00000504
>>>
> 


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

end of thread, other threads:[~2020-05-26  6:16 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-21 23:02 [PATCH edk2-platforms 00/16] Add PCIe Support Wasim Khan
2020-05-21 23:02 ` [PATCH edk2-platforms 01/16] Silicon/NXP/NxpQoriqLs.dec: Add PCIe related PCDs Wasim Khan
2020-05-22  9:12   ` Ard Biesheuvel
2020-05-24 18:31     ` Wasim Khan (OSS)
2020-05-26  6:16       ` Ard Biesheuvel
2020-05-21 23:02 ` [PATCH edk2-platforms 02/16] Silicon/NXP: LS1043A: Define " Wasim Khan
2020-05-21 23:02 ` [PATCH edk2-platforms 03/16] Silicon/NXP: Implement PciHostBridgeLib support Wasim Khan
2020-05-22  9:20   ` Ard Biesheuvel
2020-05-21 23:02 ` [PATCH edk2-platforms 04/16] Silicon/NXP: PciHostBridgeLib: CFG Shift feature support for PCIeLS Ctrl Wasim Khan
2020-05-22  9:22   ` Ard Biesheuvel
2020-05-21 23:02 ` [PATCH edk2-platforms 05/16] Silicon/NXP: PciHostBridgeLib: Setup PCIe LsGen4 Controller and ATU Windows Wasim Khan
2020-05-22  9:24   ` Ard Biesheuvel
2020-05-24 18:31     ` Wasim Khan (OSS)
2020-05-21 23:02 ` [PATCH edk2-platforms 06/16] Silicon/NXP: PciHostBridgeLib: add Workaround for A-011451 Wasim Khan
2020-05-21 23:02 ` [PATCH edk2-platforms 07/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale Gen4 ATU windows Wasim Khan
2020-05-22  9:33   ` Ard Biesheuvel
2020-05-21 23:02 ` [PATCH edk2-platforms 08/16] Silicon/NXP: PciHostBridgeLib: Dump Layerscale iATU windows Wasim Khan
2020-05-22  9:31   ` Ard Biesheuvel
2020-05-21 23:02 ` [PATCH edk2-platforms 09/16] Silicon/NXP: Implement PciSegmentLib for PCIe Layerscape Controller Wasim Khan
2020-05-22  9:29   ` Ard Biesheuvel
2020-05-24 18:32     ` Wasim Khan (OSS)
2020-05-25  4:30       ` Jon Nettleton
2020-05-25 15:21         ` Wasim Khan (OSS)
2020-05-21 23:02 ` [PATCH edk2-platforms 10/16] Silicon/NXP: PciSegmentLib: Add ECAM config support for PCIe LS Controller Wasim Khan
2020-05-22  9:36   ` Ard Biesheuvel
2020-05-24 18:32     ` Wasim Khan (OSS)
2020-05-21 23:02 ` [PATCH edk2-platforms 11/16] Silicon/NXP: PciSegmentLib: Add support PCIe LsGen4 Controller Wasim Khan
2020-05-22  9:38   ` Ard Biesheuvel
2020-05-24 18:32     ` Wasim Khan (OSS)
2020-05-21 23:02 ` [PATCH edk2-platforms 12/16] Silicon/NXP: PciSegmentLib: LsGen4Ctrl: Add Workaround for A-011264 Wasim Khan
2020-05-22  9:39   ` Ard Biesheuvel
2020-05-24 18:32     ` Wasim Khan (OSS)
2020-05-21 23:02 ` [PATCH edk2-platforms 13/16] Silicon/NXP/Drivers: Implement PciCpuIo2Dxe Driver Wasim Khan
2020-05-22  9:42   ` Ard Biesheuvel
2020-05-21 23:02 ` [PATCH edk2-platforms 14/16] Platform/NXP: LS1043aRdbPkg: Enable NetworkPkg Wasim Khan
2020-05-22  9:42   ` Ard Biesheuvel
2020-05-21 23:02 ` [PATCH edk2-platforms 15/16] Platform/NXP: LS1043aRdbPkg: Enable PCIE support Wasim Khan
2020-05-21 23:02 ` [PATCH edk2-platforms 16/16] Platform/NXP: LS1043aRdbPkg : Increase fv image size Wasim Khan
2020-05-22  9:44   ` Ard Biesheuvel
2020-05-22  9:46 ` [PATCH edk2-platforms 00/16] Add PCIe Support Ard Biesheuvel
2020-05-22 10:58   ` Leif Lindholm
2020-05-24 18:32     ` Wasim Khan (OSS)

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