From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=pass header.i=@semihalf-com.20150623.gappssmtp.com header.s=20150623 header.b=JxhDe1Ss; spf=none, err=SPF record not found (domain: semihalf.com, ip: 209.85.208.196, mailfrom: mw@semihalf.com) Received: from mail-lj1-f196.google.com (mail-lj1-f196.google.com [209.85.208.196]) by groups.io with SMTP; Fri, 24 May 2019 08:59:40 -0700 Received: by mail-lj1-f196.google.com with SMTP id h19so717903ljj.4 for ; Fri, 24 May 2019 08:59:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=roSwxb/j/H5R6rXyk6sO8Iz8S3y/Nj/yHTphpXHEHrQ=; b=JxhDe1SsC/qVHlJ164S1d8lEA7EhXj/uX3/mOJ98T0sNrZQeVgWylk6wCQvzrWw/Hi MFt79jBq5csKqaQ8r7PgEEJ4EAHcFVKSibDqreXkc20ai5jWkewnlYhPbID2kotonf+n 7xryWJTYSZhDQ6SW2z3pHndIOQzE9x51ha5TJ6RwPsA+ni4nY0XSXs36ym/Dia81Zt1W 5IPPbolaWxhOr4ayAoAxNqcK7Km1iibwC5Id+mBv8dNDUTP2JYRVCIP/w1bGBSS5ePE7 W3dL8b5s7wmClSghcYJLQpto7fvNKDHO6KF6XR7lzYPEZ/5g47a3DsHU0Rz3/HQv56G5 E0vQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=roSwxb/j/H5R6rXyk6sO8Iz8S3y/Nj/yHTphpXHEHrQ=; b=oRQOYMvYWsDIvu31+dPVFtXVLi3/gfu979CfxA4yMjAtuxO7Vkymq60behDpPL8nar 3DJHv2aGaXxPg5nwGaxd0fJ/gy220xnfQn7mzZv3Upw2ZOFr4s2WqVE6+8ikUZSjpoHy 1XKAPFuxoWxnNOdb1QRxhL6wwhGJYZBfkq7AQD6nM5FJf5vkvycTEBs4iPlbmRh/ubA6 dRaHglzIKxzl4irNqzrK+A3eTphTfJS1KKI7hXhee8V5j7fxq8US4lf+f826Pt4mBliu XzyVkvQy/L20ZluboGY6fMvpUF2v2oyJD5S9yH2BZUPHe2QIYthOVlL3pzwBKBQ22Hpo 7gDA== X-Gm-Message-State: APjAAAXjXBwwYgdMFJK8eeDRRR/mYCDcyHCA+NWP15NW4zsO8NoMDwUl oFvcyxabHhasicMTyt/NFyNaFIzPG3j/Ag== X-Google-Smtp-Source: APXvYqz6F/ddaHdNKUgLGVdVB8C+omX/jODYgt0F6cqxvJU5TYTqYTSGaYKcmFy+96l0+VgtLTwFAw== X-Received: by 2002:a2e:9a4f:: with SMTP id k15mr45816995ljj.159.1558713577214; Fri, 24 May 2019 08:59:37 -0700 (PDT) Return-Path: Received: from gilgamesh.semihalf.com (31-172-191-173.noc.fibertech.net.pl. [31.172.191.173]) by smtp.gmail.com with ESMTPSA id d18sm685280lfl.95.2019.05.24.08.59.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 24 May 2019 08:59:36 -0700 (PDT) From: "Marcin Wojtas" To: devel@edk2.groups.io Cc: leif.lindholm@linaro.org, ard.biesheuvel@linaro.org, mw@semihalf.com, jsd@semihalf.com, jaz@semihalf.com, kostap@marvell.com, Jici.Gao@arm.com, rebecca@bluestop.org, kettenis@jive.eu Subject: [edk2-platforms: PATCH v3 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib Date: Fri, 24 May 2019 17:59:04 +0200 Message-Id: <1558713551-25363-8-git-send-email-mw@semihalf.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1558713551-25363-1-git-send-email-mw@semihalf.com> References: <1558713551-25363-1-git-send-email-mw@semihalf.com> 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 and Jing Hua / Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Marcin Wojtas --- Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf | 52 +++ Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h | 95 ++++++ Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c | 265 +++++++++++++++ Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c | 345 ++++++++++++++++++++ 4 files changed, 757 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.
+# Copyright (c) 2019 Marvell International Ltd. All rights reserved.
+# +# 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..8188001 --- /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.
+ Copyright (c) 2019 Marvell International Ltd. All rights reserved.
+ + 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..58cdf83 --- /dev/null +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c @@ -0,0 +1,265 @@ +/** @file + PCI Host Bridge Library instance for Marvell Armada 70x0/80x0 + + Copyright (c) 2017, Linaro Ltd. All rights reserved.
+ Copyright (c) 2019 Marvell International Ltd. All rights reserved.
+ + 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#pragma pack(1) +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH; +#pragma pack () + +STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0x0A08), // PCI Express + 0 + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = { + L"Mem", L"I/O", L"Bus" +}; + +/** + Return all the root bridge instances in an array. + + @param Count Return the count of root bridge instances. + + @return All the root bridge instances in an array. + The array should be passed into PciHostBridgeFreeRootBridges() + when it's not used. + +**/ +PCI_ROOT_BRIDGE * +EFIAPI +PciHostBridgeGetRootBridges ( + UINTN *Count + ) +{ + MV_BOARD_PCIE_DESCRIPTION CONST *BoardPcieDescription; + MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol; + MV_PCIE_CONTROLLER CONST *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; + +#ifndef MDE_CPU_ARM + RootBridge->AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | + EFI_PCI_HOST_BRIDGE_MEM64_DECODE; +#else + RootBridge->AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM; +#endif + + RootBridge->Bus.Base = PcieController->PcieBusMin; + RootBridge->Bus.Limit = PcieController->PcieBusMax; + RootBridge->Io.Base = PcieController->PcieIoWinBase; + RootBridge->Io.Limit = PcieController->PcieIoWinBase + + PcieController->PcieIoWinSize - 1; + RootBridge->Io.Translation = MAX_UINT64 - + PcieController->PcieIoTranslation + 1; + RootBridge->Mem.Base = PcieController->PcieMmio32WinBase; + RootBridge->Mem.Limit = PcieController->PcieMmio32WinBase + + PcieController->PcieMmio32WinSize - 1; + RootBridge->Mem.Translation = MAX_UINT64 - + PcieController->PcieMmio32Translation + 1; +#ifndef MDE_CPU_ARM + RootBridge->MemAbove4G.Base = PcieController->PcieMmio64WinBase; + RootBridge->MemAbove4G.Limit = PcieController->PcieMmio64WinBase + + PcieController->PcieMmio64WinSize - 1; + RootBridge->MemAbove4G.Translation = MAX_UINT64 - + PcieController->PcieMmio64Translation + 1; +#else + RootBridge->MemAbove4G.Base = MAX_UINT64; + RootBridge->MemAbove4G.Limit = 0; + RootBridge->MemAbove4G.Translation = 0; +#endif + + /* 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; + + + 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; + CHAR16 *MemoryTypeDescription[] = { L"(Prefetchable)", L"" }; + CHAR16 *MemoryType; + 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) { + if (Descriptor->SpecificFlag & + EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) { + MemoryType = MemoryTypeDescription[0]; + } else { + MemoryType = MemoryTypeDescription[1]; + } + + DEBUG ((DEBUG_ERROR, + " Granularity/SpecificFlag = %ld / %02x%s\n", + Descriptor->AddrSpaceGranularity, + Descriptor->SpecificFlag, + MemoryType)); + } + } + /* 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..8376756 --- /dev/null +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c @@ -0,0 +1,345 @@ +/** @file + PCI Host Bridge Library instance for Marvell 70x0/80x0 + + Copyright (c) 2017, Linaro Ltd. All rights reserved.
+ Copyright (c) 2019 Marvell International Ltd. All rights reserved.
+ + 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 + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "PciHostBridgeLibConstructor.h" + +/** + This function configures PCIE controllers IATU windows. + + @param [in] PcieDbiAddress 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 PcieDbiAddress, + IN UINTN Index, + IN UINT64 CpuBase, + IN UINT64 PciBase, + IN UINT64 Size, + IN UINTN Type, + IN UINTN EnableFlags + ) +{ + ArmDataMemoryBarrier (); + + MmioWrite32 (PcieDbiAddress + IATU_VIEWPORT_OFF, + IATU_VIEWPORT_OUTBOUND | IATU_VIEWPORT_REGION_INDEX (Index)); + + ArmDataMemoryBarrier (); + + MmioWrite32 (PcieDbiAddress + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0, + (UINT32)(CpuBase & MAX_UINT32)); + MmioWrite32 (PcieDbiAddress + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0, + (UINT32)(CpuBase >> 32)); + MmioWrite32 (PcieDbiAddress + IATU_LIMIT_ADDR_OFF_OUTBOUND_0, + (UINT32)(CpuBase + Size - 1)); + MmioWrite32 (PcieDbiAddress + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0, + (UINT32)(PciBase & MAX_UINT32)); + MmioWrite32 (PcieDbiAddress + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0, + (UINT32)(PciBase >> 32)); + MmioWrite32 (PcieDbiAddress + IATU_REGION_CTRL_1_OFF_OUTBOUND_0, + Type); + MmioWrite32 (PcieDbiAddress + 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] PcieDbiAddress PCIE controller base address. + + @retval none + +**/ +STATIC +VOID +WaitForLink ( + IN EFI_PHYSICAL_ADDRESS PcieDbiAddress + ) +{ + UINT32 Mask; + UINT32 Status; + UINT32 Timeout; + + if (!(MmioRead32 (PcieDbiAddress + 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 (PcieDbiAddress + PCIE_GLOBAL_STATUS_REG); + if ((Status & Mask) == Mask) { + DEBUG ((DEBUG_ERROR, "pcie@0x%x link UP\n", PcieDbiAddress)); + break; + } + /* Wait 10us between each link status check. */ + gBS->Stall (10); + } while (Timeout--); +} + +/** + Perform PCIE slot reset using external GPIO pin. + + @param [in] *PcieResetGpio GPIO pin description. + + @retval EFI_SUCEESS PCIE slot reset succeeded. + @retval Other Return error status. + +**/ +STATIC +EFI_STATUS +ResetPcieSlot ( + IN MV_GPIO_PIN CONST *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), + + /* Activate reset. */ + Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_1 : GPIO_MODE_OUTPUT_0; + Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode); + + /* + * According to the PCIE specification, the reset signal must be active + * for minimum 100ms. To be on a safe side, use 150ms delay. + */ + MemoryFence (); + gBS->Stall (150 * 1000); + + /* Dectivate reset. */ + Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_0 : GPIO_MODE_OUTPUT_1; + Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode); + + /* + * The controller cannot be configured (e.g. the clocks have to establish) + * during 20ms period after the reset is deactivated. + */ + MemoryFence (); + gBS->Stall (20 * 1000); + + return EFI_SUCCESS; +} + +/** + Obtain resources and perform a low-level PCIE controllers + configuration. + + @param [in] ImageHandle The image handle. + @param [in] *SystemTable The system table. + + @retval EFI_SUCEESS PCIE configuration successful. + @retval Other Return error status. + +**/ +EFI_STATUS +EFIAPI +Armada7k8kPciHostBridgeLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + MV_BOARD_PCIE_DESCRIPTION CONST *BoardPcieDescription; + MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol; + MV_PCIE_CONTROLLER CONST *PcieController; + EFI_PHYSICAL_ADDRESS PcieDbiAddress; + 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 */ + PcieDbiAddress = PcieController->PcieDbiAddress; + + MmioAndThenOr32 (PcieDbiAddress + PORT_LINK_CTRL_OFF, + ~PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK, + PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4); + + MmioAndThenOr32 (PcieDbiAddress + GEN2_CTRL_OFF, + ~GEN2_CTRL_OFF_NUM_OF_LANES_MASK, + GEN2_CTRL_OFF_NUM_OF_LANES(4) | GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE); + + MmioAndThenOr32 (PcieDbiAddress + PCIE_GLOBAL_CTRL_OFFSET, + ~(PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK | PCIE_GLOBAL_APP_LTSSM_EN), + PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC); + + MmioWrite32 (PcieDbiAddress + PCIE_ARCACHE_TRC_REG, + ARCACHE_DEFAULT_VALUE); + + MmioWrite32 (PcieDbiAddress + PCIE_AWCACHE_TRC_REG, + AWCACHE_DEFAULT_VALUE); + + MmioAndThenOr32 (PcieDbiAddress + PCIE_ARUSER_REG, + ~AX_USER_DOMAIN_MASK, + AX_USER_DOMAIN_OUTER_SHAREABLE); + + MmioAndThenOr32 (PcieDbiAddress + PCIE_AWUSER_REG, + ~AX_USER_DOMAIN_MASK, + AX_USER_DOMAIN_OUTER_SHAREABLE); + + MmioAndThenOr32 (PcieDbiAddress + PCIE_LINK_CTL_2, + ~TARGET_LINK_SPEED_MASK, + LINK_SPEED_GEN_3); + + MmioAndThenOr32 (PcieDbiAddress + PCIE_LINK_CAPABILITY, + ~TARGET_LINK_SPEED_MASK, + LINK_SPEED_GEN_3); + + MmioOr32 (PcieDbiAddress + PCIE_GEN3_EQU_CTRL, + GEN3_EQU_EVAL_2MS_DISABLE); + + MmioOr32 (PcieDbiAddress + PCIE_GLOBAL_CTRL_OFFSET, + PCIE_GLOBAL_APP_LTSSM_EN); + + /* Region 0: MMIO32 range */ + ConfigureWindow (PcieDbiAddress, + PcieController->PcieMmio32WinBase - PcieController->PcieMmio32Translation, + PcieController->PcieMmio32WinBase, + PcieController->PcieMmio32WinBase, + PcieController->PcieMmio32WinSize, + IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM, + 0); + + /* Region 1: Type 0 config space */ + ConfigureWindow (PcieDbiAddress, + 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 (PcieDbiAddress, + 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 (PcieDbiAddress, + 3, + PcieController->PcieIoTranslation, + PcieController->PcieIoWinBase, + PcieController->PcieIoWinSize, + IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO, + 0); + + /* Region 4: MMIO64 range */ + ConfigureWindow (PcieDbiAddress, + 4, + PcieController->PcieMmio64WinBase, + PcieController->PcieMmio64WinBase, + PcieController->PcieMmio64WinSize, + IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM, + 0); + + MmioOr32 (PcieDbiAddress + 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 (PcieDbiAddress); + + /* Enable the RC */ + MmioOr32 (PcieDbiAddress + PCI_COMMAND_OFFSET, + EFI_PCI_COMMAND_IO_SPACE | + EFI_PCI_COMMAND_MEMORY_SPACE | + EFI_PCI_COMMAND_BUS_MASTER); + } + + return EFI_SUCCESS; +} -- 2.7.4