/* $NoKeywords:$ */ /** * @file * * mrndcton.c * * Northbridge DCT support for Ontario Recovery * * @xrefitem bom "File Content Label" "Release Content" * @e project: AGESA * @e sub-project: (Proc/Recovery/Mem) * @e \$Revision: 48803 $ @e \$Date: 2011-03-10 20:18:28 -0700 (Thu, 10 Mar 2011) $ * **/ /* ***************************************************************************** * * 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. * * *************************************************************************** * */ /* *---------------------------------------------------------------------------- * MODULES USED * *---------------------------------------------------------------------------- */ #include "AGESA.h" #include "OptionMemory.h" #include "PlatformMemoryConfiguration.h" #include "Ids.h" #include "amdlib.h" #include "mm.h" #include "mn.h" #include "mt.h" #include "mru.h" #include "mrnon.h" #include "cpuFamilyTranslation.h" #include "cpuCommonF14Utilities.h" #include "Filecode.h" #define FILECODE PROC_RECOVERY_MEM_NB_ON_MRNDCTON_FILECODE /*---------------------------------------------------------------------------- * DEFINITIONS AND MACROS * *---------------------------------------------------------------------------- */ #define RECDEF_CSMASK_REG 0x00003FE0 #define RECDEF_DRAM_BASE_REG 0x00000003 #define MAX_RD_DQS_DLY 0x1F #define DEFAULT_WR_ODT_ON_ON 6 #define DEFAULT_RD_ODT_ON_ON 6 /*---------------------------------------------------------------------------- * TYPEDEFS AND STRUCTURES * *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * PROTOTYPES OF LOCAL FUNCTIONS * *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * EXPORTED FUNCTIONS * *---------------------------------------------------------------------------- */ /* -----------------------------------------------------------------------------*/ /** * * This function gets platform specific config/timing values from the interface layer and * programs them into DCT. * * * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK * * @return TRUE - An Error value lower than AGESA_ERROR may have occurred * @return FALSE - An Error value greater than or equal to AGESA_ERROR may have occurred */ BOOLEAN MemRecNPlatformSpecON ( IN OUT MEM_NB_BLOCK *NBPtr ) { UINT32 AddrTmgValue; UINT32 DrvStrValue; UINT32 RODTCSLow; UINT32 WODTCSLow; CH_DEF_STRUCT *ChannelPtr; ChannelPtr = NBPtr->ChannelPtr; if (ChannelPtr->SODimmPresent != 0) { // SODIMM if (ChannelPtr->Dimms == 2) { AddrTmgValue = 0x00000039; DrvStrValue = 0x20222323; } else { AddrTmgValue = 0; DrvStrValue = 0x00002223; } } else { // UDIMM if (ChannelPtr->Dimms == 2) { AddrTmgValue = 0x00390039; DrvStrValue = 0x30222322; } else { AddrTmgValue = 0; DrvStrValue = 0x00112222; if (ChannelPtr->DimmDrPresent != 0) { AddrTmgValue = 0x003B0000; } } } MemRecNSetBitFieldNb (NBPtr, BFODCControl, DrvStrValue); MemRecNSetBitFieldNb (NBPtr, BFAddrTmgControl, AddrTmgValue); RODTCSLow = 0; if (ChannelPtr->Dimms == 2) { RODTCSLow = 0x01010404; WODTCSLow = 0x09050605; } else if (NBPtr->ChannelPtr->DimmDrPresent != 0) { WODTCSLow = 0x00000201; if (NBPtr->DimmToBeUsed == 1) { WODTCSLow = 0x08040000; } } else { WODTCSLow = 0x00000001; if (NBPtr->DimmToBeUsed == 1) { WODTCSLow = 0x00040000; } } MemRecNSetBitFieldNb (NBPtr, BFPhyRODTCSLow, RODTCSLow); MemRecNSetBitFieldNb (NBPtr, BFPhyWODTCSLow, WODTCSLow); return TRUE; } /* -----------------------------------------------------------------------------*/ /** * * This function sets the maximum round-trip latency in the system from the processor to the DRAM * devices and back. * * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK * @param[in] MaxRcvEnDly - Maximum receiver enable delay value * */ VOID MemRecNSetMaxLatencyON ( IN OUT MEM_NB_BLOCK *NBPtr, IN UINT16 MaxRcvEnDly ) { UINT32 N; UINT32 T; UINT32 P; UINT32 Px2; UINT32 MemClkPeriod; T = MemRecNTotalSyncComponentsClientNb (NBPtr); // P = P + CEIL(MAX (total delay in DqsRcvEn + RdDqsTime)) P = (MaxRcvEnDly + MAX_RD_DQS_DLY + 31) / 32; MemClkPeriod = 1000000 / DDR800_FREQUENCY; // P = P + 6.5 // T = T + 2586 ps Px2 = (P * 2) + 13; T += 2586; // N = (P/(MemClkFreq * 2) + T) * NclkFreq N = ((((Px2 * MemClkPeriod + 3) / 4) + T) * NBPtr->NBClkFreq + 999999) / 1000000; MemRecNSetBitFieldNb (NBPtr, BFMaxLatency, N); } /* -----------------------------------------------------------------------------*/ /** * * Set Dram ODT for mission mode and write leveling mode. * * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK * @param[in] OdtMode - Mission mode or write leveling mode * @param[in] ChipSelect - Chip select number * @param[in] TargetCS - Chip select number that is being trained * */ VOID MemRecNSetDramOdtON ( IN OUT MEM_NB_BLOCK *NBPtr, IN ODT_MODE OdtMode, IN UINT8 ChipSelect, IN UINT8 TargetCS ) { UINT8 Dimms; UINT8 DramTerm; UINT8 DramTermDyn; UINT8 WrLvOdt; UINT8 MaxDimmsPerChannel; Dimms = NBPtr->ChannelPtr->Dimms; // Dram nominal termination if (Dimms == 1) { DramTerm = 2; // 120 Ohms DramTermDyn = 0; // Disabled } else { DramTerm = 3; // 40 Ohms DramTermDyn = 2; // 120 Ohms } if (OdtMode == WRITE_LEVELING_MODE) { if (ChipSelect == TargetCS) { if (Dimms >= 2) { DramTerm = DramTermDyn; } MaxDimmsPerChannel = RecGetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, 0, NBPtr->ChannelPtr->ChannelID); if (MaxDimmsPerChannel == 2) { if (Dimms == 2) { WrLvOdt = 5; } else { // Dimms = 1 if (TargetCS == 0) { WrLvOdt = 1; } else { // TargetCS = 2 WrLvOdt = 4; } } } else { WrLvOdt = 1; } MemRecNSetBitFieldNb (NBPtr, BFWrLvOdt, WrLvOdt); } } MemRecNSetBitFieldNb (NBPtr, BFDramTerm, DramTerm); MemRecNSetBitFieldNb (NBPtr, BFDramTermDyn, DramTermDyn); } /* -----------------------------------------------------------------------------*/ /** * * This function programs the memory controller with configuration parameters * * * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK * * @return TRUE - An Error value lower than AGESA_ERROR may have occurred * @return FALSE - An Error value greater than or equal to AGESA_ERROR may have occurred */ BOOLEAN MemRecNAutoConfigON ( IN OUT MEM_NB_BLOCK *NBPtr ) { UINT8 Dimm; UINT8 ChipSel; UINT32 CSBase; UINT32 NBClkFreq; UINT8 i; DCT_STRUCT *DCTPtr; CH_DEF_STRUCT *ChannelPtr; DCTPtr = NBPtr->DCTPtr; ChannelPtr = NBPtr->ChannelPtr; // Force NB P-state to NBP0 F14NbPstateInit (DDR800_FREQUENCY, 6, 0, &NBClkFreq, &(NBPtr->MemPtr->StdHeader)); MemRecNSetBitFieldNb (NBPtr, BFNbPsCtrlDis, 1); //Prepare variables for future usage. for (Dimm = 0; Dimm < 2; Dimm++) { if ((ChannelPtr->ChDimmValid & (UINT8) 1 << Dimm) != 0) { DCTPtr->Timings.CsPresent |= (UINT16) 1 << (Dimm * 2); if (((ChannelPtr->DimmDrPresent & (UINT8) 1 << Dimm) == 0) && ((ChannelPtr->DimmQrPresent & (UINT8) 1 << Dimm) == 0)) { continue; } else { DCTPtr->Timings.CsPresent |= (UINT16) 1 << (Dimm * 2 + 1); } } } //Temporarily set all CS Base/Limit registers (corresponding to Dimms exist on a channel) with 256MB size for WL training. CSBase = 0; for (ChipSel = 0; ChipSel < 4; ChipSel++) { if (DCTPtr->Timings.CsPresent & (UINT8) 1 << ChipSel) { CSBase &= (UINT32) ~0x08; //Clear OnDimmMirror bit. if (((ChipSel & 1) != 0) && ((ChannelPtr->DimmMirrorPresent & (UINT8) 1 << (ChipSel >> 1)) != 0)) { CSBase |= (UINT32) 0x08; //Set OnDimmMirror bit. } MemRecNSetBitFieldNb (NBPtr, (BFCSBaseAddr0Reg + ChipSel), (CSBase | 0x01)); CSBase += 0x100000; if ((ChipSel & 1) == 0) { MemRecNSetBitFieldNb (NBPtr, (BFCSMask0Reg + (ChipSel >> 1)), RECDEF_CSMASK_REG); } } } MemRecNSetBitFieldNb (NBPtr, BFDramBaseReg0, RECDEF_DRAM_BASE_REG); MemRecNSetBitFieldNb (NBPtr, BFDramLimitReg0, 0x70000); // Use default values for common registers i = 0; while (NBPtr->RecModeDefRegArray[i] != NULL) { MemRecNSetBitFieldNb (NBPtr, NBPtr->RecModeDefRegArray[i], NBPtr->RecModeDefRegArray[i + 1]); i += 2; } //====================================================================== // Build Dram Config Misc Register Value //====================================================================== // // Max out Non-SPD timings MemRecNSetBitFieldNb (NBPtr, BFTwrrdSD, 0xA); MemRecNSetBitFieldNb (NBPtr, BFTrdrdSD, 0x8); MemRecNSetBitFieldNb (NBPtr, BFTwrwrSD, 0x9); MemRecNSetBitFieldNb (NBPtr, BFWrOdtOnDuration, DEFAULT_WR_ODT_ON_ON); MemRecNSetBitFieldNb (NBPtr, BFRdOdtOnDuration, DEFAULT_RD_ODT_ON_ON); MemRecNSetBitFieldNb (NBPtr, BFWrOdtTrnOnDly, 0); MemRecNSetBitFieldNb (NBPtr, BFRdOdtTrnOnDly, 6 - 5); //====================================================================== // DRAM MRS Register, set ODT //====================================================================== MemRecNSetBitFieldNb (NBPtr, BFBurstCtrl, 1); // // Recommended registers setting BEFORE DRAM device initialization and training // MemRecNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1); MemRecNSetBitFieldNb (NBPtr, BFZqcsInterval, 0); MemRecNSetBitFieldNb (NBPtr, BFRxMaxDurDllNoLock, 0); MemRecNSetBitFieldNb (NBPtr, BFTxMaxDurDllNoLock, 0); MemRecNSetBitFieldNb (NBPtr, BFEnRxPadStandby, 0); MemRecNSetBitFieldNb (NBPtr, BFPrefCpuDis, 1); MemRecNSetBitFieldNb (NBPtr, BFDctWrLimit, 0x1F); MemRecNSetBitFieldNb (NBPtr, BFEnCpuSerRdBehindNpIoWr, 1); MemRecNSetBitFieldNb (NBPtr, BFDbeGskMemClkAlignMode, 0); MemRecNSetBitFieldNb (NBPtr, BFMaxLatency, 0x12); MemRecNSetBitFieldNb (NBPtr, BFTraceModeEn, 0); // Enable cut through mode for NB P0 MemRecNSetBitFieldNb (NBPtr, BFDisCutThroughMode, 0); return TRUE; } /* -----------------------------------------------------------------------------*/ /** * * This function overrides the seed for hardware based RcvEn training of Ontario. * * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK * @param[in,out] *SeedPtr - Pointer to the seed value. * * @return TRUE */ BOOLEAN MemRecNOverrideRcvEnSeedON ( IN OUT MEM_NB_BLOCK *NBPtr, IN OUT VOID *SeedPtr ) { *(UINT16*) SeedPtr = 0x5B; return TRUE; } /*---------------------------------------------------------------------------- * LOCAL FUNCTIONS * *---------------------------------------------------------------------------- */