| /** |
| * @file |
| * |
| * NB Initialization. |
| * |
| * Init IOAPIC/IOMMU/Misc NB features. |
| * |
| * @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" |
| |
| /*---------------------------------------------------------------------------------------- |
| * 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 |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Early post validate input parameters |
| * |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| |
| AGESA_STATUS |
| NbLibEarlyPostInitValidateInput ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| AGESA_STATUS Status; |
| NB_CONFIG *pNbConfig; |
| NB_INFO NbInfo; |
| |
| Status = AGESA_SUCCESS; |
| NbInfo = LibNbGetRevisionInfo (pConfig); |
| if (NbInfo.Type == NB_UNKNOWN) { |
| return AGESA_FATAL; |
| } |
| pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| if (pNbConfig->sHeader.InitializerID != INITIALIZED_BY_INITIALIZER) { |
| Status = NbLibInitializer (pConfig); |
| } |
| if (pNbConfig->SysMemoryTomBelow4G == 0) { |
| Status = AGESA_FATAL; |
| } |
| //pNbConfig->sHeader.InitializerID = PH_AmdEarlyPostInit; |
| return Status; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Mid/Late post validate input parameters |
| * |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| |
| AGESA_STATUS |
| NbLibPostInitValidateInput ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| AGESA_STATUS Status; |
| NB_CONFIG *pNbConfig; |
| NB_INFO NbInfo; |
| |
| NbInfo = LibNbGetRevisionInfo (pConfig); |
| Status = AGESA_SUCCESS; |
| if (NbInfo.Type == NB_UNKNOWN) { |
| return AGESA_FATAL; |
| } |
| pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| if (pNbConfig->sHeader.InitializerID != INITIALIZED_BY_INITIALIZER) { |
| Status = AGESA_FATAL; |
| } |
| //pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| //if (pNbConfig->sHeader.InitializerID != PH_AmdEarlyPostInit) { |
| // return AGESA_FATAL; |
| //} |
| return Status; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Prepare NB to boot to OS. |
| * |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| |
| AGESA_STATUS |
| NbLibPrepareToOS ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG00, AccessS3SaveWidth32, 0xffffffff, BIT7, pConfig); |
| return AGESA_SUCCESS; |
| } |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Set Multiple NB support |
| * |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| |
| VOID |
| NbMultiNbIocInit ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| UINT32 Value; |
| NB_CONFIG *pNbConfig; |
| |
| pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| if (GET_BLOCK_CONFIG_PTR (pConfig)->NumberOfNorthbridges > 0) { |
| if (pConfig->NbPciAddress.AddressValue == 0) { |
| //Primary NB |
| Value = BIT3 + (HT_INTERRUPT_ENCODING_OFFSET << 4); |
| } else { |
| //Secondary NB |
| Value = BIT2 + (HT_INTERRUPT_ENCODING_OFFSET << 4); |
| } |
| LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG75, AccessS3SaveWidth32, (UINT32)~((0x7f << 2) + BIT28) , Value, pConfig); |
| } |
| LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG75, AccessS3SaveWidth32, (UINT32)~(BIT9 + BIT10 + BIT28), pNbConfig->P2PMode << 9, pConfig); |
| } |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Set NB SSID/SVID. |
| * |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| |
| VOID |
| NbLibSetSSID ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| NB_CONFIG *pNbConfig; |
| |
| pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| if (pNbConfig->SSID == 0xffffffff) { |
| LibNbPciRead (pConfig->NbPciAddress.AddressValue, AccessWidth32, &pNbConfig->SSID, pConfig); |
| } |
| if (pNbConfig->SSID != 0) { |
| LibNbPciWrite (pConfig->NbPciAddress.AddressValue | NB_PCI_REG50, AccessS3SaveWidth32, &pNbConfig->SSID, pConfig); |
| } |
| } |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Setup UnitId clamping |
| * |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| |
| VOID |
| NbLibSetupClumping ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| UINT16 ClumpingCapability; |
| UINT16 Value; |
| NB_CONFIG *pNbConfig; |
| |
| pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| Value = 0; |
| if (LibNbGetCpuFamily () == CPU_FAMILY_NPT) { |
| return; |
| } |
| LibNbPciRead (pConfig->NbPciAddress.AddressValue | NB_PCI_REG58, AccessS3SaveWidth16, &ClumpingCapability, pConfig); |
| if ((ClumpingCapability & BIT3) != 0 && |
| (pNbConfig->UnitIdClumping & DEV3_CLUMPING) != 0 && |
| !LibNbIsDevicePresent (PcieLibGetPortPciAddress (3, pConfig), pConfig)) { |
| Value |= BIT3; |
| } |
| if ((ClumpingCapability & BIT12) != 0 && |
| (pNbConfig->UnitIdClumping & DEV12_CLUMPING) != 0 && |
| !LibNbIsDevicePresent (PcieLibGetPortPciAddress (12, pConfig), pConfig)) { |
| Value |= BIT12; |
| } |
| if (Value != 0) { |
| LibNbPciRMW (pConfig->NbPciAddress.AddressValue | NB_PCI_REG5C, AccessS3SaveWidth16, 0xffff, Value, pConfig); |
| LibNbPciRMW (MAKE_SBDFO (0, 0, pConfig->NbHtPath.NodeID + 0x18, 0, HT_PATH_LINK_ID (pConfig->NbHtPath) * 4 + HT_PATH_SUBLINK_ID (pConfig->NbHtPath) * 0x10 + 0x110), AccessS3SaveWidth16, 0xffff, Value, pConfig); |
| } |
| } |
| |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Set top of memory in NB. |
| * NB will not pass to CPU any upstream DMA request to address above TOM and TOM2 |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| |
| AGESA_STATUS |
| NbLibSetTopOfMemory ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| NB_CONFIG *pNbConfig; |
| UINT32 RD890_TOM2; |
| UINT32 RD890_TOM3; |
| |
| RD890_TOM2 = 0; |
| RD890_TOM3 = 0; |
| pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| if (pNbConfig->SysMemoryTomBelow4G != 0) { |
| LibNbPciRMW (pConfig->NbPciAddress.AddressValue | NB_PCI_REG90, AccessS3SaveWidth32, 0, ((UINT32)pNbConfig->SysMemoryTomBelow4G) << 20, pConfig); |
| } |
| if (pNbConfig->SysMemoryTomAbove4G != 0) { |
| if ((pNbConfig->SysMemoryTomAbove4G - 1) <= 0xfffff) { |
| RD890_TOM2 = pNbConfig->SysMemoryTomAbove4G; |
| } else { |
| RD890_TOM2 = (UINT32) (0xFD00000000 >> 20); |
| RD890_TOM3 = pNbConfig->SysMemoryTomAbove4G; |
| } |
| } |
| if (RD890_TOM2 != 0) { |
| LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG31, AccessS3SaveWidth32, 0, (RD890_TOM2 >> 12), pConfig); |
| LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG30, AccessS3SaveWidth32, 0, (RD890_TOM2 << 20) | 1, pConfig); |
| } |
| if (RD890_TOM3 != 0) { |
| LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG4E, AccessS3SaveWidth32, 0, ((UINT32)pNbConfig->SysMemoryTomAbove4G >> 2) | BIT31, pConfig); |
| } |
| return AGESA_SUCCESS; |
| } |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Loget COre APic ID and dtore to scratch |
| * |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| AGESA_STATUS |
| NbLibGetCore0ApicId ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| UINT64 Value; |
| UINT32 Apic20; |
| NB_CONFIG *pNbConfig; |
| |
| pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| LibAmdMsrRead (0x0000001B, &Value, (AMD_CONFIG_PARAMS *)pConfig); |
| LibNbMemRead ((Value & 0xfffffffff000) + 0x20, AccessWidth32, &Apic20, pConfig); |
| pNbConfig->Reserved = (UINT16) (Apic20 >> 24); |
| return AGESA_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Direct NMI message to Core 0 |
| * |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| VOID |
| NbLibSetNmiRouting ( |
| IN AMD_NB_CONFIG *pConfig |
| ) |
| { |
| NB_CONFIG *pNbConfig; |
| |
| pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| LibNbPciIndexRMW ( |
| pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, |
| NB_MISC_REG12, |
| AccessS3SaveWidth32, |
| 0x00ffffff, |
| (UINT32)pNbConfig->Reserved << 24, |
| pConfig); |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * AMD structures initializer for all NB. |
| * |
| * |
| * |
| * @param[in] ConfigPtr Northbridges configuration block pointer. |
| * |
| */ |
| |
| AGESA_STATUS |
| AmdNbInitializer ( |
| IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr |
| ) |
| { |
| AGESA_STATUS Status; |
| Status = LibNbApiCall (NbLibInitializer, ConfigPtr); |
| return Status; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * NB config structure initializer |
| * |
| * |
| * |
| * @param[in] pConfig Northbridge configuration structure pointer. |
| * |
| */ |
| /*----------------------------------------------------------------------------------------*/ |
| AGESA_STATUS |
| NbLibInitializer ( |
| IN OUT AMD_NB_CONFIG *pConfig |
| ) |
| { |
| UINT64 Value64; |
| NB_CONFIG *pNbConfig; |
| |
| pNbConfig = GET_NB_CONFIG_PTR (pConfig); |
| if (pNbConfig == NULL) { |
| return AGESA_WARNING; |
| } |
| if (pNbConfig->sHeader.InitializerID == INITIALIZED_BY_INITIALIZER) { |
| return AGESA_SUCCESS; |
| } |
| LibAmdMemFill (pNbConfig, 0, sizeof (NB_CONFIG), (AMD_CONFIG_PARAMS *)&(pNbConfig->sHeader)); |
| pNbConfig->sHeader.InitializerID = INITIALIZED_BY_INITIALIZER; |
| // Get TOM and TOM2 |
| LibAmdMsrRead (0xC001001a, &Value64, (AMD_CONFIG_PARAMS *)pConfig); |
| pNbConfig->SysMemoryTomBelow4G = (UINT16) (Value64 >> 20); |
| LibAmdMsrRead (0xC0010010, &Value64, (AMD_CONFIG_PARAMS *)pConfig); |
| if ((Value64 & BIT21) != 0) { |
| LibAmdMsrRead (0xC001001d, &Value64, (AMD_CONFIG_PARAMS *)pConfig); |
| pNbConfig->SysMemoryTomAbove4G = (UINT32) (Value64 >> 20); |
| } |
| pNbConfig->P2PMode = 1; |
| pNbConfig->UnitIdClumping = 3; |
| return AGESA_SUCCESS; |
| } |
| |
| |