/* $NoKeywords:$ */ /** * @file * * AMD Family_15 Orochi NB COF VID Initialization * * Performs the "BIOS Northbridge COF and VID Configuration" as * described in the BKDG. * * @xrefitem bom "File Content Label" "Release Content" * @e project: AGESA * @e sub-project: CPU/Family/0x15/OR * @e \$Revision: 51891 $ @e \$Date: 2011-04-28 12:39:55 -0600 (Thu, 28 Apr 2011) $ * */ /* ****************************************************************************** * * 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 "AGESA.h" #include "amdlib.h" #include "cpuRegisters.h" #include "cpuF15PowerMgmt.h" #include "cpuF15OrPowerMgmt.h" #include "cpuApicUtilities.h" #include "OptionMultiSocket.h" #include "cpuServices.h" #include "GeneralServices.h" #include "cpuFamilyTranslation.h" #include "F15OrPmNbCofVidInit.h" #include "Filecode.h" CODE_GROUP (G3_DXE) RDATA_GROUP (G3_DXE) #define FILECODE PROC_CPU_FAMILY_0X15_OR_F15ORPMNBCOFVIDINIT_FILECODE /*---------------------------------------------------------------------------------------- * 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 *---------------------------------------------------------------------------------------- */ VOID STATIC F15OrPmNbCofVidInitOnCore ( IN AMD_CONFIG_PARAMS *StdHeader ); /*---------------------------------------------------------------------------------------- * E X P O R T E D F U N C T I O N S *---------------------------------------------------------------------------------------- */ extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration; /*---------------------------------------------------------------------------------------*/ /** * Family 15h Orochi core 0 entry point for performing the "Mixed Northbridge Frequency * Configuration Sequence" * * BIOS must match F5x1[6C:60][NbFid, NbDid, NbPstateEn] between all * processors of a multi-socket system. The lowest setting from all * processors is used as the common F5x1[6C:60][NbFid, NbDid]. All * processors must have the same number of NB P-states. * * For each node in the system { * For (i = 0; i <= F5x170[NbPstateMaxVal]; i++) { * NewNbFreq = the lowest NBCOF from all processors for NB P-state i * NewNbFid = F5x1[6C:60][NbFid] that corresponds to NewNbFreq * NewNbDid = F5x1[6C:60][NbDid] that corresponds to NewNbFreq * Write NewNbFid and NewNbDid to F5x1[6C:60][NbFid, NbDid] indexed * by NB P-state i * } * If (F5x170[NbPstateMaxVal] == 0) { * Save F5x170 and F5x1[6C:60] indexed by NB P-state 1 * Copy F5x1[6C:60] indexed by NB P-state 0 to F5x1[6C:60] indexed by NB P-state 1 * Write 1 to F5x170[NbPstateMaxVal, NbPstateLo] * Write 0 to F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold] * Wait for F5x174[CurNbPstate] = F5x170[NbPstateLo] and F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from F5x1[6C:60] indexed by F5x170[NbPstateLo] * Restore F5x170 and F5x1[6C:60] indexed by NB P-state 1 * Wait for F5x174[CurNbPstate] = F5x170[NbPstateHi] * } * } * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParamsPtr Service related parameters (unused). * @param[in] StdHeader Config handle for library and services. * */ VOID F15OrPmNbCofVidInit ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 i; UINT32 NbFreq; UINT32 NbDiv; UINT32 LocalPciRegister; UINT32 AndMask; UINT32 OrMask; UINT32 Ignored; UINT32 NbPsCtrl; UINT32 TaskedCore; BOOLEAN PstateSettingsChanged; BOOLEAN PstatesMatch; BOOLEAN PstateEnabledAll; AP_TASK TaskPtr; PCI_ADDR PciAddress; AGESA_STATUS IgnoredSts; // Get the local node ID IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); ASSERT (Core == 0); PstateSettingsChanged = FALSE; GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); PciAddress.Address.Function = FUNC_5; PciAddress.Address.Register = NB_PSTATE_CTRL; LibAmdPciRead (AccessWidth32, PciAddress, &NbPsCtrl, StdHeader); for (i = 0; i <= ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrl)->NbPstateMaxVal; i++) { if (OptionMultiSocketConfiguration.GetSystemNbPstateSettings (i, &CpuEarlyParamsPtr->PlatformConfig, &NbFreq, &NbDiv, &PstatesMatch, &PstateEnabledAll, StdHeader)) { if (PstateEnabledAll) { // Valid system-wide NB P-state if (!PstatesMatch) { // Configure NbPstate[i] to match the slowest PciAddress.Address.Register = (NB_PSTATE_0 + (4 * i)); LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); OrMask = 0x00000000; ((NB_PSTATE_REGISTER *) &OrMask)->NbFid = ((NbFreq / 200) - 4); ((NB_PSTATE_REGISTER *) &OrMask)->NbDid = (UINT32) LibAmdBitScanForward (NbDiv); if ((((NB_PSTATE_REGISTER *) &OrMask)->NbFid != ((NB_PSTATE_REGISTER *) &LocalPciRegister)->NbFid) || (((NB_PSTATE_REGISTER *) &OrMask)->NbDid != ((NB_PSTATE_REGISTER *) &LocalPciRegister)->NbDid)) { AndMask = 0xFFFFFFFF; ((NB_PSTATE_REGISTER *) &AndMask)->NbFid = 0; ((NB_PSTATE_REGISTER *) &AndMask)->NbDid = 0; OptionMultiSocketConfiguration.ModifyCurrSocketPci (&PciAddress, AndMask, OrMask, StdHeader); PstateSettingsChanged = TRUE; } } } else { // At least one processor in the system does not have NbPstate[i] PciAddress.Address.Register = NB_PSTATE_CTRL; AndMask = 0xFFFFFFFF; ((NB_PSTATE_CTRL_REGISTER *) &AndMask)->NbPstateMaxVal = 0; OrMask = 0; if (i != 0) { ((NB_PSTATE_CTRL_REGISTER *) &OrMask)->NbPstateMaxVal = (i - 1); } // Modify NbPstateMaxVal to reflect the system value OptionMultiSocketConfiguration.ModifyCurrSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // Disable this NB P-state PciAddress.Address.Register = (NB_PSTATE_0 + (4 * i)); AndMask = 0xFFFFFFFF; ((NB_PSTATE_REGISTER *) &AndMask)->NbPstateEn = 0; OrMask = 0; OptionMultiSocketConfiguration.ModifyCurrSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // Log error for the invalid configuration PutEventLog (AGESA_ERROR, CPU_ERROR_PM_NB_PSTATE_MISMATCH, Socket, i, 0, 0, StdHeader); break; } } } if (PstateSettingsChanged) { PciAddress.Address.Register = NB_PSTATE_CTRL; LibAmdPciRead (AccessWidth32, PciAddress, &NbPsCtrl, StdHeader); if (((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrl)->NbPstateMaxVal == 0) { // Launch one core per node. TaskPtr.FuncAddress.PfApTask = F15OrPmNbCofVidInitOnCore; TaskPtr.DataTransfer.DataSizeInDwords = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetGivenModuleCoreRange (Socket, Module, &TaskedCore, &Ignored, StdHeader)) { if (TaskedCore != 0) { ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) TaskedCore, &TaskPtr, StdHeader); } } } ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, (VOID *) CpuEarlyParamsPtr); } } } /*--------------------------------------------------------------------------------------- * L O C A L F U N C T I O N S *--------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------*/ /** * Support routine for F15OrPmNbCofVidInit to perform the actual NB P-state transition * to the leveled NB P-state settings on one core of each die in a family 15h socket. * * The following steps are performed: * 1. Save F5x170 and F5x1[6C:60] indexed by NB P-state 1 * 2. Copy F5x1[6C:60] indexed by NB P-state 0 to F5x1[6C:60] indexed by NB P-state 1 * 3, Write 1 to F5x170[NbPstateMaxVal, NbPstateLo] * 4. Write 0 to F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold] * 5. Wait for F5x174[CurNbPstate] = F5x170[NbPstateLo] and F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from F5x1[6C:60] indexed by F5x170[NbPstateLo] * 6. Restore F5x170 and F5x1[6C:60] indexed by NB P-state 1 * 7. Wait for F5x174[CurNbPstate] = F5x170[NbPstateHi] * * @param[in] StdHeader Config handle for library and services. * */ VOID STATIC F15OrPmNbCofVidInitOnCore ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 NbPsCtrl; UINT32 NbPs0; UINT32 NbPs1; UINT32 LocalPciRegister; PCI_ADDR PciAddress; OptionMultiSocketConfiguration.GetCurrPciAddr (&PciAddress, StdHeader); // Save F5x170 and F5x164 PciAddress.Address.Function = FUNC_5; PciAddress.Address.Register = NB_PSTATE_CTRL; LibAmdPciRead (AccessWidth32, PciAddress, &NbPsCtrl, StdHeader); PciAddress.Address.Register = NB_PSTATE_0; LibAmdPciRead (AccessWidth32, PciAddress, &NbPs0, StdHeader); PciAddress.Address.Register = NB_PSTATE_1; LibAmdPciRead (AccessWidth32, PciAddress, &NbPs1, StdHeader); // Copy F5x160 to F5x164 LibAmdPciWrite (AccessWidth32, PciAddress, &NbPs0, StdHeader); // Write 1 to F5x170[NbPstateMaxVal, NbPstateLo] PciAddress.Address.Register = NB_PSTATE_CTRL; LocalPciRegister = NbPsCtrl; ((NB_PSTATE_CTRL_REGISTER *) &LocalPciRegister)->NbPstateMaxVal = 1; ((NB_PSTATE_CTRL_REGISTER *) &LocalPciRegister)->NbPstateLo = 1; LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // Write 0 to F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold] ((NB_PSTATE_CTRL_REGISTER *) &LocalPciRegister)->SwNbPstateLoDis = 0; ((NB_PSTATE_CTRL_REGISTER *) &LocalPciRegister)->NbPstateDisOnP0 = 0; ((NB_PSTATE_CTRL_REGISTER *) &LocalPciRegister)->NbPstateThreshold = 0; LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // Wait for F5x174[CurNbPstate] = F5x170[NbPstateLo] (written to 1 above) and // F5x174[CurNbFid, CurNbDid] = F5x164[NbFid, NbDid] PciAddress.Address.Register = NB_PSTATE_STATUS; do { LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); } while ((((NB_PSTATE_STS_REGISTER *) &LocalPciRegister)->CurNbPstate != 1) && (((NB_PSTATE_STS_REGISTER *) &LocalPciRegister)->CurNbFid != ((NB_PSTATE_REGISTER *) &NbPs0)->NbFid) && (((NB_PSTATE_STS_REGISTER *) &LocalPciRegister)->CurNbDid != ((NB_PSTATE_REGISTER *) &NbPs0)->NbDid)); // Restore F5x170 and F5x164 PciAddress.Address.Register = NB_PSTATE_CTRL; LibAmdPciWrite (AccessWidth32, PciAddress, &NbPsCtrl, StdHeader); PciAddress.Address.Register = NB_PSTATE_1; LibAmdPciWrite (AccessWidth32, PciAddress, &NbPs1, StdHeader); // Wait for F5x174[CurNbPstate] = F5x170[NbPstateHi] PciAddress.Address.Register = NB_PSTATE_STATUS; do { LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); } while (((NB_PSTATE_STS_REGISTER *) &LocalPciRegister)->CurNbPstate != ((NB_PSTATE_CTRL_REGISTER *) &NbPsCtrl)->NbPstateHi); }