/** * @file * * NB library functions. * * * * @xrefitem bom "File Content Label" "Release Content" * @e project: CIMx-NB * @e sub-project: * @e \$Revision:$ @e \$Date:$ * */ /***************************************************************************** * * Copyright (C) 2012 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. * * ***************************************************************************/ /*---------------------------------------------------------------------------------------- * M O D U L E S U S E D *---------------------------------------------------------------------------------------- */ #include "NbPlatform.h" #include "amdDebugOutLib.h" /*---------------------------------------------------------------------------------------- * D E F I N I T I O N S A N D M A C R O S *---------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------- * T Y P E D E F S A N D S T R U C T U R E S *---------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------- * P R O T O T Y P E S O F L O C A L F U N C T I O N S *---------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------- * E X P O R T E D F U N C T I O N S *---------------------------------------------------------------------------------------- */ /*----------------------------------------------------------------------------------------*/ /** * Get silicon type and revision info. * * * * @param[in] NbConfigPtr configuration structure pointer. * @retval NB_INFO Northbrige Info Structure. */ /*----------------------------------------------------------------------------------------*/ NB_INFO LibNbGetRevisionInfo ( IN AMD_NB_CONFIG *NbConfigPtr ) { NB_INFO RevisionInfo; UINT16 DeviceId; UINT8 RevisionId; UINT32 PrivateId; LibNbPciRead (NbConfigPtr->NbPciAddress.AddressValue | 0x8, AccessWidth8, &RevisionId, NbConfigPtr); RevisionInfo.Revision = RevisionId; LibNbPciRead (NbConfigPtr->NbPciAddress.AddressValue | 0x2, AccessWidth16, &DeviceId, NbConfigPtr); switch (DeviceId) { case 0x5956: RevisionInfo.Type = NB_RD890TV; break; case 0x5957: RevisionInfo.Type = NB_RX780; break; case 0x5958: RevisionInfo.Type = NB_RD780; break; case 0x5A10: RevisionInfo.Type = NB_SR5690; break; case 0x5A11: RevisionInfo.Type = NB_RD890; break; case 0x5A12: RevisionInfo.Type = NB_SR5670; break; case 0x5A13: RevisionInfo.Type = NB_SR5650; break; case 0x5A14: RevisionInfo.Type = NB_990FX; LibNbPciIndexRead (NbConfigPtr->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG7D, AccessWidth32, &PrivateId, NbConfigPtr); PrivateId = (PrivateId >> 21) & 0x0f; if (PrivateId == 1) { RevisionInfo.Type = NB_990FX; } if (PrivateId == 2) { RevisionInfo.Type = NB_990X; } if (PrivateId == 3) { RevisionInfo.Type = NB_970; } break; default: RevisionInfo.Type = NB_UNKNOWN; CIMX_ASSERT (FALSE); } return RevisionInfo; } /*----------------------------------------------------------------------------------------*/ /** * Call Back routine. * * * * @param[in] CallBackId Callback ID. * @param[in] Data Callback specific data. * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ AGESA_STATUS LibNbCallBack ( IN UINT32 CallBackId, IN OUT UINTN Data, IN OUT AMD_NB_CONFIG *NbConfigPtr ) { AGESA_STATUS Status; CALLOUT_ENTRY CallBackPtr = GET_BLOCK_CONFIG_PTR (NbConfigPtr)->StandardHeader.CalloutPtr; Status = AGESA_UNSUPPORTED; if (CallBackPtr != NULL) { CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NB_TRACE), "[NBLIB]LibNbCallBack CallBackId = 0x%x\n", CallBackId)); Status = (*CallBackPtr) (CallBackId, Data, GET_BLOCK_CONFIG_PTR (NbConfigPtr)); CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NB_TRACE), "[NBLIB]LibNbCallBack Return = 0x%x\n", Status)); } return Status; } /*----------------------------------------------------------------------------------------*/ /** * Call Back routine. * * * * @param[in] SystemApi Pointer to System API * @param[in] ConfigPtr Northbridge block configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ AGESA_STATUS LibSystemApiCall ( IN SYSTEM_API SystemApi, IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr ) { API_WORKSPACE Workspace; UINT8 NorthbridgeId; LibAmdMemFill (&Workspace, 0, sizeof (API_WORKSPACE), (AMD_CONFIG_PARAMS *)&(ConfigPtr->StandardHeader)); Workspace.ConfigPtr = ConfigPtr; Workspace.Status = AGESA_SUCCESS; for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) { ConfigPtr->Northbridges[NorthbridgeId].ConfigPtr = &Workspace.ConfigPtr; } if (SystemApi != NULL) { (*SystemApi)(ConfigPtr); } return Workspace.Status; } /*----------------------------------------------------------------------------------------*/ /** * Call Back routine. * * * * @param[in] NbApi Pointer to NB API * @param[in] ConfigPtr Northbridge block configuration structure pointer */ /*----------------------------------------------------------------------------------------*/ AGESA_STATUS LibNbApiCall ( IN NB_API NbApi, IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr ) { UINT8 NorthbridgeId; AGESA_STATUS Status; Status = AGESA_SUCCESS; for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) { AMD_NB_CONFIG *NbConfigPtr = &ConfigPtr->Northbridges[NorthbridgeId]; ConfigPtr->CurrentNorthbridge = NorthbridgeId; if (!LibNbIsDevicePresent (NbConfigPtr->NbPciAddress, NbConfigPtr)) { REPORT_EVENT (AGESA_WARNING, GENERAL_ERROR_NB_NOT_PRESENT, 0 , 0, 0, 0, NbConfigPtr); continue; } if (NbApi != NULL) { Status = (*NbApi) (NbConfigPtr); if (Status == AGESA_FATAL) { break; } } } return Status; } /*----------------------------------------------------------------------------------------*/ /** * Write PCI register. * * * * @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue * @param[in] Width Access width. * @param[in] Value Pointer to new register value. * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbPciWrite ( IN UINT32 Address, IN ACCESS_WIDTH Width, IN VOID *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { PCI_ADDR DeviceAddress; DeviceAddress.AddressValue = Address; LibAmdPciWrite (Width, DeviceAddress, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr))); } /*----------------------------------------------------------------------------------------*/ /** * Read PCI register * * * * @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue * @param[in] Width Access width. * @param[in] Value Pointer to save register value. * @param[in] NbConfigPtr Northbridge configuration structure pointer. * */ /*----------------------------------------------------------------------------------------*/ VOID LibNbPciRead ( IN UINT32 Address, IN ACCESS_WIDTH Width, OUT VOID *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { PCI_ADDR DeviceAddress; DeviceAddress.AddressValue = Address; LibAmdPciRead (Width, DeviceAddress, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr))); } /*----------------------------------------------------------------------------------------*/ /** * Read/Modify/Write PCI register * * * * @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue * @param[in] Width Access width. * @param[in] Mask AND Mask. * @param[in] Data OR Mask. * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbPciRMW ( IN UINT32 Address, IN ACCESS_WIDTH Width, IN UINT32 Mask, IN UINT32 Data, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 Value; LibNbPciRead (Address, Width, &Value, NbConfigPtr); Value = (Value & Mask) | Data; LibNbPciWrite (Address, Width, &Value, NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Read PCI Index/Data Address space * * * * @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue * @param[in] Index Index Address. * @param[in] Width Access width of Index/Data register. * @param[in] Value Pointer to save register value. * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbPciIndexRead ( IN UINT32 Address, IN UINT32 Index, IN ACCESS_WIDTH Width, OUT UINT32 *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 IndexOffset; IndexOffset = (1 << ((Width < 0x80)? (Width - 1): (Width - 0x81))); LibNbPciWrite (Address, Width, &Index, NbConfigPtr); LibNbPciRead (Address + IndexOffset, Width, Value, NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Write PCI Index/Data Address space * * * * @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue * @param[in] Index Index Address. * @param[in] Width Access width of Index/Data register. * @param[in] Value Pointer to save register value. * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbPciIndexWrite ( IN UINT32 Address, IN UINT32 Index, IN ACCESS_WIDTH Width, IN UINT32 *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 IndexOffset; IndexOffset = (1 << ((Width < 0x80)? (Width - 1): (Width - 0x81))); LibNbPciWrite (Address, Width, &Index, NbConfigPtr); LibNbPciWrite (Address + IndexOffset , Width, Value, NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Read/Modify/Write PCI Index/Data Address space * * * * @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue * @param[in] Index Index Address. * @param[in] Width Access width of Index/Data register. * @param[in] Mask AND Mask. * @param[in] Data OR Mask. * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbPciIndexRMW ( IN UINT32 Address, IN UINT32 Index, IN ACCESS_WIDTH Width, IN UINT32 Mask, IN UINT32 Data, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 Value; LibNbPciIndexRead (Address, Index, Width, &Value, NbConfigPtr); Value = (Value & Mask) | Data; LibNbPciIndexWrite (Address, Index, Width, &Value, NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Program table of indirect register. * * * * @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue * @param[in] Index Index Address. Index address OR with INDIRECT_REG_ENTRY.Register * @param[in] pTable Pointer to indirect register table. * @param[in] Length Number of entry in indirect register table. * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbIndirectTableInit ( IN UINT32 Address, IN UINT32 Index, IN INDIRECT_REG_ENTRY *pTable, IN UINTN Length, IN AMD_NB_CONFIG *NbConfigPtr ) { UINTN i; for (i = 0; i < Length; i++) { LibNbPciIndexRMW (Address, Index | pTable[i].Register , AccessS3SaveWidth32, pTable[i].Mask, pTable[i].Data, NbConfigPtr); } } /*----------------------------------------------------------------------------------------*/ /* * Find PCI capability pointer * * * * * */ /*----------------------------------------------------------------------------------------*/ UINT8 LibNbFindPciCapability ( IN UINT32 Address, IN UINT8 CapabilityId, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT8 CapabilityPtr; UINT8 CurrentCapabilityId; PCI_ADDR Device; Device.AddressValue = Address; CapabilityPtr = 0x34; if (!LibNbIsDevicePresent (Device, NbConfigPtr)) { return 0; } while (CapabilityPtr != 0) { LibNbPciRead (Address | CapabilityPtr, AccessWidth8 , &CapabilityPtr, NbConfigPtr); if (CapabilityPtr) { LibNbPciRead (Address | CapabilityPtr , AccessWidth8 , &CurrentCapabilityId, NbConfigPtr); if (CurrentCapabilityId == CapabilityId) break; CapabilityPtr++; } } return CapabilityPtr; } /*----------------------------------------------------------------------------------------*/ /* * Find PCIe extended capability pointer * * * * * */ /*----------------------------------------------------------------------------------------*/ UINT16 LibNbFindPcieExtendedCapability ( IN UINT32 Address, IN UINT16 ExtendedCapabilityId, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT16 CapabilityPtr; UINT32 ExtendedCapabilityIdBlock; if (LibNbFindPciCapability (Address, 0x10, NbConfigPtr) != 0) { CapabilityPtr = 0x100; LibNbPciRead (Address | CapabilityPtr , AccessWidth32 , &ExtendedCapabilityIdBlock, NbConfigPtr); if (ExtendedCapabilityIdBlock != 0 && (UINT16)ExtendedCapabilityIdBlock != 0xffff) { do { if ((UINT16)ExtendedCapabilityIdBlock == ExtendedCapabilityId) { return CapabilityPtr; } CapabilityPtr = (UINT16) ((ExtendedCapabilityIdBlock >> 20) & 0xfff); LibNbPciRead (Address | CapabilityPtr , AccessWidth32 , &ExtendedCapabilityIdBlock, NbConfigPtr); } while (CapabilityPtr != 0); } } return 0; } /*----------------------------------------------------------------------------------------*/ /** * Read IO space * * * * @param[in] Address IO Port address. * @param[in] Width Access width * @param[in] Value Pointer to save IO port value; * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbIoRead ( IN UINT16 Address, IN ACCESS_WIDTH Width, OUT VOID *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { LibAmdIoRead (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr))); } /*----------------------------------------------------------------------------------------*/ /** * Write IO space * * * * @param[in] Address IO Port address. * @param[in] Width Access width * @param[in] Value Pointer to new IO port value * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ VOID LibNbIoWrite ( IN UINT16 Address, IN ACCESS_WIDTH Width, IN VOID *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { LibAmdIoWrite (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr))); } /*----------------------------------------------------------------------------------------*/ /** * Read/Modify/Write IO space * * * * @param[in] Address IO Port address. * @param[in] Width Access width * @param[in] Mask AND Mask * @param[in] Data OR Mask * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbIoRMW ( IN UINT16 Address, IN ACCESS_WIDTH Width, IN UINT32 Mask, IN UINT32 Data, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 Value; LibNbIoRead (Address, Width, &Value, NbConfigPtr); Value = (Value & Mask) | Data; LibNbIoWrite (Address, Width, &Value, NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Read CPU HT link Phy register * * * * @param[in] Node Node device Address (0x18 - Node 0, 0x19 - Mode 1 etc.) * @param[in] Link HT Link ID (0 - Link 0, 1 - Link 1 etc.) * @param[in] Register Register address. * @param[in] Value Pointer to save register value * @param[in] NbConfigPtr Northbridge configuration block pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbCpuHTLinkPhyRead ( IN UINT8 Node, IN UINT8 Link, IN UINT16 Register, OUT UINT32 *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 Data; PCI_ADDR CpuPciAddress; UINT8 LinkId; LinkId = Link & 0xf; CpuPciAddress.AddressValue = MAKE_SBDFO (0, 0, Node, 4, 0); LibNbPciRMW (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, 0x0, Register | ((Register & 0xfe00)?BIT29:0), NbConfigPtr); do { LibNbPciRead (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, &Data, NbConfigPtr); } while ((Data & BIT31) == 0); LibNbPciRead (CpuPciAddress.AddressValue | (LinkId * 8 + 0x184), AccessWidth32, Value, NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Write CPU HT link Phy register * * * * @param[in] Node Node device Address (0x18 - Node 0, 0x19 - Mode 1 etc.) * @param[in] Link HT Link ID (0 - Link 0, 1 - Link 1 etc.) * @param[in] Register Register address. * @param[in] Value Pointer to new register value * @param[in] NbConfigPtr Northbridge configuration block pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbCpuHTLinkPhyWrite ( IN UINT8 Node, IN UINT8 Link, IN UINT16 Register, IN UINT32 *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 Data; PCI_ADDR CpuPciAddress; UINT8 LinkId; LinkId = Link & 0xf; CpuPciAddress.AddressValue = MAKE_SBDFO (0, 0, Node, 4, 0); LibNbPciWrite (CpuPciAddress.AddressValue | (LinkId * 8 + 0x184), AccessWidth32, Value, NbConfigPtr); LibNbPciRMW (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, 0x0, Register | BIT30 | ((Register & 0xfe00)?BIT29:0), NbConfigPtr); do { LibNbPciRead (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, &Data, NbConfigPtr); } while ((Data & BIT31) == 0); } /*----------------------------------------------------------------------------------------*/ /** * Read/Modify/Write CPU HT link Phy register * * * * @param[in] Node Node device Address (0x18 - Node 0, 0x19 - Mode 1 etc.) * @param[in] Link HT Link ID (0 - Link 0, 1 - Link 1 etc.) * @param[in] Register Register address. * @param[in] Mask AND Mask. * @param[in] Data OR Mask. * @param[in] NbConfigPtr Northbridge configuration block pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbCpuHTLinkPhyRMW ( IN UINT8 Node, IN UINT8 Link, IN UINT16 Register, IN UINT32 Mask, IN UINT32 Data, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 Value; LibNbCpuHTLinkPhyRead (Node, Link, Register, &Value, NbConfigPtr); Value = (Value & Mask) | Data; LibNbCpuHTLinkPhyWrite (Node, Link, Register, &Value, NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Enable Clock Config space access. * Enable access to Clock Config Space at 0:0:1 PCI address. * * * @param[in] pConfig Northbridge configuration block pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbEnableClkConfig ( IN AMD_NB_CONFIG *pConfig ) { LibNbPciRMW (NB_SBDFO | NB_PCI_REG4C, AccessS3SaveWidth8, (UINT32)~BIT0, BIT0, pConfig); } /*----------------------------------------------------------------------------------------*/ /** * Disable Clock Config space access. * Disable access to Clock Config Space at 0:0:1 PCI address. * * * @param[in] pConfig Northbridge configuration block pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbDisableClkConfig ( IN AMD_NB_CONFIG *pConfig ) { LibNbPciRMW (NB_SBDFO | NB_PCI_REG4C, AccessS3SaveWidth8, (UINT32)~BIT0, 0x0 , pConfig); } /*----------------------------------------------------------------------------------------*/ /** * Check if PCI Device Present * * * * @param[in] Device Device PCI address. * @param[in] NbConfigPtr Northbridge configuration block pointer. * * @retval TRUE Device present. * @retval FALSE Device not present. */ /*----------------------------------------------------------------------------------------*/ BOOLEAN LibNbIsDevicePresent ( IN PCI_ADDR Device, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 VendorId; LibNbPciRead (Device.AddressValue, AccessWidth32, &VendorId, NbConfigPtr); return (VendorId == 0xffffffff)?FALSE:TRUE; } /*----------------------------------------------------------------------------------------*/ /** * Check if IOMMU enabled * * * * @param[in] NbConfigPtr Northbridge configuration block pointer. * * @retval TRUE IOMMU not enabled. * @retval FALSE IOMMU not enabled. */ /*----------------------------------------------------------------------------------------*/ BOOLEAN LibNbIsIommuEnabled ( IN AMD_NB_CONFIG *NbConfigPtr ) { PCI_ADDR IommuAddress; IommuAddress.AddressValue = NbConfigPtr->NbPciAddress.AddressValue; IommuAddress.Address.Function = 2; if (LibNbIsDevicePresent (IommuAddress, NbConfigPtr)) { UINT8 Value; LibNbPciRead (IommuAddress.AddressValue | 0x44, AccessWidth8, &Value, NbConfigPtr); if ((Value & BIT0) != 0) { return TRUE; } } return FALSE; } /*----------------------------------------------------------------------------------------*/ /** * Reverse bit in DWORD. * Reverse bits in bitfield inside DWORD. * * * @param[in] Data Value to reverse. * @param[in] StartBit Start bit. * @param[in] StopBit Stop bit. * @retval Reversed Value. */ /*----------------------------------------------------------------------------------------*/ UINT32 LibNbBitReverse ( IN UINT32 Data, IN UINT8 StartBit, IN UINT8 StopBit ) { UINT32 Bitr; UINT32 Bitl; UINT32 Distance; while (StartBit < StopBit) { Bitr = Data & (1 << StartBit ); Bitl = Data & (1 << StopBit ); Distance = StopBit - StartBit; Data = (Data & ((UINT32)~(Bitl | Bitr))) | (Bitr << Distance ) | (Bitl >> Distance); StartBit++; StopBit--; } return Data; } /*----------------------------------------------------------------------------------------*/ /** * Read CPU family * * * * @retval 0xXX00000 CPU family. * */ UINT32 LibNbGetCpuFamily ( VOID ) { CPUID_DATA Cpuid; CpuidRead (0x1, &Cpuid); return Cpuid.EAX_Reg & 0xff00000; } /*----------------------------------------------------------------------------------------*/ /** * Load Firmware block * * * * @param[in] Address Address to load firmware * @param[in] Size Firmware block size * @param[in] FirmwareBlockPtr Pointer to firmware block * @param[in] NbConfigPtr Northbridge configuration block pointer. * */ VOID LibNbLoadMcuFirmwareBlock ( IN UINT16 Address, IN UINT16 Size, IN UINT32 *FirmwareBlockPtr, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 i; PCI_ADDR ClkPciAddress; UINT32 Selector; Selector = (Address >= 0x200)?0x0000000:0x10000; ClkPciAddress = NbConfigPtr->NbPciAddress; ClkPciAddress.Address.Function = 1; LibNbEnableClkConfig (NbConfigPtr); for (i = 0; i < Size; i++) { LibNbPciIndexWrite (ClkPciAddress.AddressValue | MC_CLK_INDEX, Selector | (Address + (i * 4)), AccessWidth32, &FirmwareBlockPtr[i], NbConfigPtr); } LibNbDisableClkConfig (NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Read SMU firmware ram * * * * @param[in] Address Address to read * @param[in] NbConfigPtr Northbridge configuration block pointer. * */ UINT32 LibNbReadMcuRam ( IN UINT16 Address, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 Value; PCI_ADDR ClkPciAddress; UINT32 Selector; Selector = (Address >= 0x200) ? 0x0000000 : 0x10000; ClkPciAddress = NbConfigPtr->NbPciAddress; ClkPciAddress.Address.Function = 1; LibNbEnableClkConfig (NbConfigPtr); LibNbPciIndexRead (ClkPciAddress.AddressValue | MC_CLK_INDEX, Selector | (Address), AccessWidth32, &Value, NbConfigPtr); LibNbDisableClkConfig (NbConfigPtr); return Value; } /*----------------------------------------------------------------------------------------*/ /** * MCU Control * * * * @param[in] Operation Set/Reset MCU controller * @param[in] NbConfigPtr Northbridge configuration block pointer. */ VOID LibNbMcuControl ( IN NB_MCU_MODE Operation, IN AMD_NB_CONFIG *NbConfigPtr ) { PCI_ADDR ClkPciAddress; UINT32 Value; Value = (Operation == AssertReset)?0x00000ee1:0x00000ee2; ClkPciAddress = NbConfigPtr->NbPciAddress; ClkPciAddress.Address.Function = 1; CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NBPCIE_TRACE), "LibNbMcuControl Operation [0x%x]\n", Operation)); LibNbEnableClkConfig (NbConfigPtr); LibNbPciIndexWrite (ClkPciAddress.AddressValue | MC_CLK_INDEX, 0x00030000, AccessWidth32, &Value, NbConfigPtr); LibNbDisableClkConfig (NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Read/Modify/Write memory space * * * * @param[in] Address Memory address. * @param[in] Width Access width * @param[in] Mask AND Mask * @param[in] Data OR Mask * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbMemRMW ( IN UINT64 Address, IN ACCESS_WIDTH Width, IN UINT32 Mask, IN UINT32 Data, IN AMD_NB_CONFIG *NbConfigPtr ) { UINT32 Value; LibNbMemRead (Address, Width, &Value, NbConfigPtr); Value = (Value & Mask) | Data; LibNbMemWrite (Address, Width, &Value, NbConfigPtr); } /*----------------------------------------------------------------------------------------*/ /** * Read memory space * * * * @param[in] Address Memory address. * @param[in] Width Access width * @param[in] Value Pointer to memory to store value * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbMemRead ( IN UINT64 Address, IN ACCESS_WIDTH Width, IN VOID *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { LibAmdMemRead (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr))); } /*----------------------------------------------------------------------------------------*/ /** * Write memory space * * * * @param[in] Address Memory address. * @param[in] Width Access width * @param[in] Value Pointer to memory to get value * @param[in] NbConfigPtr Northbridge configuration structure pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbMemWrite ( IN UINT64 Address, IN ACCESS_WIDTH Width, OUT VOID *Value, IN AMD_NB_CONFIG *NbConfigPtr ) { LibAmdMemWrite (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr))); } /*----------------------------------------------------------------------------------------*/ /** * Scan Pci Bridge * * * * @param[in] This Pointer to PCI topology scan protocol * @param[in] Bridge Address of PCI to PCI bridge to scan. */ SCAN_STATUS LibNbScanPciBridgeBuses ( IN PCI_SCAN_PROTOCOL *This, IN PCI_ADDR Bridge ) { SCAN_STATUS Status; UINT8 CurrentBus; UINT8 MinBus; UINT8 MaxBus; PCI_ADDR Device; CIMX_ASSERT (This != NULL); if (This->ScanBus == NULL) { return SCAN_FINISHED; } LibNbPciRead (Bridge.AddressValue | 0x19, AccessWidth8, &MinBus, This->pConfig); LibNbPciRead (Bridge.AddressValue | 0x1A, AccessWidth8, &MaxBus, This->pConfig); if (MinBus == 0 || MaxBus == 0) { return SCAN_FINISHED; } CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (This->pConfig), CIMX_NBPCIE_TRACE), " Scan bridge %d:%d:%d \n", Bridge.Address.Bus, Bridge.Address.Device, Bridge.Address.Function)); for (CurrentBus = MinBus; CurrentBus <= MaxBus; CurrentBus++) { Device.AddressValue = MAKE_SBDFO (0, CurrentBus, 0, 0, 0); Status = This->ScanBus (This, Device); } return SCAN_FINISHED; } /*----------------------------------------------------------------------------------------*/ /** * Scan Pci Bus * * * * @param[in] This Pointer to PCI topology scan protocol * @param[in] Device Pci address device to start bus scan from */ /*----------------------------------------------------------------------------------------*/ SCAN_STATUS LibNbScanPciBus ( IN PCI_SCAN_PROTOCOL *This, IN PCI_ADDR Device ) { SCAN_STATUS Status; UINT32 CurrentDevice; CIMX_ASSERT (This != NULL); if (This->ScanDevice == NULL) { return SCAN_FINISHED; } for (CurrentDevice = Device.Address.Device; CurrentDevice <= 0x1f; CurrentDevice++) { Device.Address.Device = CurrentDevice; if (LibNbIsDevicePresent (Device, This->pConfig)) { Status = This->ScanDevice (This, Device); if (Status == SCAN_STOP_BUS_ENUMERATION) { return Status; } } } return SCAN_FINISHED; } /*----------------------------------------------------------------------------------------*/ /** * Scan Pci Device * * * * @param[in] This Pointer to PCI topology scan protocol * @param[in] Device Pci address device to scan */ /*----------------------------------------------------------------------------------------*/ SCAN_STATUS LibNbScanPciDevice ( IN PCI_SCAN_PROTOCOL *This, IN PCI_ADDR Device ) { SCAN_STATUS Status; UINT8 Header; UINT32 CurrentFunction; UINT32 MaxFunction; CIMX_ASSERT (This != NULL); if (This->ScanFunction == NULL) { return SCAN_FINISHED; } LibNbPciRead (Device.AddressValue | 0x0E , AccessWidth8, &Header, This->pConfig); MaxFunction = (Header & 0x80)?7:0; for (CurrentFunction = Device.Address.Function; CurrentFunction <= MaxFunction; CurrentFunction++) { Device.Address.Function = CurrentFunction; if (LibNbIsDevicePresent (Device, This->pConfig)) { CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (This->pConfig), CIMX_NBPCIE_TRACE), " Scan function %d:%d:%d \n", Device.Address.Bus, Device.Address.Device, Device.Address.Function)); Status = This->ScanFunction (This, Device); if (Status == SCAN_STOP_DEVICE_ENUMERATION || Status == SCAN_STOP_BUS_ENUMERATION) { return Status; } } } return SCAN_FINISHED; } /*----------------------------------------------------------------------------------------*/ /** * Set default Indexes * * * @param[in] NbConfigPtr Northbridge configuration block pointer. */ /*----------------------------------------------------------------------------------------*/ VOID LibNbSetDefaultIndexes ( IN AMD_NB_CONFIG *NbConfigPtr ) { PCI_ADDR PciAddress; PORT PortId; LibNbPciRMW (NbConfigPtr->NbPciAddress.AddressValue | NB_HTIU_INDEX, AccessWidth32, 0x0, 0x0, NbConfigPtr); LibNbPciRMW (NbConfigPtr->NbPciAddress.AddressValue | NB_MISC_INDEX, AccessWidth32, 0x0, 0x0, NbConfigPtr); LibNbPciRMW (NbConfigPtr->NbPciAddress.AddressValue | NB_BIF_INDEX, AccessWidth32, 0x0, SB_CORE, NbConfigPtr); PciAddress.AddressValue = NbConfigPtr->NbPciAddress.AddressValue; for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { PciAddress.Address.Device = PortId; LibNbPciRMW (PciAddress.AddressValue | NB_BIF_INDEX, AccessWidth32, 0x0, 0x0, NbConfigPtr); } }