[edk2-devel] [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib

Leif Lindholm leif.lindholm at linaro.org
Fri May 10 15:50:20 UTC 2019


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

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

>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c            | 244 +++++++++++++++
>  Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c | 330 ++++++++++++++++++++
>  4 files changed, 721 insertions(+)
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
>  create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> 
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> new file mode 100644
> index 0000000..e46f71d
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf
> @@ -0,0 +1,52 @@
> +## @file
> +#  PCI Host Bridge Library instance for Marvell Armada 7k/8k SOC
> +#
> +#  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +#  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials are licensed and made available
> +#  under the terms and conditions of the BSD License which accompanies this
> +#  distribution. The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
> +#  IMPLIED.
> +#
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = Armada7k8kPciHostBridgeLib
> +  FILE_GUID                      = 7f989c9d-02a0-4348-8aeb-ab2e1566fb18
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciHostBridgeLib|DXE_DRIVER
> +  CONSTRUCTOR                    = Armada7k8kPciHostBridgeLibConstructor
> +
> +[Sources]
> +  PciHostBridgeLib.c
> +  PciHostBridgeLibConstructor.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Marvell/Marvell.dec
> +
> +[LibraryClasses]
> +  ArmLib
> +  ArmadaSoCDescLib
> +  DebugLib
> +  DevicePathLib
> +  MemoryAllocationLib
> +  MvGpioLib
> +  UefiBootServicesTableLib
> +
> +[Protocols]
> +  gEmbeddedGpioProtocolGuid
> +  gMarvellBoardDescProtocolGuid
> +
> +[Depex]
> +  gMarvellPlatformInitCompleteProtocolGuid
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> new file mode 100644
> index 0000000..ff9d919
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h
> @@ -0,0 +1,95 @@
> +/** @file
> +  PCI Host Bridge Library instance for Marvell 70x0/80x0
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  This program and the accompanying materials are licensed and made available
> +  under the terms and conditions of the BSD License which accompanies this
> +  distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php.
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
> +  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +#ifndef __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
> +#define __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__
> +
> +#define IATU_VIEWPORT_OFF                                   0x900
> +#define IATU_VIEWPORT_INBOUND                               BIT31
> +#define IATU_VIEWPORT_OUTBOUND                              0
> +#define IATU_VIEWPORT_REGION_INDEX(Idx)                     ((Idx) & 7)
> +
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0                   0x904
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM          0x0
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO           0x2
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0         0x4
> +#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1         0x5
> +
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0                   0x908
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN         BIT31
> +#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE    BIT28
> +
> +#define IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0                   0x90C
> +#define IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0                 0x910
> +#define IATU_LIMIT_ADDR_OFF_OUTBOUND_0                      0x914
> +#define IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0                 0x918
> +#define IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0               0x91C
> +
> +#define PORT_LINK_CTRL_OFF                                  0x710
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x1                  (0x01 << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x2                  (0x03 << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4                  (0x07 << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x8                  (0x0f << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x16                 (0x1f << 16)
> +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK                (0x3f << 16)
> +
> +#define GEN2_CTRL_OFF                                       0x80c
> +#define GEN2_CTRL_OFF_NUM_OF_LANES(n)                       (((n) & 0x1f) << 8)
> +#define GEN2_CTRL_OFF_NUM_OF_LANES_MASK                     (0x1f << 8)
> +#define GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE                   BIT17
> +
> +#define PCIE_GLOBAL_CTRL_OFFSET                             0x8000
> +#define PCIE_GLOBAL_APP_LTSSM_EN                            BIT2
> +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC                     (0x4 << 4)
> +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK                   (0xF << 4)
> +
> +#define PCIE_GLOBAL_STATUS_REG                              0x8008
> +#define PCIE_GLOBAL_STATUS_RDLH_LINK_UP                     BIT1
> +#define PCIE_GLOBAL_STATUS_PHY_LINK_UP                      BIT9
> +
> +#define PCIE_PM_STATUS                                      0x8014
> +#define PCIE_PM_LTSSM_STAT_MASK                             (0x3f << 3)
> +
> +#define PCIE_GLOBAL_INT_MASK1_REG                           0x8020
> +#define PCIE_INT_A_ASSERT_MASK                              BIT9
> +#define PCIE_INT_B_ASSERT_MASK                              BIT10
> +#define PCIE_INT_C_ASSERT_MASK                              BIT11
> +#define PCIE_INT_D_ASSERT_MASK                              BIT12
> +
> +#define PCIE_ARCACHE_TRC_REG                                0x8050
> +#define PCIE_AWCACHE_TRC_REG                                0x8054
> +#define PCIE_ARUSER_REG                                     0x805C
> +#define PCIE_AWUSER_REG                                     0x8060
> +
> +#define ARCACHE_DEFAULT_VALUE                               0x3511
> +#define AWCACHE_DEFAULT_VALUE                               0x5311
> +
> +#define AX_USER_DOMAIN_INNER_SHAREABLE                      (0x1 << 4)
> +#define AX_USER_DOMAIN_OUTER_SHAREABLE                      (0x2 << 4)
> +#define AX_USER_DOMAIN_MASK                                 (0x3 << 4)
> +
> +#define PCIE_LINK_CAPABILITY                                0x7C
> +#define PCIE_LINK_CTL_2                                     0xA0
> +#define TARGET_LINK_SPEED_MASK                              0xF
> +#define LINK_SPEED_GEN_1                                    0x1
> +#define LINK_SPEED_GEN_2                                    0x2
> +#define LINK_SPEED_GEN_3                                    0x3
> +
> +#define PCIE_GEN3_EQU_CTRL                                  0x8A8
> +#define GEN3_EQU_EVAL_2MS_DISABLE                           BIT5
> +
> +#define PCIE_LINK_UP_TIMEOUT_US                             40000
> +
> +#endif
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
> new file mode 100644
> index 0000000..ff6288c
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c
> @@ -0,0 +1,244 @@
> +/** @file
> +  PCI Host Bridge Library instance for Marvell Armada 70x0/80x0
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  This program and the accompanying materials are licensed and made available
> +  under the terms and conditions of the BSD License which accompanies this
> +  distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php.
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
> +  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +#include <PiDxe.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/BoardDesc.h>
> +#include <Protocol/PciHostBridgeResourceAllocation.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +
> +#pragma pack(1)
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH     AcpiDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
> +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
> +#pragma pack ()
> +
> +STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
> +  {
> +    {
> +      ACPI_DEVICE_PATH,
> +      ACPI_DP,
> +      {
> +        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
> +        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)

Drop space after (UINT8), x2.

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

Space before (.

> +    0
> +  },
> +
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      END_DEVICE_PATH_LENGTH,
> +      0
> +    }
> +  }
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> +  L"Mem", L"I/O", L"Bus"
> +};
> +
> +/**
> +  Return all the root bridge instances in an array.
> +
> +  @param Count  Return the count of root bridge instances.
> +
> +  @return All the root bridge instances in an array.
> +          The array should be passed into PciHostBridgeFreeRootBridges()
> +          when it's not used.
> +
> +**/
> +PCI_ROOT_BRIDGE *
> +EFIAPI
> +PciHostBridgeGetRootBridges (
> +  UINTN *Count
> +  )
> +{
> +  MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol;
> +  MV_BOARD_PCIE_DESCRIPTION   *BoardPcieDescription;
> +  MV_PCIE_CONTROLLER          *PcieController;
> +  PCI_ROOT_BRIDGE             *PciRootBridges;
> +  PCI_ROOT_BRIDGE             *RootBridge;
> +  EFI_STATUS                   Status;
> +  UINTN                        Index;
> +
> +  *Count = 0;
> +
> +  /* Obtain list of available controllers */
> +  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
> +                  NULL,
> +                  (VOID **)&BoardDescriptionProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot locate BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  Status = BoardDescriptionProtocol->PcieDescriptionGet (
> +                                       BoardDescriptionProtocol,
> +                                       &BoardPcieDescription);
> +  if (Status == EFI_NOT_FOUND) {
> +    /* No controllers used on the platform, exit silently */
> +    return NULL;
> +  } else if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot get Pcie board desc from BoardDesc protocol\n",
> +      __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  /* Assign return values */
> +  PciRootBridges = AllocateZeroPool (BoardPcieDescription->PcieControllerCount *
> +                                     sizeof (PCI_ROOT_BRIDGE));
> +  if (PciRootBridges == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a: Fail to allocate resources\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  *Count = BoardPcieDescription->PcieControllerCount;
> +  RootBridge = PciRootBridges;
> +
> +  /* Fill information of all root bridge instances */
> +  for (Index = 0; Index < *Count; Index++, RootBridge++) {
> +
> +    PcieController = &(BoardPcieDescription->PcieControllers[Index]);
> +
> +    RootBridge->Segment   = 0;
> +    RootBridge->Supports  = 0;
> +    RootBridge->Attributes  = RootBridge->Supports;
> +
> +    RootBridge->DmaAbove4G  = FALSE;
> +
> +    RootBridge->AllocationAttributes  = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |
> +                                        EFI_PCI_HOST_BRIDGE_MEM64_DECODE;
> +
> +    RootBridge->Bus.Base = PcieController->PcieBusMin;
> +    RootBridge->Bus.Limit = PcieController->PcieBusMax;
> +    RootBridge->Io.Base = PcieController->PcieIoWinBase;
> +    RootBridge->Io.Limit = PcieController->PcieIoWinBase +
> +                           PcieController->PcieIoWinSize - 1;
> +    RootBridge->Mem.Base = PcieController->PcieMmio32WinBase;
> +    RootBridge->Mem.Limit = PcieController->PcieMmio32WinBase +
> +                            PcieController->PcieMmio32WinSize - 1;
> +    RootBridge->MemAbove4G.Base = PcieController->PcieMmio64WinBase;
> +    RootBridge->MemAbove4G.Limit = PcieController->PcieMmio64WinBase +
> +                                   PcieController->PcieMmio64WinSize - 1;
> +
> +    /* No separate ranges for prefetchable and non-prefetchable BARs */
> +    RootBridge->PMem.Base           = MAX_UINT64;
> +    RootBridge->PMem.Limit          = 0;
> +    RootBridge->PMemAbove4G.Base    = MAX_UINT64;
> +    RootBridge->PMemAbove4G.Limit   = 0;
> +
> +    ASSERT (PcieController->PcieMmio64Translation == 0);
> +    ASSERT (PcieController->PcieMmio32Translation == 0);
> +
> +    RootBridge->NoExtendedConfigSpace = FALSE;
> +
> +    RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath;
> +  }
> +
> +  return PciRootBridges;
> +}
> +
> +/**
> +  Free the root bridge instances array returned from PciHostBridgeGetRootBridges().
> +
> +  @param Bridges The root bridge instances array.
> +  @param Count   The count of the array.
> +
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeFreeRootBridges (
> +  PCI_ROOT_BRIDGE *Bridges,
> +  UINTN           Count
> +  )
> +{
> +  FreePool (Bridges);
> +}
> +
> +/**
> +  Inform the platform that the resource conflict happens.
> +
> +  @param HostBridgeHandle Handle of the Host Bridge.
> +  @param Configuration    Pointer to PCI I/O and PCI memory resource
> +                          descriptors. The Configuration contains the resources
> +                          for all the root bridges. The resource for each root
> +                          bridge is terminated with END descriptor and an
> +                          additional END is appended indicating the end of the
> +                          entire resources. The resource descriptor field
> +                          values follow the description in
> +                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
> +                          .SubmitResources().
> +
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeResourceConflict (
> +  EFI_HANDLE                        HostBridgeHandle,
> +  VOID                              *Configuration
> +  )
> +{
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
> +  UINTN                              RootBridgeIndex;
> +
> +  DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
> +
> +  RootBridgeIndex = 0;
> +  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;

Drop space after "*)".

> +
> +  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> +
> +    DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
> +
> +    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
> +      ASSERT (Descriptor->ResType <
> +              (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /
> +               sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])));
> +
> +      DEBUG ((DEBUG_ERROR,
> +        " %s: Length/Alignment = 0x%lx / 0x%lx\n",
> +        mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
> +        Descriptor->AddrLen, Descriptor->AddrRangeMax));
> +
> +      if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
> +        DEBUG ((DEBUG_ERROR,
> +          "     Granularity/SpecificFlag = %ld / %02x%s\n",
> +          Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
> +          ((Descriptor->SpecificFlag &
> +            EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) ?
> +            L" (Prefetchable)" : L""));

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

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

> +      }
> +    }
> +    /* Skip the END descriptor for root bridge */
> +    ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
> +    Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
> +                  (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1);
> +  }
> +}
> diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> new file mode 100644
> index 0000000..ced2c12
> --- /dev/null
> +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c
> @@ -0,0 +1,330 @@
> +/** @file
> +  PCI Host Bridge Library instance for Marvell 70x0/80x0
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +  Copyright (c) 2019 Marvell International Ltd. All rights reserved.<BR>
> +
> +  This program and the accompanying materials are licensed and made available
> +  under the terms and conditions of the BSD License which accompanies this
> +  distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php.
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
> +  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Pci22.h>
> +
> +#include <Library/ArmLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MvGpioLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/BoardDesc.h>
> +
> +#include "PciHostBridgeLibConstructor.h"
> +
> +/**
> +  This function configures PCIE controllers IATU windows.
> +
> +  @param [in] PcieBaseAddress PCIE controller base address.
> +  @param [in] Index           IATU window index.
> +  @param [in] CpuBase         Address from the CPU perspective.
> +  @param [in] PciBase         Target PCIE address.
> +  @param [in] Size            IATU window size.
> +  @param [in] Type            IATU window type.
> +  @param [in] EnableFlags     Extra configuration flags.
> +
> +  @retval none
> +
> +**/
> +STATIC
> +VOID
> +ConfigureWindow (
> +  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress,
> +  IN UINTN                Index,
> +  IN UINT64               CpuBase,
> +  IN UINT64               PciBase,
> +  IN UINT64               Size,
> +  IN UINTN                Type,
> +  IN UINTN                EnableFlags
> +  )
> +{
> +  ArmDataMemoryBarrier ();
> +
> +  MmioWrite32 (PcieBaseAddress + IATU_VIEWPORT_OFF,
> +    IATU_VIEWPORT_OUTBOUND | IATU_VIEWPORT_REGION_INDEX (Index));
> +
> +  ArmDataMemoryBarrier ();
> +
> +  MmioWrite32 (PcieBaseAddress + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(CpuBase & 0xFFFFFFFF));
> +  MmioWrite32 (PcieBaseAddress + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(CpuBase >> 32));
> +  MmioWrite32 (PcieBaseAddress + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(CpuBase + Size - 1));
> +  MmioWrite32 (PcieBaseAddress + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(PciBase & 0xFFFFFFFF));
> +  MmioWrite32 (PcieBaseAddress + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
> +    (UINT32)(PciBase >> 32));
> +  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
> +    Type);
> +  MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
> +    IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN | EnableFlags);
> +}
> +
> +/**
> +  Perform PCIE slot reset using external GPIO pin.
> +
> +  @param [in] PcieBaseAddress  PCIE controller base address.
> +
> +  @retval none
> +
> +**/
> +STATIC
> +VOID
> +WaitForLink (
> +  IN EFI_PHYSICAL_ADDRESS PcieBaseAddress
> +  )
> +{
> +  UINT32 Mask;
> +  UINT32 Status;
> +  UINT32 Timeout;
> +
> +  if (!(MmioRead32 (PcieBaseAddress + PCIE_PM_STATUS) & PCIE_PM_LTSSM_STAT_MASK)) {
> +    DEBUG ((DEBUG_INIT, "%a: no PCIE device detected\n", __FUNCTION__));
> +    return;
> +  }
> +
> +  /* Wait for the link to establish itself */
> +  DEBUG ((DEBUG_INIT, "%a: waiting for PCIE link\n", __FUNCTION__));
> +
> +  Mask = PCIE_GLOBAL_STATUS_RDLH_LINK_UP | PCIE_GLOBAL_STATUS_PHY_LINK_UP;
> +  Timeout = PCIE_LINK_UP_TIMEOUT_US / 10;
> +  do {
> +    Status = MmioRead32 (PcieBaseAddress + PCIE_GLOBAL_STATUS_REG);
> +    if ((Status & Mask) == Mask) {
> +      DEBUG ((DEBUG_ERROR, "pcie at 0x%x link UP\n", PcieBaseAddress));
> +      break;
> +    }
> +    gBS->Stall (10);

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

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

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

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

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

/
    Leif

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

-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#40445): https://edk2.groups.io/g/devel/message/40445
Mute This Topic: https://groups.io/mt/31553480/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list