summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbCommonLib/GnbLibPci.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbCommonLib/GnbLibPci.c')
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbCommonLib/GnbLibPci.c405
1 files changed, 405 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbCommonLib/GnbLibPci.c b/src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbCommonLib/GnbLibPci.c
new file mode 100644
index 0000000000..8c02a9b569
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbCommonLib/GnbLibPci.c
@@ -0,0 +1,405 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Various PCI service routines.
+ *
+ *
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: GNB
+ * @e \$Revision: 34897 $ @e \$Date: 2010-07-13 19:07:10 -0700 (Tue, 13 Jul 2010) $
+ *
+ */
+/*
+ *****************************************************************************
+ *
+ * Copyright (c) 2011, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+
+#include "Porting.h"
+#include "AMD.h"
+#include "GnbLibPciAcc.h"
+#include "GnbLibPci.h"
+#include "GnbLibPci.h"
+#include "amdlib.h"
+#include "GnbLib.h"
+#include "Filecode.h"
+#define FILECODE PROC_GNB_MODULES_GNBCOMMONLIB_GNBLIBPCI_FILECODE
+
+/*----------------------------------------------------------------------------------------*/
+/*
+ * Check if device present
+ *
+ *
+ *
+ * @param[in] Address PCI address (as described in PCI_ADDR)
+ * @param[in] StdHeader Standard configuration header
+ * @retval TRUE Device is present
+ * @retval FALSE Device is not present
+ */
+
+BOOLEAN
+GnbLibPciIsDevicePresent (
+ IN UINT32 Address,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 DeviceId;
+ GnbLibPciRead (Address, AccessWidth32, &DeviceId, StdHeader);
+ if (DeviceId == 0xffffffff) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/*----------------------------------------------------------------------------------------*/
+/*
+ * Check if device is bridge
+ *
+ *
+ *
+ * @param[in] Address PCI address (as described in PCI_ADDR)
+ * @param[in] StdHeader Standard configuration header
+ * @retval TRUE Device is a bridge
+ * @retval FALSE Device is not a bridge
+ */
+
+BOOLEAN
+GnbLibPciIsBridgeDevice (
+ IN UINT32 Address,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 Header;
+ GnbLibPciRead (Address | 0xe, AccessWidth8, &Header, StdHeader);
+ if ((Header & 0x7f) == 1) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/*
+ * Check if device is multifunction
+ *
+ *
+ *
+ * @param[in] Address PCI address (as described in PCI_ADDR)
+ * @param[in] StdHeader Standard configuration header
+ * @retval TRUE Device is a multifunction device.
+ * @retval FALSE Device is a single function device.
+ *
+ */
+BOOLEAN
+GnbLibPciIsMultiFunctionDevice (
+ IN UINT32 Address,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 Header;
+ GnbLibPciRead (Address | 0xe, AccessWidth8, &Header, StdHeader);
+ if ((Header & 0x80) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/*
+ * Check if device is PCIe device
+ *
+ *
+ *
+ * @param[in] Address PCI address (as described in PCI_ADDR)
+ * @param[in] StdHeader Standard configuration header
+ * @retval TRUE Device is a PCIe device
+ * @retval FALSE Device is not a PCIe device
+ *
+ */
+
+BOOLEAN
+GnbLibPciIsPcieDevice (
+ IN UINT32 Address,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ if (GnbLibFindPciCapability (Address, 0x10, StdHeader) != 0 ) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/*----------------------------------------------------------------------------------------*/
+/*
+ * Find PCI capability pointer
+ *
+ *
+ *
+ * @param[in] Address PCI address (as described in PCI_ADDR)
+ * @param[in] CapabilityId PCI capability ID
+ * @param[in] StdHeader Standard configuration header
+ * @retval Register address of capability pointer
+ *
+ */
+
+UINT8
+GnbLibFindPciCapability (
+ IN UINT32 Address,
+ IN UINT8 CapabilityId,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 CapabilityPtr;
+ UINT8 CurrentCapabilityId;
+ CapabilityPtr = 0x34;
+ if (!GnbLibPciIsDevicePresent (Address, StdHeader)) {
+ return 0;
+ }
+ while (CapabilityPtr != 0) {
+ GnbLibPciRead (Address | CapabilityPtr, AccessWidth8 , &CapabilityPtr, StdHeader);
+ if (CapabilityPtr != 0) {
+ GnbLibPciRead (Address | CapabilityPtr , AccessWidth8 , &CurrentCapabilityId, StdHeader);
+ if (CurrentCapabilityId == CapabilityId) {
+ break;
+ }
+ CapabilityPtr++;
+ }
+ }
+ return CapabilityPtr;
+}
+/*----------------------------------------------------------------------------------------*/
+/*
+ * Find PCIe extended capability pointer
+ *
+ *
+ *
+ * @param[in] Address PCI address (as described in PCI_ADDR)
+ * @param[in] ExtendedCapabilityId Extended PCIe capability ID
+ * @param[in] StdHeader Standard configuration header
+ * @retval Register address of extended capability pointer
+ *
+ */
+
+
+UINT16
+GnbLibFindPcieExtendedCapability (
+ IN UINT32 Address,
+ IN UINT16 ExtendedCapabilityId,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT16 CapabilityPtr;
+ UINT32 ExtendedCapabilityIdBlock;
+ if (GnbLibPciIsPcieDevice (Address, StdHeader)) {
+ GnbLibPciRead (Address | 0x100 , AccessWidth32 , &ExtendedCapabilityIdBlock, StdHeader);
+ if ((ExtendedCapabilityIdBlock != 0) && ((UINT16)ExtendedCapabilityIdBlock != 0xffff)) {
+ do {
+ CapabilityPtr = (UINT16) ((ExtendedCapabilityIdBlock >> 20) & 0xfff);
+ if ((UINT16)ExtendedCapabilityIdBlock == ExtendedCapabilityId) {
+ return CapabilityPtr;
+ }
+ GnbLibPciRead (Address | CapabilityPtr , AccessWidth32 , &ExtendedCapabilityIdBlock, StdHeader);
+ } while (((ExtendedCapabilityIdBlock >> 20) & 0xfff) != 0);
+ }
+ }
+ return 0;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/*
+ * Scan range of device on PCI bus.
+ *
+ *
+ *
+ * @param[in] Start Start address to start scan from
+ * @param[in] End End address of scan
+ * @param[in] ScanData Supporting data
+ *
+ */
+/*----------------------------------------------------------------------------------------*/
+VOID
+GnbLibPciScan (
+ IN PCI_ADDR Start,
+ IN PCI_ADDR End,
+ IN GNB_PCI_SCAN_DATA *ScanData
+ )
+{
+ UINTN Bus;
+ UINTN Device;
+ UINTN LastDevice;
+ UINTN Function;
+ UINTN LastFunction;
+ PCI_ADDR PciDevice;
+ SCAN_STATUS Status;
+
+ for (Bus = Start.Address.Bus; Bus <= End.Address.Bus; Bus++) {
+ Device = (Bus == Start.Address.Bus) ? Start.Address.Device : 0x00;
+ LastDevice = (Bus == End.Address.Bus) ? End.Address.Device : 0x1F;
+ for ( ; Device <= LastDevice; Device++) {
+ if ((Bus == Start.Address.Bus) && (Device == Start.Address.Device)) {
+ Function = Start.Address.Function;
+ } else {
+ Function = 0x0;
+ }
+ PciDevice.AddressValue = MAKE_SBDFO (0, Bus, Device, Function, 0);
+ if (!GnbLibPciIsDevicePresent (PciDevice.AddressValue, ScanData->StdHeader)) {
+ continue;
+ }
+ if (GnbLibPciIsMultiFunctionDevice (PciDevice.AddressValue, ScanData->StdHeader)) {
+ if ((Bus == End.Address.Bus) && (Device == End.Address.Device)) {
+ LastFunction = Start.Address.Function;
+ } else {
+ LastFunction = 0x7;
+ }
+ } else {
+ LastFunction = 0x0;
+ }
+ for ( ; Function <= LastFunction; Function++) {
+ PciDevice.AddressValue = MAKE_SBDFO (0, Bus, Device, Function, 0);
+ if (GnbLibPciIsDevicePresent (PciDevice.AddressValue, ScanData->StdHeader)) {
+ Status = ScanData->GnbScanCallback (PciDevice, ScanData);
+ if ((Status & SCAN_SKIP_FUNCTIONS) != 0) {
+ Function = LastFunction + 1;
+ }
+ if ((Status & SCAN_SKIP_DEVICES) != 0) {
+ Device = LastDevice + 1;
+ }
+ if ((Status & SCAN_SKIP_BUSES) != 0) {
+ Bus = End.Address.Bus + 1;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Scan all subordinate buses
+ *
+ *
+ * @param[in] Bridge PCI bridge address
+ * @param[in,out] ScanData Scan configuration data
+ *
+ */
+VOID
+GnbLibPciScanSecondaryBus (
+ IN PCI_ADDR Bridge,
+ IN OUT GNB_PCI_SCAN_DATA *ScanData
+ )
+{
+ PCI_ADDR StartRange;
+ PCI_ADDR EndRange;
+ UINT8 SecondaryBus;
+ GnbLibPciRead (Bridge.AddressValue | 0x19, AccessWidth8, &SecondaryBus, ScanData->StdHeader);
+ if (SecondaryBus != 0) {
+ StartRange.AddressValue = MAKE_SBDFO (0, SecondaryBus, 0, 0, 0);
+ EndRange.AddressValue = MAKE_SBDFO (0, SecondaryBus, 0x1f, 0x7, 0);
+ GnbLibPciScan (StartRange, EndRange, ScanData);
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Get PCIe device type
+ *
+ *
+ *
+ * @param[in] Device PCI address of device.
+ * @param[in] StdHeader Northbridge configuration structure pointer.
+ *
+ * @retval PCIE_DEVICE_TYPE
+ */
+ /*----------------------------------------------------------------------------------------*/
+
+PCIE_DEVICE_TYPE
+GnbLibGetPcieDeviceType (
+ IN PCI_ADDR Device,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 PcieCapPtr;
+ UINT8 Value;
+
+ PcieCapPtr = GnbLibFindPciCapability (Device.AddressValue, PCIE_CAP_ID, StdHeader);
+ if (PcieCapPtr != 0) {
+ GnbLibPciRead (Device.AddressValue | (PcieCapPtr + 0x2) , AccessWidth8, &Value, StdHeader);
+ return Value >> 4;
+ }
+ return PcieNotPcieDevice;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Save config space area
+ *
+ *
+ *
+ * @param[in] Address PCI address of device.
+ * @param[in] StartRegisterAddress Start register address.
+ * @param[in] EndRegisterAddress End register address.
+ * @param[in] Width Acess width.
+ * @param[in] StdHeader Standard header.
+ *
+ */
+ /*----------------------------------------------------------------------------------------*/
+
+VOID
+GnbLibS3SaveConfigSpace (
+ IN UINT32 Address,
+ IN UINT16 StartRegisterAddress,
+ IN UINT16 EndRegisterAddress,
+ IN ACCESS_WIDTH Width,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT16 Index;
+ UINT16 Delta;
+ UINT16 Length;
+ Length = (StartRegisterAddress < EndRegisterAddress) ? (EndRegisterAddress - StartRegisterAddress) : (StartRegisterAddress - EndRegisterAddress);
+ Delta = LibAmdAccessWidth (Width);
+ for (Index = 0; Index <= Length; Index = Index + Delta) {
+ GnbLibPciRMW (
+ Address | ((StartRegisterAddress < EndRegisterAddress) ? (StartRegisterAddress + Index) : (StartRegisterAddress - Index)),
+ Width,
+ 0xffffffff,
+ 0x0,
+ StdHeader
+ );
+ }
+}