summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB')
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnS3tn.h111
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mndcttn.c906
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnflowtn.c156
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnidendimmtn.c172
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnmcttn.c562
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnottn.c348
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnphytn.c742
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnregtn.c856
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mns3tn.c1498
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mntn.c618
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mntn.h341
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mn.c530
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnS3.c1493
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mndct.c3613
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnfeat.c1418
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnflow.c359
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnmct.c1313
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnphy.c2059
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnreg.c608
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mntrain3.c269
20 files changed, 17972 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnS3tn.h b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnS3tn.h
new file mode 100644
index 0000000000..7014b8a00c
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnS3tn.h
@@ -0,0 +1,111 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnS3tn.h
+ *
+ * S3 resume memory related function for TN.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+#ifndef _MNS3TN_H_
+#define _MNS3TN_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+/// ID for register list of TN
+typedef enum {
+ PCI_LST_ESR_TN, ///< Assign 0x0000 for PCI register list for pre exit self refresh.
+ PCI_LST_TN, ///< Assign 0x0001 for PCI register list for post exist self refresh.
+ CPCI_LST_ESR_TN, ///< Assign 0x0002 for conditional PCI register list for pre exit self refresh.
+ CPCI_LST_TN, ///< Assign 0x0003 for conditional PCI register list for post exit self refresh.
+ MSR_LST_ESR_TN, ///< Assign 0x0004 for MSR register list for pre exit self refresh.
+ MSR_LST_TN, ///< Assign 0x0005 for MSR register list for post exit self refresh.
+ CMSR_LST_ESR_TN, ///< Assign 0x0006 for conditional MSR register list for pre exit self refresh.
+ CMSR_LST_TN ///< Assign 0x0007 for conditional MSR register list for post exit self refresh.
+} RegisterListIDTN;
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+#define SET_S3_NB_PSTATE_OFFSET(Offset, NBPstate) ((NBPstate << 10) | Offset)
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#endif //_MNS3TN_H_
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mndcttn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mndcttn.c
new file mode 100644
index 0000000000..6bbcb70b93
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mndcttn.c
@@ -0,0 +1,906 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mndcttn.c
+ *
+ * Northbridge DCT support for TN
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 63661 $ @e \$Date: 2012-01-03 01:02:47 -0600 (Tue, 03 Jan 2012) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mu.h"
+#include "OptionMemory.h"
+#include "mntn.h"
+#include "mftds.h"
+#include "merrhdl.h"
+#include "cpuFamRegisters.h"
+#include "GeneralServices.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuCommonF15Utilities.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+
+#define FILECODE PROC_MEM_NB_TN_MNDCTTN_FILECODE
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define UNUSED_CLK 4
+#define MAX_RD_DQS_DLY 0x1F
+
+CONST BIT_FIELD_NAME MemPstateBF[4] = {BFMemPstate0, BFMemPstate1, BFMemPstate2, BFMemPstate3};
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+UINT32
+STATIC
+MemNTotalSyncComponentsTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+extern BUILD_OPT_CFG UserOptions;
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * 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_FATAL may have occurred
+ * @return FALSE - An Error value greater than or equal to AGESA_FATAL may have occurred
+ * @return NBPtr->MCTPtr->ErrCode - Contains detailed AGESA_STATUS value
+ */
+
+BOOLEAN
+MemNAutoConfigTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 i;
+ DIE_STRUCT *MCTPtr;
+ DCT_STRUCT *DCTPtr;
+ MEM_PARAMETER_STRUCT *RefPtr;
+ UINT32 PowerDownMode;
+
+ RefPtr = NBPtr->RefPtr;
+ MCTPtr = NBPtr->MCTPtr;
+ DCTPtr = NBPtr->DCTPtr;
+
+ //
+ //======================================================================
+ // Build Dram Config Lo Register Value
+ //======================================================================
+ MemNSetBitFieldNb (NBPtr, BFUnBuffDimm, 1);
+ MemNSetBitFieldNb (NBPtr, BFPendRefPaybackS3En, 1);
+ MemNSetBitFieldNb (NBPtr, BFStagRefEn, 1);
+ //
+ //======================================================================
+ // Build Dram Config Hi Register Value
+ //======================================================================
+ //
+ //
+ // MemClkFreq
+ //
+ MemNSetBitFieldNb (NBPtr, BFMemClkFreq, MemNGetMemClkFreqIdUnb (NBPtr, DCTPtr->Timings.Speed));
+
+ PowerDownMode = 1;
+ IDS_OPTION_HOOK (IDS_POWERDOWN_MODE, &PowerDownMode, &(NBPtr->MemPtr->StdHeader));
+ MemNSetBitFieldNb (NBPtr, BFPowerDownMode, PowerDownMode);
+
+ if (NBPtr->MemPstateStage == MEMORY_PSTATE_1ST_STAGE) {
+ MemNBrdcstSetNb (NBPtr, BFM1MemClkFreq, MemNGetMemClkFreqIdUnb (NBPtr, DDR667_FREQUENCY));
+ MemNBrdcstSetNb (NBPtr, BFRate, MemNGetMemClkFreqIdUnb (NBPtr, DDR667_FREQUENCY) | 0x8);
+ MemNBrdcstSetNb (NBPtr, BFMxMrsEn, 7);
+ }
+
+ MemNSetBitFieldNb (NBPtr, BFDphyMemPsSelEn, 1);
+ //
+ //======================================================================
+ // Build Dram MRS Register Value
+ //======================================================================
+ //
+ MemNSetBitFieldNb (NBPtr, BFPchgPDModeSel, 1);
+ MemNSetBitFieldNb (NBPtr, BFBurstCtrl, 1);
+
+ //======================================================================
+ // DRAM Controller Miscellaneous 2
+ //======================================================================
+ MemNSetBitFieldNb (NBPtr, BFPerRankTimingEn, 1);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\nEnable Per Rank Training....\n\n");
+ MemNSetBitFieldNb (NBPtr, BFPrtlChPDEnhEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFAggrPDEn, 1);
+
+ //======================================================================
+ // GMC to DCT control
+ //======================================================================
+ MemNSetBitFieldNb (NBPtr, BFGmcTokenLimit, 4);
+ MemNSetBitFieldNb (NBPtr, BFMctTokenLimit, 4);
+ MemNSetBitFieldNb (NBPtr, BFGmcToDctControl1, 0x4444);
+ if ((MCTPtr->LogicalCpuid.Revision & 0x0000000000000100ull ) != 0) {
+ MemNSetBitFieldNb (NBPtr, BFCpuElevPrioDis, 1);
+ }
+
+ //======================================================================
+ // Other Registers
+ //======================================================================
+ //
+ //
+ // Non-SPD Timings
+ //
+ MemNSetBitFieldNb (NBPtr, BFTrwtWB, 0x17);
+ MemNSetBitFieldNb (NBPtr, BFTrwtTO, 0x16);
+ MemNSetBitFieldNb (NBPtr, BFTwrrd, 0xB );
+
+ MemNSetBitFieldNb (NBPtr, BFTrdrdSdSc, 0xB);
+ MemNSetBitFieldNb (NBPtr, BFTrdrdSdDc, 0xB);
+ MemNSetBitFieldNb (NBPtr, BFTrdrdDd, 0xB);
+
+ MemNSetBitFieldNb (NBPtr, BFTwrwrSdSc, 0xB);
+ MemNSetBitFieldNb (NBPtr, BFTwrwrSdDc, 0xB);
+ MemNSetBitFieldNb (NBPtr, BFTwrwrDd, 0xB);
+
+ MemNSetBitFieldNb (NBPtr, BFWrOdtOnDuration, DEFAULT_WR_ODT_TN);
+ MemNSetBitFieldNb (NBPtr, BFRdOdtOnDuration, DEFAULT_RD_ODT_TN);
+ MemNSetBitFieldNb (NBPtr, BFWrOdtTrnOnDly, DEFAULT_RD_ODT_TRNONDLY_TN);
+
+ for (i = 0; i < 4; i++) {
+ MemNSetBitFieldNb (NBPtr, BFTstag0 + i, 0x14);
+ }
+
+ MemNSetBitFieldNb (NBPtr, BFTmrd, 4);
+ MemNSetBitFieldNb (NBPtr, BFFlushWrOnS3StpGnt, 1);
+ MemNSetBitFieldNb (NBPtr, BFFastSelfRefEntryDis, 0);
+
+ return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function caps speed based on battery life check.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ */
+VOID
+MemNCapSpeedBatteryLifeTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST UINT16 SupportedFreq[] = {
+ DDR2133_FREQUENCY,
+ DDR1866_FREQUENCY,
+ DDR1600_FREQUENCY,
+ DDR1333_FREQUENCY,
+ DDR1066_FREQUENCY,
+ DDR800_FREQUENCY,
+ DDR667_FREQUENCY
+ };
+
+ UINT32 FreqNumeratorInMHz;
+ UINT32 FreqDivisor;
+ UINT32 VoltageInuV;
+ UINT32 NBFreq;
+ UINT16 DdrFreq;
+ UINT16 j;
+ INT8 NbPs;
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+ BOOLEAN SkipAdjustNbPs;
+
+ FamilySpecificServices = NULL;
+ GetCpuServicesOfSocket (NBPtr->MCTPtr->SocketId, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &(NBPtr->MemPtr->StdHeader));
+
+
+ // Find the lowest supported NB Pstate
+ NBFreq = 0;
+ for (NbPs = 3; NbPs >= 0; NbPs--) {
+ if (FamilySpecificServices->GetNbPstateInfo (FamilySpecificServices,
+ NBPtr->MemPtr->PlatFormConfig,
+ &NBPtr->PciAddr,
+ (UINT32) NbPs,
+ &FreqNumeratorInMHz,
+ &FreqDivisor,
+ &VoltageInuV,
+ &(NBPtr->MemPtr->StdHeader))) {
+ if (MemNGetBitFieldNb (NBPtr, MemPstateBF[NbPs]) == 0) {
+ NBFreq = FreqNumeratorInMHz / FreqDivisor;
+ break;
+ }
+ }
+ }
+
+ ASSERT (NBFreq > 0);
+
+ // Pick Max MEMCLK that is less than or equal to NCLK
+ DdrFreq = DDR800_FREQUENCY;
+ for (j = 0; j < GET_SIZE_OF (SupportedFreq); j++) {
+ if (NBFreq >= ((UINT32) SupportedFreq[j])) {
+ DdrFreq = SupportedFreq[j];
+ break;
+ }
+ }
+
+ // Cap MemClk frequency to lowest NCLK frequency
+ if (NBPtr->DCTPtr->Timings.TargetSpeed > DdrFreq) {
+ NBPtr->DCTPtr->Timings.TargetSpeed = DdrFreq;
+ }
+
+ // Adjust the NB P-state northbridge voltage
+ SkipAdjustNbPs = FALSE;
+ IDS_OPTION_HOOK (IDS_NBPSDIS_OVERRIDE, &SkipAdjustNbPs, &(NBPtr->MemPtr->StdHeader));
+ if (SkipAdjustNbPs == FALSE) {
+ MemNAdjustNBPstateVolTN (NBPtr);
+ }
+
+ // Initialize NbPsCtlReg
+ NBPtr->NbPsCtlReg = 0;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function retrieves the Max latency parameters
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @param[in] *MinDlyPtr - Pointer to variable to store the Minimum Delay value
+ * @param[in] *MaxDlyPtr - Pointer to variable to store the Maximum Delay value
+ * @param[in] *DlyBiasPtr - Pointer to variable to store Delay Bias value
+ * @param[in] MaxRcvEnDly - Maximum receiver enable delay value
+ */
+
+VOID
+MemNGetMaxLatParamsTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 MaxRcvEnDly,
+ IN OUT UINT16 *MinDlyPtr,
+ IN OUT UINT16 *MaxDlyPtr,
+ IN OUT UINT16 *DlyBiasPtr
+ )
+{
+ UINT32 N;
+ UINT32 T;
+ UINT32 P;
+ UINT32 MemClkPeriod;
+
+ // 1. P = N = T = 0.
+ P = N = T = 0;
+
+ // Get all sync components BKDG steps 3,4,6
+ P = MemNTotalSyncComponentsTN (NBPtr);
+
+ // 7. P = P + CEIL(MAX(D18F2x9C_x0000_00[2A:10]_dct[1:0][DqsRcvEnGrossDelay, DqsRcvEnFineDelay] +
+ // D18F2x9C_x0000_0[3:0]0[7:5]_dct[1:0][RdDqsTime] PCLKs)) + 1
+ P = P + (MaxRcvEnDly + 31) / 32 + 1;
+
+ // 10. N = (P/(MemClkFreq * 2) + T) * NclkFreq; Convert from PCLKs plus time to NCLKs.
+ MemClkPeriod = 1000000 / ((NBPtr->MemPstate == MEMORY_PSTATE0) ? NBPtr->DCTPtr->Timings.Speed : DDR667_FREQUENCY);
+ N = ((((P * MemClkPeriod + 1) / 2) + T) * NBPtr->NBClkFreq + 999999) / 1000000;
+
+ // Calculate a starting MaxRdLatency delay value with steps 5, 9, and 12 excluded
+ *MinDlyPtr = (UINT16) N;
+
+ *MaxDlyPtr = 0x3FF;
+
+ // Left edge of MaxRdLat will be added with 1 NCLK and 3 PCLK (1.5 MEMCLK)
+ N = 1;
+ P = 3;
+ N += (((P * MemClkPeriod + 1) / 2) * NBPtr->NBClkFreq + 999999) / 1000000;
+ *DlyBiasPtr = (UINT16) N;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * 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
+MemNSetMaxLatencyTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 MaxRcvEnDly
+ )
+{
+ UINT32 N;
+ UINT32 T;
+ UINT32 P;
+ UINT32 Px2;
+ UINT32 MemClkPeriod;
+
+ AGESA_TESTPOINT (TpProcMemRcvrCalcLatency, &(NBPtr->MemPtr->StdHeader));
+
+ //
+ // Initial value for MaxRdLat used in training
+ //
+ N = 0x55;
+
+ if (MaxRcvEnDly != 0xFFFF) {
+ // 1. P = N = T = 0.
+ P = N = T = 0;
+
+ // Get all sync components BKDG steps 3,4,6
+ P = MemNTotalSyncComponentsTN (NBPtr);
+
+ // 5. P = P + 5
+ P += 5;
+
+ // 7. P = P + CEIL(MAX(D18F2x9C_x0000_00[2A:10]_dct[1:0][DqsRcvEnGrossDelay, DqsRcvEnFineDelay] +
+ // D18F2x9C_x0000_0[3:0]0[6:5]_dct[1:0][RdDqsTime] PCLKs)) + 1
+ P = P + ((MaxRcvEnDly + MAX_RD_DQS_DLY) + 31) / 32 + 1;
+
+ // 8. If (NclkFreq/MemClkFreq < 2) then P = P + 4.5 Else P = P + 2.5
+ if ((NBPtr->NBClkFreq / NBPtr->DCTPtr->Timings.Speed) < 2) {
+ Px2 = P * 2 + 9;
+ } else {
+ Px2 = P * 2 + 5;
+ }
+
+ // 9. T = T + 1050 ps
+ T += 1050;
+
+ // 10. N = (P/(MemClkFreq * 2) + T) * NclkFreq; Convert from PCLKs plus time to NCLKs.
+ MemClkPeriod = 1000000 / NBPtr->DCTPtr->Timings.Speed;
+ N = ((((Px2 * MemClkPeriod + 3) / 4) + T) * NBPtr->NBClkFreq + 999999) / 1000000;
+
+ // 11. D18F2x210_dct[1:0]_nbp[3:0][MaxRdLatency] = CEIL(N) - 1
+ N = N - 1;
+ }
+
+ NBPtr->DCTPtr->Timings.MaxRdLat = (UINT16) N;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMaxRdLat: %03x\n", N);
+ MemNSetBitFieldNb (NBPtr, BFMaxLatency, N);
+}
+
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function set MaxRdLat after HW receiver enable training is completed
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNExitPhyAssistedTrainingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ UINT8 Dct;
+ UINT8 ChipSel;
+ MEM_TECH_BLOCK *TechPtr;
+
+ TechPtr = NBPtr->TechPtr;
+
+ // Calculate Max Latency for both channels to prepare for position training
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN ; Dct++) {
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
+ NBPtr->SwitchDCT (NBPtr, Dct);
+
+ // Reset DisAutoRefresh and ZqcsInterval for position training.
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
+ MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
+ MemNSetBitFieldNb (NBPtr, BFRx4thStgEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFRxBypass3rd4thStg, 4);
+ }
+
+ if (TechPtr->FindMaxDlyForMaxRdLat (TechPtr, &ChipSel)) {
+ NBPtr->SetMaxLatency (NBPtr, TechPtr->MaxDlyForMaxRdLat);
+ }
+ }
+
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the total of sync components for Max Read Latency calculation
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return Total in PCLKs
+ */
+UINT32
+STATIC
+MemNTotalSyncComponentsTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 P;
+
+ P = 0;
+
+ // 3. If (D18F2x9C_x0000_0004_dct[1:0][AddrCmdSetup] = 0 & D18F2x9C_x0000_0004_dct[1:0][CsOdt-
+ // Setup] = 0 & D18F2x9C_x0000_0004_dct[1:0][CkeSetup] = 0)
+ // then P = P + 1
+ // else P = P + 2
+ if ((MemNGetBitFieldNb (NBPtr, BFAddrTmgControl) & 0x0202020) == 0) {
+ P += 1;
+ } else {
+ P += 2;
+ }
+
+ // 4. P = P + (8 - D18F2x210_dct[1:0]_nbp[3:0][RdPtrInit])
+ P = P + (8 - (UINT16) MemNGetBitFieldNb (NBPtr, BFRdPtrInit));
+
+ // 6. P = P + (2 * (D18F2x200_dct[1:0][Tcl] - 1 clocks))
+ P = P + (2 * (MemNGetBitFieldNb (NBPtr, BFTcl) - 1));
+
+ return P;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates and programs NB P-state dependent registers
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNProgramNbPstateDependentRegistersTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 RdPtrInit;
+ UINT8 Dct;
+ MEMORY_BUS_SPEED MemClkSpeed;
+
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ break;
+ }
+ }
+
+ if (MemNGetBitFieldNb (NBPtr, MemPstateBF[MemNGetBitFieldNb (NBPtr, BFNbPsSel)]) == 0) {
+ MemClkSpeed = NBPtr->DCTPtr->Timings.Speed;
+ } else {
+ MemClkSpeed = MemNGetMemClkFreqUnb (NBPtr, (UINT8) MemNGetBitFieldNb (NBPtr, BFM1MemClkFreq));
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMemclk Freq: %d\n", MemClkSpeed);
+
+ // NCLK:MCLK ratio DDR rate (MT/s) RdPtrInit
+ // < 2:1 < 2133 0011b (2.5T)
+ // < 2:1 2133 <= rate <= 2400 0011b (2.5T) or 0010b (3T)
+ // For each NB P-state, IF any D18F2x9C_x0000_0[3:0]0[2:1]_dct[1:0]_mp[MemPstate][WrDat-
+ // GrossDly] ==0 THEN RdPtrInit=0010b ELSE RdPtrInit=0011b
+ // >=2:1 < 1866 0110b
+ // >=2:1 1866 <= rate < 2400 0101b
+ // >=2:1 2400 0100b
+ if (NBPtr->NBClkFreq < (UINT32) (MemClkSpeed * 2)) {
+ RdPtrInit = ((MemClkSpeed >= DDR2133_FREQUENCY) && (NBPtr->TechPtr->GetMinMaxGrossDly (NBPtr->TechPtr, AccessWrDatDly, FALSE) == 0)) ? 2 : 3;
+ } else {
+ RdPtrInit = (MemClkSpeed < DDR1866_FREQUENCY) ? 6 : ((MemClkSpeed < DDR2400_FREQUENCY) ? 5 : 4);
+ }
+ MemNBrdcstSetNb (NBPtr, BFRdPtrInit, RdPtrInit);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tRdPtr: %d\n", RdPtrInit);
+
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ // Set ProcOdtAdv
+ if ((NBPtr->ChannelPtr->SODimmPresent != 0) && (NBPtr->DCTPtr->Timings.Speed <= DDR1333_FREQUENCY)) {
+ MemNSetBitFieldNb (NBPtr, BFProcOdtAdv, 0);
+ } else {
+ MemNSetBitFieldNb (NBPtr, BFProcOdtAdv, 0x4000);
+ }
+ }
+ }
+
+ MemNBrdcstSetNb (NBPtr, BFDataTxFifoWrDly, 0);
+
+ IDS_OPTION_HOOK (IDS_NBPS_REG_OVERRIDE, NBPtr, &NBPtr->MemPtr->StdHeader);
+ MemFInitTableDrive (NBPtr, MTAfterNbPstateChange);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This is a general purpose function that executes before DRAM init
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNBeforeDramInitTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dct;
+
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ //
+ // 2.10.6.7 DCT Training Specific Configuration
+ //
+ MemNSetBitFieldNb (NBPtr, BFAddrCmdTriEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
+ MemNSetBitFieldNb (NBPtr, BFForceAutoPchg, 0);
+ MemNSetBitFieldNb (NBPtr, BFDynPageCloseEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFBankSwizzleMode, 0);
+ MemNSetBitFieldNb (NBPtr, BFDcqBypassMax, 0);
+ MemNSetBitFieldNb (NBPtr, BFPowerDownEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
+ MemNSetBitFieldNb (NBPtr, BFRxMaxDurDllNoLock, 0);
+ MemNSetBitFieldNb (NBPtr, BFTxMaxDurDllNoLock, 0);
+ MemNSetBitFieldNb (NBPtr, BFEnRxPadStandby, 0);
+ MemNSetBitFieldNb (NBPtr, BFBankSwap, 0);
+ MemNSetBitFieldNb (NBPtr, BFODTSEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFDctSelIntLvEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFCmdThrottleMode, 0);
+ MemNSetBitFieldNb (NBPtr, BFBwCapEn, 0);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function modifies CS interleaving low address according to several conditions for TN.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *LowBit - Pointer to low bit
+ *
+ */
+
+BOOLEAN
+MemNCSIntLvLowAddrAdjTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *LowBit
+ )
+{
+ UINT8 DctSelIntLvAddr;
+
+ DctSelIntLvAddr = (UINT8) MemNGetBitFieldNb (NBPtr, BFDctSelIntLvAddr);
+ //
+ //D18F2x[5C:40]_dct[1:0][15:5] = BaseAddr[21:11] &&
+ //D18F2x[6C:60]_dct[1:0][15:5] = AddrMask[21:11], so *LowBit needs to be added with 2.
+ //
+ *(UINT8 *) LowBit += 2;
+
+ if (MemNGetBitFieldNb (NBPtr, BFBankSwap) == 1) {
+ if (DctSelIntLvAddr == 4) {
+ *(UINT8 *) LowBit = 5;
+ } else {
+ *(UINT8 *) LowBit = 6;
+ }
+ }
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function releases the NB P-state force.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ */
+BOOLEAN
+MemNReleaseNbPstateTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &NBPtr->MemPtr->StdHeader);
+
+ // 6. Restore the initial D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0] values.
+ MemNSetBitFieldNb (NBPtr, BFNbPstateCtlReg, (MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg) & 0xFFFF9FFF) | (NBPtr->NbPsCtlReg & 0x6000));
+ // 7. Restore the initial D18F5x170[NbPstateThreshold, NbPstateHi] values.
+ MemNSetBitFieldNb (NBPtr, BFNbPstateCtlReg, (MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg) & 0xFFFFF13F) | (NBPtr->NbPsCtlReg & 0x0EC0));
+ // 8. Restore the initial D18F5x170[NbPstateLo] values.
+ MemNSetBitFieldNb (NBPtr, BFNbPstateLo, (NBPtr->NbPsCtlReg >> 3) & 3);
+
+ // Clear NbPsSel to 0
+ MemNSetBitFieldNb (NBPtr, BFNbPsSel, 0);
+ // Update TSC rate
+ FamilySpecificServices->GetTscRate (FamilySpecificServices, &NBPtr->MemPtr->TscRate, &NBPtr->MemPtr->StdHeader);
+
+ if (MemNGetBitFieldNb (NBPtr, BFMemPsSel) != 0) {
+ MemNChangeMemPStateContextNb (NBPtr, 0);
+ }
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function handles multiple stage of training when multiple Mem Pstate is enabled
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ *
+ */
+
+BOOLEAN
+MemNMemPstateStageChangeTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ BOOLEAN RetVal;
+ TRN_DLY_TYPE AccessType;
+ UINT8 Dct;
+ UINT8 ChipSel;
+ UINT8 ByteLane;
+ UINT16 CsEnabled;
+ UINT16 TrnDly;
+
+ RetVal = FALSE;
+
+ if (NBPtr->MemPstateStage == MEMORY_PSTATE_1ST_STAGE) {
+ MemNChangeMemPStateContextNb (NBPtr, 1);
+ // Load memory registers in M1 context from data saved in the heap
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nLoad Training registers for M1 with DDR667 training result\n");
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ // Save MemPstate 1 data in output data structures
+ LibAmdMemCopy (NBPtr->ChannelPtr->RcvEnDlysMemPs1, NBPtr->ChannelPtr->RcvEnDlys, (MAX_DIMMS * MAX_DELAYS) * 2, &(NBPtr->MemPtr->StdHeader));
+ LibAmdMemCopy (NBPtr->ChannelPtr->RdDqsDlysMemPs1, NBPtr->ChannelPtr->RdDqsDlys, MAX_DIMMS * MAX_DELAYS, &(NBPtr->MemPtr->StdHeader));
+ LibAmdMemCopy (NBPtr->ChannelPtr->WrDqsDlysMemPs1, NBPtr->ChannelPtr->WrDqsDlys, MAX_DIMMS * MAX_DELAYS, &(NBPtr->MemPtr->StdHeader));
+ LibAmdMemCopy (NBPtr->ChannelPtr->WrDatDlysMemPs1, NBPtr->ChannelPtr->WrDatDlys, MAX_DIMMS * MAX_DELAYS, &(NBPtr->MemPtr->StdHeader));
+ LibAmdMemCopy (NBPtr->ChannelPtr->RdDqs2dDlysMemPs1, NBPtr->ChannelPtr->RdDqs2dDlys, MAX_DIMMS * MAX_NUMBER_LANES, &(NBPtr->MemPtr->StdHeader));
+ LibAmdMemCopy (NBPtr->ChannelPtr->RdDqsMinDlysMemPs1, NBPtr->ChannelPtr->RdDqsMinDlys, MAX_DIMMS * MAX_DELAYS, &(NBPtr->MemPtr->StdHeader));
+ LibAmdMemCopy (NBPtr->ChannelPtr->RdDqsMaxDlysMemPs1, NBPtr->ChannelPtr->RdDqsMaxDlys, MAX_DIMMS * MAX_DELAYS, &(NBPtr->MemPtr->StdHeader));
+ LibAmdMemCopy (NBPtr->ChannelPtr->WrDatMinDlysMemPs1, NBPtr->ChannelPtr->WrDatMinDlys, MAX_DIMMS * MAX_DELAYS, &(NBPtr->MemPtr->StdHeader));
+ LibAmdMemCopy (NBPtr->ChannelPtr->WrDatMaxDlysMemPs1, NBPtr->ChannelPtr->WrDatMaxDlys, MAX_DIMMS * MAX_DELAYS, &(NBPtr->MemPtr->StdHeader));
+ LibAmdMemCopy (NBPtr->ChannelPtr->FailingBitMaskMemPs1, NBPtr->ChannelPtr->FailingBitMask, MAX_CS_PER_CHANNEL * MAX_DELAYS, &(NBPtr->MemPtr->StdHeader));
+
+ CsEnabled = NBPtr->DCTPtr->Timings.CsEnabled;
+ // Set Memory Pstate 1 training value into registers
+ for (AccessType = AccessRcvEnDly; AccessType <= AccessWrDqsDly; AccessType ++) {
+ for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL_TN; ChipSel = ChipSel + NBPtr->CsPerDelay) {
+ if ((CsEnabled & ((UINT16) ((NBPtr->CsPerDelay == 2)? 3 : 1) << ChipSel)) != 0) {
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ TrnDly = (UINT16) GetTrainDlyFromHeapNb (NBPtr, AccessType, DIMM_BYTE_ACCESS (ChipSel / NBPtr->CsPerDelay, ByteLane));
+ NBPtr->SetTrainDly (NBPtr, AccessType, DIMM_BYTE_ACCESS (ChipSel / NBPtr->CsPerDelay, ByteLane), TrnDly);
+ }
+ }
+ }
+ }
+
+ if (NBPtr->RefPtr->EnablePowerDown) {
+ MemNSetTxpNb (NBPtr);
+ MemNSetBitFieldNb (NBPtr, BFPchgPDEnDelay, (MAX (MAX ((NBPtr->DCTPtr->Timings.CasL + 5),
+ (UINT8) (MemNGetBitFieldNb (NBPtr, BFTcwl) + NBPtr->DCTPtr->Timings.Twr + 5)),
+ (UINT8) MemNGetBitFieldNb (NBPtr, BFTmod))));
+ MemNSetBitFieldNb (NBPtr, BFAggrPDDelay, 0x20);
+ }
+ MemNSetOtherTimingTN (NBPtr);
+ // Save timing data structure for memory Pstate 1
+ LibAmdMemCopy (NBPtr->DCTPtr->TimingsMemPs1, &(NBPtr->DCTPtr->Timings), sizeof (CH_TIMING_STRUCT), &(NBPtr->MemPtr->StdHeader));
+
+ MemFInitTableDrive (NBPtr, MTAfterMemPstate1PartialTrn);
+ }
+ }
+
+ // Switch back to M0 context
+ MemNChangeMemPStateContextNb (NBPtr, 0);
+
+ // Load memory registers in M1 context from data saved in the heap
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nGoing into training stage 2. Complete training at DDR667 is done.\n");
+ NBPtr->MemPstateStage = MEMORY_PSTATE_2ND_STAGE;
+ } else if ((NBPtr->MemPstateStage == MEMORY_PSTATE_2ND_STAGE) && (NBPtr->DCTPtr->Timings.TargetSpeed == NBPtr->DCTPtr->Timings.Speed)) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nGoing into training stage 3. Partial training at all frequencies is done.\n");
+ NBPtr->MemPstateStage = MEMORY_PSTATE_3RD_STAGE;
+ RetVal = TRUE;
+ } else {
+ // MemPstate is disabled. Do not go through the MemPstate handling flow.
+ RetVal = TRUE;
+ }
+
+ return RetVal;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function Sets Power Down options and enables Power Down
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * The following registers are set:
+ * BFPowerDownMode BFPrtlChPDEnhEn
+ * BFTxp BFAggrPDDelay
+ * BFTxpDll BFAggrPDEn
+ * BFPchgPDEnDelay BFPowerDownEn
+ *
+ * NOTE: Delay values must be set before turning on the associated Enable bit
+ */
+VOID
+MemNPowerDownCtlTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 PowerDownMode;
+ UINT8 Tmod;
+ UINT8 Twr;
+ UINT8 Tcwl;
+ UINT8 Tcl;
+
+ if (NBPtr->RefPtr->EnablePowerDown) {
+ //
+ // PowerDownMode
+ //
+ PowerDownMode = (UINT8) UserOptions.CfgPowerDownMode;
+ PowerDownMode = (!NBPtr->IsSupported[ChannelPDMode]) ? PowerDownMode : 0;
+ IDS_OPTION_HOOK (IDS_POWERDOWN_MODE, &PowerDownMode, &(NBPtr->MemPtr->StdHeader));
+ if (PowerDownMode == 1) {
+ MemNSetBitFieldNb (NBPtr, BFPowerDownMode, 1);
+ }
+ //
+ // Txp
+ //
+ MemNSetTxpNb (NBPtr);
+ //
+ // PchgPDModeSel is set elswhere.
+ //
+ // PchgPDEnDelay = MAX(Tcl + 5, Tcwl + Twr + 5, Tmod)
+ //
+ Tmod = (UINT8) MemNGetBitFieldNb (NBPtr, BFTmod);
+ Twr = NBPtr->DCTPtr->Timings.Twr;
+ Tcwl = (UINT8) MemNGetBitFieldNb (NBPtr, BFTcwl);
+ Tcl = NBPtr->DCTPtr->Timings.CasL;
+ MemNSetBitFieldNb (NBPtr, BFPchgPDEnDelay, (MAX (MAX ((Tcl + 5), (Tcwl + Twr + 5)), Tmod)));
+ //
+ // Partial Channel Power Down
+ //
+ MemNSetBitFieldNb (NBPtr, BFPrtlChPDDynDly, 0);
+ MemNSetBitFieldNb (NBPtr, BFPrtlChPDEnhEn, 0);
+ //
+ // Aggressive PowerDown
+ //
+ MemNSetBitFieldNb (NBPtr, BFAggrPDDelay, 0x20);
+ MemNSetBitFieldNb (NBPtr, BFAggrPDEn, 1);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * Always set upper 2 bits of CKETri bitfield
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNBeforePlatformSpecTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MemNSetBitFieldNb (NBPtr, BFCKETri, 0xC | MemNGetBitFieldNb (NBPtr, BFCKETri));
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnflowtn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnflowtn.c
new file mode 100644
index 0000000000..a00fd2fb94
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnflowtn.c
@@ -0,0 +1,156 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnflowtn.c
+ *
+ * TN initializer for MCT and DCT
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mntn.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+
+#define FILECODE PROC_MEM_NB_TN_MNFLOWTN_FILECODE
+/* features */
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function selects appropriate Tech functions for the NB.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNTechBlockSwitchTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+
+ TechPtr = NBPtr->TechPtr;
+
+ // Specify Dimm-Byte training for Nb
+ MemTDimmByteTrainInit (TechPtr);
+
+ // Remove the following functions because they are not needed for TN
+ TechPtr->SetDramMode = (BOOLEAN (*) (MEM_TECH_BLOCK *)) memDefTrue;
+ TechPtr->SpdCalcWidth = (BOOLEAN (*) (MEM_TECH_BLOCK *)) memDefTrue;
+ TechPtr->SetDqsEccTmgs = (BOOLEAN (*) (MEM_TECH_BLOCK *)) memDefTrue;
+ TechPtr->FindMaxDlyForMaxRdLat = MemTFindMaxRcvrEnDlyRdDqsDlyByteUnb;
+ TechPtr->ResetDCTWrPtr = MemTResetRcvFifoUnb;
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnidendimmtn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnidendimmtn.c
new file mode 100644
index 0000000000..ea93ecfc2a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnidendimmtn.c
@@ -0,0 +1,172 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnidendimmtn.c
+ *
+ * TN northbridge constructor for dimm identification translator.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "mm.h"
+#include "mn.h"
+#include "OptionMemory.h"
+#include "mntn.h"
+#include "Ids.h"
+#include "cpuRegisters.h"
+#include "cpuFamRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+
+#define FILECODE PROC_MEM_NB_TN_MNIDENDIMMTN_FILECODE
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemNIdentifyDimmConstructorTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the northbridge block for dimm identification translator
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *MemPtr - Pointer to the MEM_DATA_STRUCT
+ * @param[in,out] NodeID - ID of current node to construct
+ * @return TRUE - This is the correct constructor for the targeted node.
+ * @return FALSE - This isn't the correct constructor for the targeted node.
+ */
+
+BOOLEAN
+MemNIdentifyDimmConstructorTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ )
+{
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemNIsIdSupportedTN (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
+ return FALSE;
+ }
+
+ NBPtr->NodeCount = 1;
+ NBPtr->DctCount = MAX_DCTS_PER_NODE_TN;
+ NBPtr->CsRegMsk = 0x7FF8FFE0;
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->MCTPtr = &(MemPtr->DiesPerSystem[NodeID]);
+ NBPtr->PciAddr.AddressValue = MemPtr->DiesPerSystem[NodeID].PciAddr.AddressValue;
+ NBPtr->Node = ((UINT8) NBPtr->PciAddr.Address.Device) - 24;
+ NBPtr->Ganged = FALSE;
+ MemNInitNBRegTableTN (NBPtr, NBPtr->NBRegTable);
+ NBPtr->MemNCmnGetSetFieldNb = MemNCmnGetSetFieldTN;
+ NBPtr->GetBitField = MemNGetBitFieldNb;
+ NBPtr->SetBitField = MemNSetBitFieldNb;
+ NBPtr->GetSocketRelativeChannel = MemNGetSocketRelativeChannelNb;
+
+ return TRUE;
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnmcttn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnmcttn.c
new file mode 100644
index 0000000000..def21eee36
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnmcttn.c
@@ -0,0 +1,562 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnmcttn.c
+ *
+ * Northbridge TN MCT supporting functions
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mport.h"
+#include "GnbRegistersTN.h"
+#include "GnbRegisterAccTN.h"
+#include "mm.h"
+#include "mn.h"
+#include "OptionMemory.h"
+#include "mntn.h"
+#include "cpuFeatures.h"
+#include "Filecode.h"
+#include "mftds.h"
+#include "mu.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+
+#define FILECODE PROC_MEM_NB_TN_MNMCTTN_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define _16MB_RJ16 0x0100
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern BUILD_OPT_CFG UserOptions;
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function force memory Pstate to M0
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - No fatal error occurs.
+ * @return FALSE - Fatal error occurs.
+ */
+
+BOOLEAN
+MemNInitializeMctTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MemNSetBitFieldNb (NBPtr, BFMemPsSel, 0);
+ MemNSetBitFieldNb (NBPtr, BFEnSplitMctDatBuffers, 1);
+
+ MemUMFenceInstr ();
+ MemNSetBitFieldNb (NBPtr, BFMctEccDisLatOptEn, 1);
+ MemUMFenceInstr ();
+
+ MemNBrdcstSetUnConditionalNb (NBPtr, BFPStateToAccess, 0);
+
+ MemNForcePhyToM0Unb (NBPtr);
+
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets final values for specific registers.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - No fatal error occurs.
+ * @return FALSE - Fatal error occurs.
+ */
+
+BOOLEAN
+MemNFinalizeMctTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_DATA_STRUCT *MemPtr;
+ MEM_PARAMETER_STRUCT *RefPtr;
+ DRAM_PREFETCH_MODE DramPrefetchMode;
+ UINT16 Speed;
+ UINT32 Value32;
+ UINT8 DcqBwThrotWm1;
+ UINT8 DcqBwThrotWm2;
+ UINT8 Dct;
+
+ MemPtr = NBPtr->MemPtr;
+ RefPtr = MemPtr->ParameterListPtr;
+ DramPrefetchMode = MemPtr->PlatFormConfig->PlatformProfile.AdvancedPerformanceProfile.DramPrefetchMode;
+ Speed = NBPtr->DCTPtr->Timings.Speed;
+
+ //
+ // F2x11C
+ //
+ MemNSetBitFieldNb (NBPtr, BFMctCfgHiReg, 0x0CE00F31);
+ if (DramPrefetchMode == DISABLE_DRAM_PREFETCH_FOR_IO || DramPrefetchMode == DISABLE_DRAM_PREFETCHER) {
+ MemNSetBitFieldNb (NBPtr, BFPrefIoDis, 1);
+ }
+
+ if (DramPrefetchMode == DISABLE_DRAM_PREFETCH_FOR_CPU || DramPrefetchMode == DISABLE_DRAM_PREFETCHER) {
+ MemNSetBitFieldNb (NBPtr, BFPrefCpuDis, 1);
+ }
+
+
+ if (Speed == DDR667_FREQUENCY) {
+ DcqBwThrotWm1 = 3;
+ DcqBwThrotWm2 = 4;
+ } else if (Speed == DDR800_FREQUENCY) {
+ DcqBwThrotWm1 = 3;
+ DcqBwThrotWm2 = 5;
+ } else if (Speed == DDR1066_FREQUENCY) {
+ DcqBwThrotWm1 = 4;
+ DcqBwThrotWm2 = 6;
+ } else if (Speed == DDR1333_FREQUENCY) {
+ DcqBwThrotWm1 = 5;
+ DcqBwThrotWm2 = 8;
+ } else if (Speed == DDR1600_FREQUENCY) {
+ DcqBwThrotWm1 = 6;
+ DcqBwThrotWm2 = 9;
+ } else if (Speed == DDR1866_FREQUENCY) {
+ DcqBwThrotWm1 = 7;
+ DcqBwThrotWm2 = 10;
+ } else {
+ DcqBwThrotWm1 = 8;
+ DcqBwThrotWm2 = 12;
+ }
+ //
+ // F2x1B0
+ //
+ Value32 = MemNGetBitFieldNb (NBPtr, BFExtMctCfgLoReg);
+ Value32 &= 0x003FE8C0;
+ Value32 |= 0x0FC01001;
+ MemNSetBitFieldNb (NBPtr, BFExtMctCfgLoReg, Value32);
+
+ //
+ // F2x1B4
+ //
+ Value32 = MemNGetBitFieldNb (NBPtr, BFExtMctCfgHiReg);
+ Value32 &= 0xFFFFFC00;
+ Value32 |= (((UINT32) DcqBwThrotWm2 << 5) | (UINT32) DcqBwThrotWm1);
+ MemNSetBitFieldNb (NBPtr, BFExtMctCfgHiReg, Value32);
+
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ //
+ // Phy Power Saving
+ //
+ MemNPhyPowerSavingMPstateUnb (NBPtr);
+ if (NBPtr->MemPstateStage == MEMORY_PSTATE_3RD_STAGE) {
+ MemNChangeMemPStateContextNb (NBPtr, 1);
+ MemNPhyPowerSavingMPstateUnb (NBPtr);
+ MemFInitTableDrive (NBPtr, MTAfterSettingMemoryPstate1);
+ MemNChangeMemPStateContextNb (NBPtr, 0);
+ }
+ //
+ // Power Down Enable
+ //
+ if (NBPtr->RefPtr->EnablePowerDown) {
+ MemNSetBitFieldNb (NBPtr, BFPowerDownEn, 1);
+ }
+ }
+ }
+
+ // Set LockDramCfg
+ if (IsFeatureEnabled (C6Cstate, NBPtr->MemPtr->PlatFormConfig, &(NBPtr->MemPtr->StdHeader))) {
+ IDS_SKIP_HOOK (IDS_LOCK_DRAM_CFG, NBPtr, &NBPtr->MemPtr->StdHeader) {
+ MemNSetBitFieldNb (NBPtr, BFLockDramCfg, 1);
+ }
+ }
+
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function create the HT memory map for TN
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - No fatal error occurs.
+ * @return FALSE - Fatal error occurs.
+ */
+
+BOOLEAN
+MemNHtMemMapInitTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 WeReMask;
+ UINT32 BottomIo;
+ UINT32 HoleOffset;
+ UINT32 DctSelBaseAddr;
+ UINT32 NodeSysBase;
+ UINT32 NodeSysLimit;
+ MEM_PARAMETER_STRUCT *RefPtr;
+ DIE_STRUCT *MCTPtr;
+
+ RefPtr = NBPtr->RefPtr;
+ MCTPtr = NBPtr->MCTPtr;
+ //
+ // Physical addresses in this function are right adjusted by 16 bits ([47:16])
+ // They are BottomIO, HoleOffset, DctSelBaseAddr, NodeSysBase, NodeSysLimit.
+ //
+
+ // Enforce bottom of IO be be 128MB aligned
+ BottomIo = (RefPtr->BottomIo & 0xF8) << 8;
+
+ if (MCTPtr->NodeMemSize != 0) {
+ NodeSysBase = 0;
+ NodeSysLimit = MCTPtr->NodeMemSize - 1;
+ DctSelBaseAddr = MCTPtr->DctData[0].Timings.DctMemSize;
+
+ if (NodeSysLimit >= BottomIo) {
+ // HW Dram Remap
+ MCTPtr->Status[SbHWHole] = TRUE;
+ RefPtr->GStatus[GsbHWHole] = TRUE;
+ MCTPtr->NodeHoleBase = BottomIo;
+ RefPtr->HoleBase = BottomIo;
+
+ HoleOffset = _4GB_RJ16 - BottomIo;
+
+ NodeSysLimit += HoleOffset;
+
+ if ((DctSelBaseAddr > 0) && (DctSelBaseAddr < BottomIo)) {
+ HoleOffset += DctSelBaseAddr;
+ } else {
+ if (DctSelBaseAddr >= BottomIo) {
+ DctSelBaseAddr += HoleOffset;
+ }
+ HoleOffset += NodeSysBase;
+ }
+
+ MemNSetBitFieldNb (NBPtr, BFDramHoleBase, BottomIo >> 8);
+ MemNSetBitFieldNb (NBPtr, BFDramHoleOffset, HoleOffset >> 7);
+ MemNSetBitFieldNb (NBPtr, BFDramHoleValid, 1);
+ MemNSetBitFieldNb (NBPtr, BFDramMemHoistValid, 1);
+ } else {
+ // No Remapping. Normal Contiguous mapping
+ }
+ MCTPtr->NodeSysBase = NodeSysBase;
+ MCTPtr->NodeSysLimit = NodeSysLimit;
+ RefPtr->SysLimit = MCTPtr->NodeSysLimit;
+
+ WeReMask = 3;
+ // Set the Dram base and set the WE and RE flags in the base.
+ MemNSetBitFieldNb (NBPtr, BFDramBaseReg0, (NodeSysBase << 8) | WeReMask);
+ MemNSetBitFieldNb (NBPtr, BFDramBaseHiReg0, NodeSysBase >> 24);
+ // Set the Dram limit and set DstNode.
+ MemNSetBitFieldNb (NBPtr, BFDramLimitReg0, ((NodeSysLimit << 8) & 0xFFFF0000));
+ MemNSetBitFieldNb (NBPtr, BFDramLimitHiReg0, NodeSysLimit >> 24);
+
+ MemNSetBitFieldNb (NBPtr, BFDramBaseAddr, NodeSysBase >> (27 - 16));
+ MemNSetBitFieldNb (NBPtr, BFDramLimitAddr, NodeSysLimit >> (27 - 16));
+
+ if ((MCTPtr->DctData[1].Timings.DctMemSize != 0) && (!NBPtr->Ganged)) {
+ MemNSetBitFieldNb (NBPtr, BFDctSelBaseAddr, DctSelBaseAddr >> 11);
+ MemNSetBitFieldNb (NBPtr, BFDctSelHiRngEn, 1);
+ MemNSetBitFieldNb (NBPtr, BFDctSelHi, 1);
+ MemNSetBitFieldNb (NBPtr, BFDctSelBaseOffset, DctSelBaseAddr >> 10);
+ }
+ }
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * Report the Uma size that is going to be allocated.
+ * Total system memory UMASize
+ * >= 2G 512M
+ * >=1G 256M
+ * <1G 64M
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return Uma size [31:0] = Addr [47:16]
+ */
+UINT32
+MemNGetUmaSizeTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 SysMemSize;
+ UINT32 SizeOfUma;
+
+ SysMemSize = NBPtr->RefPtr->SysLimit + 1;
+ SysMemSize = (SysMemSize + 0x100) & 0xFFFFF000; // Ignore 16MB allocated for C6 when finding UMA size
+ if (SysMemSize >= 0x8000) {
+ SizeOfUma = 512 << (20 - 16);
+ } else if (SysMemSize >= 0x4000) {
+ SizeOfUma = 256 << (20 - 16);
+ } else {
+ SizeOfUma = 64 << (20 - 16);
+ }
+
+ return SizeOfUma;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function allocates 16MB of memory for C6 storage when it is requested to be enabled
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNAllocateC6StorageTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 SysLimit;
+ UINT32 DramLimitReg;
+
+ if (NBPtr->SharedPtr->C6Enabled || IsFeatureEnabled (C6Cstate, NBPtr->MemPtr->PlatFormConfig, &(NBPtr->MemPtr->StdHeader))) {
+
+ SysLimit = NBPtr->RefPtr->SysLimit;
+
+ // Calculate new SysLimit
+ if (!NBPtr->SharedPtr->C6Enabled) {
+ // System memory available is reduced by 16MB
+ SysLimit -= _16MB_RJ16;
+
+ NBPtr->MCTPtr->NodeSysLimit = SysLimit;
+ NBPtr->RefPtr->SysLimit = SysLimit;
+ NBPtr->SharedPtr->C6Enabled = TRUE;
+
+ // Set TOPMEM and MTRRs (only need to be done once for BSC)
+ MemNC6AdjustMSRs (NBPtr);
+ }
+
+ // Set Dram Limit
+ DramLimitReg = MemNGetBitFieldNb (NBPtr, BFDramLimitReg0) & 0x0000FFFF;
+ MemNSetBitFieldNb (NBPtr, BFDramLimitReg0, ((SysLimit << 8) & 0xFFFF0000) | DramLimitReg);
+ MemNSetBitFieldNb (NBPtr, BFDramLimitHiReg0, SysLimit >> 24);
+
+ MemNSetBitFieldNb (NBPtr, BFCoreStateSaveDestNode, 0);
+
+ // Set BFCC6SaveEn
+ MemNSetBitFieldNb (NBPtr, BFCC6SaveEn, 1);
+ // LockDramCfg will be set in FinalizeMCT
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function adjusts NB pstate norbridge voltage for TN
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNAdjustNBPstateVolTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+
+ D0F0xBC_xE0104168_STRUCT D0F0xBC_xE0104168;
+ D0F0xBC_xE010416C_STRUCT D0F0xBC_xE010416C;
+ D0F0xBC_xE0104170_STRUCT D0F0xBC_xE0104170;
+ UINT8 MemClkVidHi;
+ UINT8 MemClkVidLo;
+ UINT8 MemPstate;
+ UINT8 NbVid;
+ UINT8 NbPs;
+ UINT8 NbPstateMaxVal;
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nStart NB Pstate voltage adjustment.\n");
+
+ GnbRegisterReadTN (TYPE_D0F0xBC, D0F0xBC_xE0104168_ADDRESS, &D0F0xBC_xE0104168.Value, 0, &(NBPtr->MemPtr->StdHeader));
+ GnbRegisterReadTN (TYPE_D0F0xBC, D0F0xBC_xE010416C_ADDRESS, &D0F0xBC_xE010416C.Value, 0, &(NBPtr->MemPtr->StdHeader));
+ GnbRegisterReadTN (TYPE_D0F0xBC, D0F0xBC_xE0104170_ADDRESS, &D0F0xBC_xE0104170.Value, 0, &(NBPtr->MemPtr->StdHeader));
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tD0F0xBC_xE0104168: %08x\n", D0F0xBC_xE0104168.Value);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tD0F0xBC_xE010416C: %08x\n", D0F0xBC_xE010416C.Value);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tD0F0xBC_xE0104170: %08x\n", D0F0xBC_xE0104170.Value);
+
+ // MemClkVidHi = read D0F0xBC_xE0104168 through D0F0xBC_xE0104170 to find the VID code corresponding
+ // to the M0 MEMCLK. If the M0 MEMCLK is not found, use the next higher defined MEMCLK as the target.
+ switch (NBPtr->DCTPtr->Timings.TargetSpeed) {
+ case DDR667_FREQUENCY:
+ MemClkVidHi = (UINT8) D0F0xBC_xE0104168.Field.MemClkVid0_7_0;
+ break;
+ case DDR800_FREQUENCY:
+ MemClkVidHi = (UINT8) D0F0xBC_xE0104168.Field.MemClkVid1_7_0;
+ break;
+ case DDR1066_FREQUENCY:
+ MemClkVidHi = (UINT8) D0F0xBC_xE0104168.Field.MemClkVid2_7_0;
+ break;
+ case DDR1333_FREQUENCY:
+ MemClkVidHi = (UINT8) D0F0xBC_xE0104168.Field.MemClkVid3_1_0 | ((UINT8) D0F0xBC_xE010416C.Field.MemClkVid3_7_2 << 2);
+ break;
+ case DDR1600_FREQUENCY:
+ MemClkVidHi = (UINT8) D0F0xBC_xE010416C.Field.MemClkVid4_7_0;
+ break;
+ case DDR1866_FREQUENCY:
+ MemClkVidHi = (UINT8) D0F0xBC_xE010416C.Field.MemClkVid5_7_0;
+ break;
+ case DDR2100_FREQUENCY:
+ MemClkVidHi = (UINT8) D0F0xBC_xE010416C.Field.MemClkVid6_7_0;
+ break;
+ case DDR2133_FREQUENCY:
+ MemClkVidHi = (UINT8) D0F0xBC_xE010416C.Field.MemClkVid7_1_0 | ((UINT8) D0F0xBC_xE0104170.Field.MemClkVid7_7_2 << 2);
+ break;
+ case DDR2400_FREQUENCY:
+ MemClkVidHi = (UINT8) D0F0xBC_xE0104170.Field.MemClkVid8_7_0;
+ break;
+ default:
+ // If the M0 MEMCLK is greater than MemClkVid8, use the MemClkVid8 VID as the target
+ MemClkVidHi = (UINT8) D0F0xBC_xE0104170.Field.MemClkVid8_7_0;
+ }
+
+ // MemClkVidLo = read D0F0xBC_xE0104168 through D0F0xBC_xE0104170 to find the VID code corresponding
+ // to the M1 MEMCLK. If the M1 MEMCLK is not found, use the next higher defined MEMCLK as the target.
+ MemClkVidLo = (UINT8) D0F0xBC_xE0104168.Field.MemClkVid0_7_0;
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tOriginal MemClkVidLo: %02x\n", MemClkVidLo);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tOriginal MemClkVidHi: %02x\n", MemClkVidHi);
+
+ // If D18F5x188[NbOffsetTrim] == 01b, MemClkVid = Fuse[MemClkVid] - 4 (-25mV offset so add 25mV to VID)
+ // Else if D18F5x188[NbOffsetTrim] == 11b, MemClkVid = Fuse[MemClkVid] + 4 (+25mV offset so decrease 25mV from VID)
+ // Else MemClkVid = Fuse[MemClkVid]
+ if (MemNGetBitFieldNb (NBPtr, BFNbOffsetTrim) == 1) {
+ MemClkVidLo -= 4;
+ MemClkVidHi -= 4;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tAdd 25mV\n");
+ } else if (MemNGetBitFieldNb (NBPtr, BFNbOffsetTrim) == 3) {
+ MemClkVidLo += 4;
+ MemClkVidHi += 4;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDecrease 25mV\n");
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tAdjusted MemClkVidLo: %02x\n", MemClkVidLo);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tAdjusted MemClkVidHi: %02x\n", MemClkVidHi);
+
+ // For each NB P-state from NBP0 through D18F5x170[NbPstateMaxVal]:
+ // If ((D18F5x1[6C:60][MemPstate] == 0) && (MemClkVidHi voltage > D18F5x1[6C:60][NbVid] voltage)):
+ // Program D18F5x1[6C:60][NbVid] == MemClkVidHi.
+ // If ((D18F5x1[6C:60][MemPstate] == 1) && (MemClkVidLo voltage > D18F5x1[6C:60][NbVid] voltage)):
+ // Program D18F5x1[6C:60][NbVid] == MemClkVidLo.
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tNBPs\tNbVid\tMemPstate\tOverride\n");
+ NbPstateMaxVal = (UINT8) MemNGetBitFieldNb (NBPtr, BFNbPstateMaxVal);
+ for (NbPs = 0; NbPs <= NbPstateMaxVal; NbPs ++) {
+ NbVid = (UINT8) MemNGetBitFieldNb (NBPtr, BFNbVid0 + (NbPs << 1));
+ MemPstate = (UINT8) MemNGetBitFieldNb (NBPtr, BFMemPstate0 + NbPs);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t %01d \t %02x \t %01d \t", NbPs, NbVid, MemPstate);
+ // higher voltage correspond to smaller VID
+ if ((MemPstate == 0) && (MemClkVidHi < NbVid)) {
+ MemNSetBitFieldNb (NBPtr, BFNbVid0 + (NbPs << 1), MemClkVidHi);
+ IDS_HDT_CONSOLE (MEM_FLOW, "MemClkVidHi\n");
+ } else if ((MemPstate == 1) && (MemClkVidLo < NbVid)) {
+ MemNSetBitFieldNb (NBPtr, BFNbVid0 + (NbPs << 1), MemClkVidLo);
+ IDS_HDT_CONSOLE (MEM_FLOW, "MemClkVidLo\n");
+ } else {
+ IDS_HDT_CONSOLE (MEM_FLOW, "No change\n");
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnottn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnottn.c
new file mode 100644
index 0000000000..821bb1d63d
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnottn.c
@@ -0,0 +1,348 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnottn.c
+ *
+ * Northbridge Non-SPD timings for TN
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "OptionMemory.h"
+#include "mntn.h"
+#include "mu.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_MEM_NB_TN_MNOTTN_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+#if 0
+UINT32
+STATIC
+MemNGetODTDelaysTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+#endif
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+extern BUILD_OPT_CFG UserOptions;
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the non-SPD timings
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - No fatal error occurs.
+ * @return FALSE - Fatal error occurs.
+ */
+
+BOOLEAN
+MemNOtherTimingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dct;
+ IDS_HDT_CONSOLE (MEM_STATUS, "\nStart Programming of Non-SPD Timings.\n");
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctDimmValid > 0) {
+ MemNSetOtherTimingTN (NBPtr);
+ }
+ }
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the non-SPD timings in PCI registers
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNSetOtherTimingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ INT8 ROD;
+ INT8 WOD;
+ INT8 LD;
+ INT8 WrEarlyx2;
+ INT8 CDDTrdrdSdDc;
+ INT8 CDDTrdrdDd;
+ INT8 CDDTwrwrDd;
+ INT8 CDDTwrwrSdDc;
+ INT8 CDDTrwtTO;
+ INT8 CDDTwrrd;
+ UINT8 TrdrdSdDc;
+ UINT8 TrdrdDd;
+ UINT8 TwrwrSdDc;
+ UINT8 TwrwrDd;
+ UINT8 TrdrdSdSc;
+ UINT8 TwrwrSdSc;
+ UINT8 Twrrd;
+ UINT8 TrwtTO;
+ BOOLEAN PerRankTimingEn;
+
+ CH_DEF_STRUCT *ChannelPtr;
+ ChannelPtr = NBPtr->ChannelPtr;
+
+ PerRankTimingEn = (BOOLEAN) (MemNGetBitFieldNb (NBPtr, BFPerRankTimingEn));
+ //
+ // Latency Difference (LD) = Tcl - Tcwl
+ //
+ LD = (INT8) (MemNGetBitFieldNb (NBPtr, BFTcl)) - (INT8) (MemNGetBitFieldNb (NBPtr, BFTcwl));
+
+ //
+ // Read ODT Delay (ROD) = MAX ( 0, (RdOdtOnDuration - 6)) + MAX ( 0, (RdOdtTrnOnDly - LD))
+ //
+ ROD = MAX (0, (INT8) (MemNGetBitFieldNb (NBPtr, BFRdOdtOnDuration) - 6)) +
+ MAX ( 0, (INT8) (MemNGetBitFieldNb (NBPtr, BFRdOdtTrnOnDly) - LD));
+ //
+ // Write ODT Delay (WOD) = MAX (0, (WrOdtOnDuration - 6))
+ //
+ WOD = MAX (0, (INT8) (MemNGetBitFieldNb (NBPtr, BFWrOdtOnDuration) - 6));
+ //
+ // WrEarly = ABS (WrDqDqsEarly) / 2
+ //
+ WrEarlyx2 = (INT8) MemNGetBitFieldNb (NBPtr, BFWrDqDqsEarly);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tLD: %d ROD: %d WOD: %d WrEarlyx2: %d\n\n", LD, ROD, WOD, WrEarlyx2);
+ //
+ // Read to Read Timing (TrdrdSdSc, TrdrdScDc, TrdrdDd)
+ //
+ // TrdrdSdSc = 1.
+ // TrdrdSdDc (in MEMCLKs) = MAX(TrdrdSdSc, 3 + (IF (D18F2xA8_dct[1:0][PerRankTimingEn])
+ // THEN CEIL(CDDTrdrdSdDc / 2 ) ELSE 0 ENDIF)).
+ // TrdrdDd = MAX(TrdrdSdDc, CEIL(MAX(ROD + 3, CDDTrdrdDd/2 + 3.5)))
+ //
+ TrdrdSdSc = 1;
+
+ CDDTrdrdSdDc = (INT8) MemNCalcCDDNb (NBPtr, AccessRcvEnDly, AccessRcvEnDly, TRUE, FALSE);
+ TrdrdSdDc = MAX (0, PerRankTimingEn ? (3 + (CDDTrdrdSdDc + 1) / 2) : 3);
+ TrdrdSdDc = MAX (TrdrdSdSc, TrdrdSdDc);
+
+ CDDTrdrdDd = (INT8) MemNCalcCDDNb (NBPtr, AccessRcvEnDly, AccessRcvEnDly, FALSE, TRUE);
+ TrdrdDd = MAX (ROD + 3, (CDDTrdrdDd + 7 + 1) / 2);
+ TrdrdDd = MAX (TrdrdSdDc, TrdrdDd);
+
+ MemNSetBitFieldNb (NBPtr, BFTrdrdDd, (UINT32) TrdrdDd);
+ MemNSetBitFieldNb (NBPtr, BFTrdrdSdDc, (UINT32) TrdrdSdDc);
+ MemNSetBitFieldNb (NBPtr, BFTrdrdSdSc, (UINT32) TrdrdSdSc);
+ //
+ // Write to Write Timing (TwrwrSdSc, TwrwrScDc, TwrwrDd)
+ //
+ // TwrwrSdSc = 1.
+ // TwrwrSdDc = CEIL(MAX(WOD + 3, CDDTwrwrSdDc / 2 +
+ // (IF (D18F2xA8_dct[1:0][PerRankTimingEn]) THEN 3.5 ELSE 3 ENDIF))).
+ //
+ // TwrwrDd = CEIL (MAX (WOD + 3, CDDTwrwrDd / 2 + 3.5))
+ // TwrwrSdSc <= TwrwrSdDc <= TwrwrDd
+ //
+ TwrwrSdSc = 1;
+
+ CDDTwrwrSdDc = (INT8) MemNCalcCDDNb (NBPtr, AccessWrDqsDly, AccessWrDqsDly, TRUE, FALSE);
+ TwrwrSdDc = (UINT8) MAX (WOD + 3, (CDDTwrwrSdDc + (PerRankTimingEn ? 7 : 6) + 1 ) / 2);
+
+ CDDTwrwrDd = (INT8) MemNCalcCDDNb (NBPtr, AccessWrDqsDly, AccessWrDqsDly, FALSE, TRUE);
+ TwrwrDd = (UINT8) MAX ((UINT8) (WOD + 3), (CDDTwrwrDd + 7 + 1) / 2);
+
+ TwrwrSdDc = (TwrwrSdSc <= TwrwrSdDc) ? TwrwrSdDc : TwrwrSdSc;
+ TwrwrDd = (TwrwrSdDc <= TwrwrDd) ? TwrwrDd : TwrwrSdDc;
+
+ MemNSetBitFieldNb (NBPtr, BFTwrwrDd, (UINT32) TwrwrDd);
+ MemNSetBitFieldNb (NBPtr, BFTwrwrSdDc, (UINT32) TwrwrSdDc);
+ MemNSetBitFieldNb (NBPtr, BFTwrwrSdSc, (UINT32) TwrwrSdSc);
+ //
+ // Write to Read DIMM Termination Turn-around
+ //
+ // Twrrd = MAX ( 1, CEIL (MAX (WOD, (CDDTwrrd / 2) + 0.5 - WrEarly) - LD + 3))
+ //
+ CDDTwrrd = (INT8) MemNCalcCDDNb (NBPtr, AccessWrDqsDly, AccessRcvEnDly, TRUE, TRUE);
+ Twrrd = MAX (1, MAX (WOD, (CDDTwrrd + 1 - WrEarlyx2 + 1) / 2) - LD + 3);
+
+ MemNSetBitFieldNb (NBPtr, BFTwrrd, (UINT32) Twrrd);
+ //
+ // Read to Write Turnaround for Data, DQS Contention
+ //
+ // TrwtTO = CEIL (MAX (ROD, (CDDTrwtTO / 2) - 0.5 + WrEarly) + LD + 3)
+ //
+ CDDTrwtTO = (INT8) MemNCalcCDDNb (NBPtr, AccessRcvEnDly, AccessWrDqsDly, TRUE, TRUE);
+
+ TrwtTO = MAX ((ChannelPtr->Dimms == 1 ? 0 : ROD) , (CDDTrwtTO - 1 + WrEarlyx2 + 1) / 2) + LD + 3;
+
+ MemNSetBitFieldNb (NBPtr, BFTrwtTO, (UINT32) TrwtTO);
+ //
+ // Read to Write Turnaround for opportunistic Write Bursting
+ //
+ // TrwtWB = TrwtTO + 1
+ //
+ MemNSetBitFieldNb (NBPtr, BFTrwtWB, (UINT32) TrwtTO + 1);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t TrdrdSdSc : %02x\n", TrdrdSdSc);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCDDTrdrdSdDc : %02x TrdrdSdDc : %02x\n", CDDTrdrdSdDc, TrdrdSdDc);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCDDTrdrdDd : %02x TrdrdDd : %02x\n\n", CDDTrdrdDd, TrdrdDd);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t TwrwrSdSc : %02x\n", TwrwrSdSc);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCDDTwrwrSdDc : %02x TwrwrSdDc : %02x\n", CDDTwrwrSdDc, TwrwrSdDc );
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCDDTwrwrDd : %02x TwrwrDd : %02x\n\n", CDDTwrwrDd, TwrwrDd);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t TrwtWB : %02x\n", TrwtTO + 1);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCDDTwrrd : %02x Twrrd : %02x\n", (UINT8) CDDTwrrd, (UINT8) Twrrd );
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCDDTrwtTO : %02x TrwtTO : %02x\n\n", (UINT8) CDDTrwtTO, (UINT8) TrwtTO );
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the ODT delays
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+#if 0
+UINT32
+STATIC
+MemNGetODTDelaysTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ INT8 Ld;
+ UINT32 ODTDelays;
+ //
+ // The BIOS must additionally configure the ODT pattern
+ // and the ODT switching delays.
+ //
+ // Program F2x[1, 0]9C_x83 DRAM Phy ODT Assertion Control Register based on Burst length.
+ // -Read the Burst Length from F2x[1, 0]84[BurstCtrl].
+ // -Value of 2, BL = 4 else assume BL=8.
+ // -Initialize ODTDelays based on BL value
+ // -WrOdtOnDuration [14:12] = BL / 2 + 1
+ // -WrOdtTrnOnDly [10:8] = 0
+ // -RdOdtOnDuration [6:4] = BL / 2 + 1
+ //
+ ODTDelays = (MemNGetBitFieldNb (NBPtr, BFBurstCtrl) == 2) ? 0x00003030 : 0x00005050;
+
+ // RdOdtTrnOnDly [3:0] < (CL-CWL) or (CL-CWL - 1)
+ // See BKDG F2x[1, 0]9C_x83 DRAM Phy ODT Assertion Control Register [3:0]
+ Ld = ((INT8)MemNGetBitFieldNb (NBPtr, BFTcl) + 1) - ((INT8)MemNGetBitFieldNb (NBPtr, BFTcwl) + 5);
+ if (Ld < 0) {
+ Ld = 0;
+ }
+ if (Ld > 7) {
+ Ld = 7;
+ }
+ ODTDelays += Ld;
+ return ODTDelays;
+}
+#endif
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnphytn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnphytn.c
new file mode 100644
index 0000000000..8a0199420f
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnphytn.c
@@ -0,0 +1,742 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnphytn.c
+ *
+ * Northbridge Phy support for TN
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mport.h"
+#include "ma.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mu.h"
+#include "OptionMemory.h" // need def for MEM_FEAT_BLOCK_NB
+#include "mntn.h"
+#include "PlatformMemoryConfiguration.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+
+#define FILECODE PROC_MEM_NB_TN_MNPHYTN_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define UNUSED_CLK 4
+
+
+/// The structure of TxPrePN tables
+typedef struct {
+ UINT32 Speed; ///< Applied memory speed
+ UINT16 TxPrePNVal[4]; ///< Table values
+} TXPREPN_STRUCT;
+
+/// The entry of individual TxPrePN tables
+typedef struct {
+ UINT8 TxPrePNTblSize; ///< Total Table size
+ CONST TXPREPN_STRUCT *TxPrePNTblPtr; ///< Pointer to the table
+} TXPREPN_ENTRY;
+
+/// Type of an entry for processing phy init compensation for TN
+typedef struct {
+ BIT_FIELD_NAME IndexBitField; ///< Bit field on which the value is decided
+ BIT_FIELD_NAME StartTargetBitField; ///< First bit field to be modified
+ BIT_FIELD_NAME EndTargetBitField; ///< Last bit field to be modified
+ UINT16 ExtraValue; ///< Extra value needed to be written to bit field
+ CONST TXPREPN_ENTRY *TxPrePN; ///< Pointer to slew rate table
+} PHY_COMP_INIT_NB;
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemNRdPosTrnTN (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern MEM_FEAT_TRAIN_SEQ memTrainSequenceDDR3[];
+/* -----------------------------------------------------------------------------*/
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the DDR phy compensation logic
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNInitPhyCompTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ //
+ // Phy Predriver Calibration Codes for Data/DQS
+ //
+ CONST STATIC TXPREPN_STRUCT TxPrePNDataDqsV15TN[] = {
+ //{TxPreP, TxPreN}[Speed][Drive Strength] at 1.5V
+ {DDR667 + DDR800, {0x924, 0x924, 0x924, 0x924}},
+ {DDR1066 + DDR1333, {0xFF6, 0xFF6, 0xFF6, 0xFF6}},
+ {DDR1600 + DDR1866 + DDR2133, {0xFF6, 0xFF6, 0xFF6, 0xFF6}}
+ };
+ CONST STATIC TXPREPN_STRUCT TxPrePNDataDqsV135TN[] = {
+ //{TxPreP, TxPreN}[Speed][Drive Strength] at 1.35V
+ {DDR667 + DDR800, {0xFF6, 0xB6D, 0xB6D, 0x924}},
+ {DDR1066 + DDR1333, {0xFF6, 0xFF6, 0xFF6, 0xFF6}},
+ {DDR1600 + DDR1866 + DDR2133, {0xFF6, 0xFF6, 0xFF6, 0xFF6}}
+ };
+ CONST STATIC TXPREPN_STRUCT TxPrePNDataDqsV125TN[] = {
+ //{TxPreP, TxPreN}[Speed][Drive Strength] at 1.25V
+ {DDR667 + DDR800, {0xFF6, 0xDAD, 0xDAD, 0x924}},
+ {DDR1066 + DDR1333, {0xFF6, 0xFF6, 0xFF6, 0xFF6}},
+ {DDR1600 + DDR1866 + DDR2133, {0xFF6, 0xFF6, 0xFF6, 0xFF6}}
+ };
+ CONST STATIC TXPREPN_ENTRY TxPrePNDataDqsTN[] = {
+ {GET_SIZE_OF (TxPrePNDataDqsV15TN), (TXPREPN_STRUCT *)&TxPrePNDataDqsV15TN},
+ {GET_SIZE_OF (TxPrePNDataDqsV135TN), (TXPREPN_STRUCT *)&TxPrePNDataDqsV135TN},
+ {GET_SIZE_OF (TxPrePNDataDqsV125TN), (TXPREPN_STRUCT *)&TxPrePNDataDqsV125TN}
+ };
+
+ //
+ // Phy Predriver Calibration Codes for Cmd/Addr
+ //
+ CONST STATIC TXPREPN_STRUCT TxPrePNCmdAddrV15TN[] = {
+ //{TxPreP, TxPreN}[Speed][Drive Strength] at 1.5V
+ {DDR667 + DDR800, {0x492, 0x492, 0x492, 0x492}},
+ {DDR1066 + DDR1333, {0x6DB, 0x6DB, 0x6DB, 0x6DB}},
+ {DDR1600 + DDR1866 + DDR2133, {0xB6D, 0xB6D, 0xB6D, 0xB6D}}
+ };
+ CONST STATIC TXPREPN_STRUCT TxPrePNCmdAddrV135TN[] = {
+ //{TxPreP, TxPreN}[Speed][Drive Strength] at 1.35V
+ {DDR667 + DDR800, {0x492, 0x492, 0x492, 0x492}},
+ {DDR1066 + DDR1333, {0x924, 0x6DB, 0x6DB, 0x6DB}},
+ {DDR1600 + DDR1866 + DDR2133, {0xB6D, 0xB6D, 0x924, 0x924}}
+ };
+ CONST STATIC TXPREPN_STRUCT TxPrePNCmdAddrV125TN[] = {
+ //{TxPreP, TxPreN}[Speed][Drive Strength] at 1.25V
+ {DDR667 + DDR800, {0x492, 0x492, 0x492, 0x492}},
+ {DDR1066 + DDR1333, {0xDAD, 0x924, 0x6DB, 0x492}},
+ {DDR1600 + DDR1866 + DDR2133, {0xFF6, 0xDAD, 0xB64, 0xB64}}
+ };
+ CONST STATIC TXPREPN_ENTRY TxPrePNCmdAddrTN[] = {
+ {GET_SIZE_OF (TxPrePNCmdAddrV15TN), (TXPREPN_STRUCT *)&TxPrePNCmdAddrV15TN},
+ {GET_SIZE_OF (TxPrePNCmdAddrV135TN), (TXPREPN_STRUCT *)&TxPrePNCmdAddrV135TN},
+ {GET_SIZE_OF (TxPrePNCmdAddrV125TN), (TXPREPN_STRUCT *)&TxPrePNCmdAddrV125TN}
+ };
+
+ //
+ // Phy Predriver Calibration Codes for Clock
+ //
+ CONST STATIC TXPREPN_STRUCT TxPrePNClockV15TN[] = {
+ //{TxPreP, TxPreN}[Speed][Drive Strength] at 1.5V
+ {DDR667 + DDR800, {0x924, 0x924, 0x924, 0x924}},
+ {DDR1066 + DDR1333, {0xFF6, 0xFF6, 0xFF6, 0xB6D}},
+ {DDR1600 + DDR1866 + DDR2133, {0xFF6, 0xFF6, 0xFF6, 0xFF6}}
+ };
+ CONST STATIC TXPREPN_STRUCT TxPrePNClockV135TN[] = {
+ //{TxPreP, TxPreN}[Speed][Drive Strength] at 1.35V
+ {DDR667 + DDR800, {0xDAD, 0xDAD, 0x924, 0x924}},
+ {DDR1066 + DDR1333, {0xFF6, 0xFF6, 0xFF6, 0xDAD}},
+ {DDR1600 + DDR1866 + DDR2133, {0xFF6, 0xFF6, 0xFF6, 0xDAD}}
+ };
+ CONST STATIC TXPREPN_STRUCT TxPrePNClockV125TN[] = {
+ //{TxPreP, TxPreN}[Speed][Drive Strength] at 1.25V
+ {DDR667 + DDR800, {0xDAD, 0xDAD, 0x924, 0x924}},
+ {DDR1066 + DDR1333, {0xFF6, 0xFF6, 0xFF6, 0xFF6}},
+ {DDR1600 + DDR1866 + DDR2133, {0xFF6, 0xFF6, 0xFF6, 0xFF6}}
+ };
+ CONST STATIC TXPREPN_ENTRY TxPrePNClockTN[] = {
+ {GET_SIZE_OF (TxPrePNClockV15TN), (TXPREPN_STRUCT *)&TxPrePNClockV15TN},
+ {GET_SIZE_OF (TxPrePNClockV135TN), (TXPREPN_STRUCT *)&TxPrePNClockV135TN},
+ {GET_SIZE_OF (TxPrePNClockV125TN), (TXPREPN_STRUCT *)&TxPrePNClockV125TN}
+ };
+
+ //
+ // Tables to describe the relationship between drive strength bit fields, PreDriver Calibration bit fields and also
+ // the extra value that needs to be written to specific PreDriver bit fields
+ //
+ CONST PHY_COMP_INIT_NB PhyCompInitBitFieldTN[] = {
+ // 3. Program TxPreP/TxPreN for Data and DQS according toTable 25 if VDDIO is 1.5V or Table 26 if 1.35V.
+ // A. Program D18F2x9C_x0D0F_0[F,7:0]0[A,6]_dct[1:0]={0000b, TxPreP, TxPreN}.
+ // B. Program D18F2x9C_x0D0F_0[F,7:0]02_dct[1:0]={0000b, TxPreP, TxPreN}.
+ {BFDqsDrvStren, BFDataByteTxPreDriverCal2Pad1, BFDataByteTxPreDriverCal2Pad1, 0, TxPrePNDataDqsTN},
+ {BFDataDrvStren, BFDataByteTxPreDriverCal2Pad2, BFDataByteTxPreDriverCal2Pad2, 0, TxPrePNDataDqsTN},
+ {BFDataDrvStren, BFDataByteTxPreDriverCal, BFDataByteTxPreDriverCal, 8, TxPrePNDataDqsTN},
+ // 4. Program TxPreP/TxPreN for Cmd/Addr according to Table 28 if VDDIO is 1.5V or Table 29 if 1.35V.
+ // A. Program D18F2x9C_x0D0F_[C,8][1:0][12,0E,0A,06]_dct[1:0]={0000b, TxPreP, TxPreN}.
+ // B. Program D18F2x9C_x0D0F_[C,8][1:0]02_dct[1:0]={1000b, TxPreP, TxPreN}.
+ {BFCsOdtDrvStren, BFCmdAddr0TxPreDriverCal2Pad1, BFCmdAddr0TxPreDriverCal2Pad2, 0, TxPrePNCmdAddrTN},
+ {BFAddrCmdDrvStren, BFCmdAddr1TxPreDriverCal2Pad1, BFAddrTxPreDriverCal2Pad4, 0, TxPrePNCmdAddrTN},
+ {BFCsOdtDrvStren, BFCmdAddr0TxPreDriverCalPad0, BFCmdAddr0TxPreDriverCalPad0, 8, TxPrePNCmdAddrTN},
+ {BFCkeDrvStren, BFAddrTxPreDriverCalPad0, BFAddrTxPreDriverCalPad0, 8, TxPrePNCmdAddrTN},
+ {BFAddrCmdDrvStren, BFCmdAddr1TxPreDriverCalPad0, BFCmdAddr1TxPreDriverCalPad0, 8, TxPrePNCmdAddrTN},
+ // 5. Program TxPreP/TxPreN for Clock according to Table 31 if VDDIO is 1.5V or Table 32 if 1.35V.
+ // A. Program D18F2x9C_x0D0F_2[2:0]02_dct[1:0]={1000b, TxPreP, TxPreN}.
+ {BFClkDrvStren, BFClock0TxPreDriverCalPad0, BFClock2TxPreDriverCalPad0, 8, TxPrePNClockTN}
+ };
+
+ BIT_FIELD_NAME CurrentBitField;
+ UINT32 SpeedMask;
+ UINT8 SizeOfTable;
+ UINT8 Voltage;
+ UINT8 i;
+ UINT8 j;
+ UINT8 k;
+ UINT8 Dct;
+ CONST TXPREPN_STRUCT *TblPtr;
+
+ Dct = NBPtr->Dct;
+ NBPtr->SwitchDCT (NBPtr, 0);
+ // 1. Program D18F2x[1,0]9C_x0000_0008[DisAutoComp, DisablePreDriverCal] = {1b, 1b}.
+ MemNSetBitFieldNb (NBPtr, BFDisablePredriverCal, 3);
+ NBPtr->SwitchDCT (NBPtr, Dct);
+
+ SpeedMask = (UINT32) 1 << (NBPtr->DCTPtr->Timings.Speed / 66);
+ Voltage = (UINT8) CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage);
+
+ for (j = 0; j < GET_SIZE_OF (PhyCompInitBitFieldTN); j ++) {
+ i = (UINT8) MemNGetBitFieldNb (NBPtr, PhyCompInitBitFieldTN[j].IndexBitField);
+ TblPtr = (PhyCompInitBitFieldTN[j].TxPrePN[Voltage]).TxPrePNTblPtr;
+ SizeOfTable = (PhyCompInitBitFieldTN[j].TxPrePN[Voltage]).TxPrePNTblSize;
+ for (k = 0; k < SizeOfTable; k++, TblPtr++) {
+ if ((TblPtr->Speed & SpeedMask) != 0) {
+ for (CurrentBitField = PhyCompInitBitFieldTN[j].StartTargetBitField; CurrentBitField <= PhyCompInitBitFieldTN[j].EndTargetBitField; CurrentBitField ++) {
+ MemNSetBitFieldNb (NBPtr, CurrentBitField, ((PhyCompInitBitFieldTN[j].ExtraValue << 12) | TblPtr->TxPrePNVal[i]));
+ }
+ break;
+ }
+ }
+ // Asserting if no table is found corresponding to current memory speed.
+ ASSERT (k < SizeOfTable);
+ }
+ NBPtr->SwitchDCT (NBPtr, 0);
+ // 6. Program D18F2x9C_x0000_0008_dct[1:0]_mp[1:0][DisAutoComp] = 0.
+ MemNSetBitFieldNb (NBPtr, BFDisablePredriverCal, 1);
+ NBPtr->SwitchDCT (NBPtr, Dct);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This is a general purpose function that executes before DRAM training
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNBeforeDQSTrainingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dct;
+
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ MemNSetBitFieldNb (NBPtr, BFTrNibbleSel, 0);
+ //
+ // 2.10.6.9.2 - BIOS should program D18F2x210_dct[1:0]_nbp[3:0][MaxRdLatency] to 55h.
+ //
+ MemNSetBitFieldNb (NBPtr, BFMaxLatency, 0x55);
+ NBPtr->CsPerDelay = MemNCSPerDelayNb (NBPtr);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This is a function that executes after DRAM training for TN
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNAfterDQSTrainingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dct;
+ BOOLEAN DllShutDownEn;
+ UINT8 Dimm;
+ UINT8 Byte;
+ UINT16 Dly;
+
+ DllShutDownEn = TRUE;
+ IDS_OPTION_HOOK (IDS_DLL_SHUT_DOWN, &DllShutDownEn, &(NBPtr->MemPtr->StdHeader));
+
+ MemNBrdcstSetNb (NBPtr, BFMemPhyPllPdMode, 2);
+ MemNBrdcstSetNb (NBPtr, BFPllLockTime, 0x190);
+
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ //
+ // 2.10.6.7 DCT Training Specific Configuration
+ //
+ MemNSetBitFieldNb (NBPtr, BFAddrCmdTriEn, 1);
+ MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 0);
+ if (DllShutDownEn && NBPtr->IsSupported[SetDllShutDown]) {
+ MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 0);
+ }
+ MemNSetBitFieldNb (NBPtr , BFForceAutoPchg, 0);
+ MemNSetBitFieldNb (NBPtr , BFDynPageCloseEn, 0);
+ if (NBPtr->RefPtr->EnableBankSwizzle) {
+ MemNSetBitFieldNb (NBPtr, BFBankSwizzleMode, 1);
+ }
+ MemNSetBitFieldNb (NBPtr, BFDcqBypassMax, 0x01F);
+ MemNPowerDownCtlTN (NBPtr);
+ MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 2);
+ MemNSetBitFieldNb (NBPtr, BFBankSwap, 1);
+ //
+ // Post Training values for BFRxMaxDurDllNoLock, BFTxMaxDurDllNoLock,
+ // and BFEnRxPadStandby are handled by Power savings code
+ //
+ // BFBwCapEn and BFODTSEn are handled by OnDimmThermal Code
+ //
+ // BFDctSelIntLvEn is programmed by Interleaving feature
+ //
+ }
+ }
+ //
+ //
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ if (!(NBPtr->DctCachePtr->excel846 )) {
+ for (Dimm = 0; Dimm < 4; Dimm++) {
+ for (Byte = 0; Byte < 9; Byte++) {
+ Dly = (UINT16) MemNGetTrainDlyNb (NBPtr, AccessRdDqsDly, DIMM_BYTE_ACCESS (Dimm, Byte));
+ MemNSetTrainDlyNb (NBPtr, excel845 , DIMM_NBBL_ACCESS (Dimm, Byte * 2), Dly);
+ MemNSetTrainDlyNb (NBPtr, excel845 , DIMM_NBBL_ACCESS (Dimm, (Byte * 2) + 1), Dly);
+ }
+ }
+ }
+ }
+ }
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function overrides the seed for hardware based RcvEn training of TN.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *SeedPtr - Pointer to the seed value.
+ *
+ * @return TRUE
+ */
+
+BOOLEAN
+MemNOverrideRcvEnSeedTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *SeedPtr
+ )
+{
+ *(UINT16 *)SeedPtr = 0x32 - (0x20 * (UINT16) MemNGetBitFieldNb (NBPtr, BFWrDqDqsEarly));
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function choose the correct PllLockTime for TN
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *PllLockTime - Bit offset of the field to be programmed
+ *
+ * @return TRUE
+ */
+BOOLEAN
+MemNAdjustPllLockTimeTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *PllLockTime
+ )
+{
+ if (MemNGetBitFieldNb (NBPtr, BFMemPhyPllPdMode) == 2) {
+ *(UINT16*) PllLockTime = 0x190;
+ }
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function overrides the seed for hardware based WL for TN.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *SeedPtr - Pointer to the seed value.
+ *
+ * @return TRUE
+ */
+
+BOOLEAN
+MemNOverrideWLSeedTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *SeedPtr
+ )
+{
+ if (NBPtr->ChannelPtr->SODimmPresent != 0) {
+ *(UINT8*) SeedPtr = 0xE;
+ } else {
+ // Unbuffered dimm
+ *(UINT8*) SeedPtr = 0x15;
+ }
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function adjusts Avg PRE value of Phy fence training for TN.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *Value16 - Pointer to the value that we want to adjust
+ *
+ */
+VOID
+MemNPFenceAdjustTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT INT16 *Value16
+ )
+{
+ if (*Value16 < 0) {
+ *Value16 = 0;
+ }
+
+ // This makes sure the phy fence value will be written to M1 context as well.
+ MULTI_MPSTATE_COPY_TSEFO (NBPtr->NBRegTable, BFPhyFence);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function programs Fence2RxDll for TN.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *Fence2Data - Pointer to the value of fence2 data
+ *
+ */
+BOOLEAN
+MemNProgramFence2RxDllTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *Fence2Data
+ )
+{
+ UINT8 Dct;
+ UINT16 Fence2RxDllTxPad;
+ UINT16 Fence2Value;
+ UINT16 Fence1;
+ BIT_FIELD_NAME BitField;
+
+ Fence2Value = (UINT16) MemNGetBitFieldNb (NBPtr, BFFence2);
+ Fence2RxDllTxPad = (*(UINT16*) Fence2Data & 0x1F) | (((*(UINT16*) Fence2Data >> 5) & 0x1F) << 10);
+
+ Fence2Value &= ~(UINT16) ((0x1F << 10) | 0x1F);
+ Fence2Value |= Fence2RxDllTxPad;
+ MemNSetBitFieldNb (NBPtr, BFFence2, Fence2Value);
+
+ if (NBPtr->MemPstateStage == MEMORY_PSTATE_1ST_STAGE) {
+ MAKE_TSEFO (NBPtr->NBRegTable, DCT_PHY_ACCESS, 0x0C, 30, 16, BFPhyFence);
+ BitField = (NBPtr->Dct == 0) ? BFChAM1FenceSave : BFChBM1FenceSave;
+
+ Fence1 = (UINT16) MemNGetBitFieldNb (NBPtr, BFPhyFence);
+ Dct = NBPtr->Dct;
+ MemNSwitchDCTNb (NBPtr, 1);
+ MemNSetBitFieldNb (NBPtr, BitField, Fence1);
+ MemNSwitchDCTNb (NBPtr, Dct);
+ }
+
+ return TRUE;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function checks if RdDqsDly needs to be restarted for Trinity
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *Center - Center of the data eye
+ *
+ * @return TRUE
+ */
+
+BOOLEAN
+MemNRdDqsDlyRestartChkTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *Center
+ )
+{
+ INT8 EyeCenter;
+ UINT8 ByteLane;
+ BOOLEAN RetVal;
+ MEM_TECH_BLOCK *TechPtr;
+ CH_DEF_STRUCT *ChanPtr;
+
+ TechPtr = NBPtr->TechPtr;
+ ChanPtr = NBPtr->ChannelPtr;
+ ByteLane = NBPtr->TechPtr->Bytelane;
+ RetVal = TRUE;
+
+ // If the average value of passing read DQS delay for the lane is negative, then adjust the input receiver
+ // DQ delay in D18F2x9C_x0D0F_0[F,7:0][5F,1F]_dct[1:0] for the lane as follows:
+
+ EyeCenter = ((INT8) ChanPtr->RdDqsMinDlys[ByteLane] + (INT8) ChanPtr->RdDqsMaxDlys[ByteLane] + 1) / 2;
+
+ if ((EyeCenter < 0) && (NBPtr->RdDqsDlyRetrnStat != RDDQSDLY_RTN_SUSPEND)) {
+ IDS_HDT_CONSOLE (MEM_FLOW, " Negative data eye center.\n");
+
+ if (MemNGetBitFieldNb (NBPtr, BFRxBypass3rd4thStg) == 4) {
+ // IF (RxBypass3rd4thStg == 1) program RxBypass3rd4thStg=0 and repeat step 3 above for all
+ // ranks and lanes
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tRxByPass3rd4thStg is 1, clear it and restart RdDqsDly training on current Dct.\n");
+
+ MemNSetBitFieldNb (NBPtr, BFRxBypass3rd4thStg, 0);
+ NBPtr->RdDqsDlyRetrnStat = RDDQSDLY_RTN_ONGOING;
+
+ // When Retrain condition is first detected, record the current chipsel at which the retrain starts
+ // so we don't need to retrain RcvEnDly and WrDatDly on the chipsels that are already done with these steps.
+ TechPtr->RestartChipSel = (INT8) TechPtr->ChipSel;
+
+ RetVal = FALSE;
+ } else if (MemNGetBitFieldNb (NBPtr, BFRx4thStgEn) == 0) {
+ // ELSEIF (Rx4thStgEn == 0) program Rx4thStgEn=1 and repeat step 3 above for all ranks and lanes
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tRx4thStg is 0, set it and restart RdDqsDly training on current Dct.\n");
+
+ MemNSetBitFieldNb (NBPtr, BFRx4thStgEn, 0x100);
+ NBPtr->RdDqsDlyRetrnStat = RDDQSDLY_RTN_ONGOING;
+
+ // If the second retrain starts beyond the chip selects that are previously trained, update the record so
+ // we don't need to retrain RcvEnDly and WrDatDly
+ if (TechPtr->RestartChipSel < ((INT8) TechPtr->ChipSel)) {
+ TechPtr->RestartChipSel = (INT8) TechPtr->ChipSel;
+ }
+
+ RetVal = FALSE;
+ } else {
+ // ELSE program the read DQS delay for the lane with a value of zero
+ IDS_HDT_CONSOLE (MEM_FLOW, " ");
+ IDS_HDT_CONSOLE (MEM_FLOW, "Center of data eye is still negative after 2 retires. Do not restart training, just use 0\n");
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t ");
+ *(UINT8 *) Center = 0;
+ }
+ }
+
+ return RetVal;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function executes RdDQS training
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ * @return TRUE - All bytelanes pass
+ * @return FALSE - Some bytelanes fail
+*/
+BOOLEAN
+MemNRdPosTrnTN (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ BOOLEAN RetVal;
+
+ if (((INT8) TechPtr->ChipSel) > TechPtr->RestartChipSel) {
+ RetVal = MemTRdPosWithRxEnDlySeeds3 (TechPtr);
+ } else {
+ // Skip RcvEnDly cycle training when current chip select has already gone through that step.
+ // Because a retrain condition can only be detected on a chip select after RcvEnDly cycle training
+ // So when current chip select is equal to RestartChipSel, we don't need to redo RcvEnDly cycle training.
+ // Only redo DQS position training.
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\tSkip RcvEnDly Cycle Training on Current Chip Select.\n\n");
+ RetVal = MemTTrainDQSEdgeDetect (TechPtr);
+ }
+ return RetVal;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function skips WrDatDly training when a retrain condition is just detected
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *ChipSel - Pointer to ChipSel
+ *
+ * @return TRUE
+ */
+
+BOOLEAN
+MemNHookBfWrDatTrnTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *ChipSel
+ )
+{
+ BOOLEAN RetVal;
+
+ RetVal = TRUE;
+ if (NBPtr->RdDqsDlyRetrnStat == RDDQSDLY_RTN_ONGOING) {
+ NBPtr->RdDqsDlyRetrnStat = RDDQSDLY_RTN_NEEDED;
+ // Clear chipsel value to force a restart of Rd Dqs Training
+ if (NBPtr->CsPerDelay == 1) {
+ *(UINT8 *) ChipSel = 0xFF;
+ } else {
+ *(UINT8 *) ChipSel = 0xFE;
+ }
+
+ RetVal = FALSE;
+ } else if (((INT8) NBPtr->TechPtr->ChipSel) < NBPtr->TechPtr->RestartChipSel) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSkip WrDatDly Training on Current Chip Select.\n\n");
+ // Skip WrDatDly training when current chip select has gone through WrDatDly procedure
+ // A retrain is detected during RdDqsDly training, so if RestartChipSel is equal to current
+ // chip select, then WrDatDly has not been started for current chip select in the previous cycle.
+ // However, RcvEnDly cycle training has been done for current chip select.
+ // So we don't need to do RcvEnDly cycle training when current chip select is equal to RestartChipSel
+ // but we need to do WrDatDly training for current chip select.
+ RetVal = FALSE;
+ }
+
+ // when return is FALSE, WrDatDly training will be skipped
+
+ return RetVal;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets up output driver and write leveling mode in MR1 during WL
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *Value - MR1 value
+ *
+ * @return TRUE
+ */
+
+BOOLEAN
+MemNWLMR1TN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *Value
+ )
+{
+ BOOLEAN Target;
+
+ // For the target rank of the target DIMM, enable write leveling mode and enable the output driver.
+ // For all other ranks of the target DIMM, enable write leveling mode and disable the output driver.
+ Target = (BOOLEAN) (*(UINT16 *) Value >> 7) & 1;
+
+ if (NBPtr->CsPerDelay == 1) {
+ // Clear Qoff and reset it based on TN requirement
+ *(UINT16 *) Value &= ~((UINT16) 1 << 12);
+
+ if (!Target) {
+ *(UINT16 *) Value |= (((UINT16) 1 << 7) | ((UINT16) 1 << 12));
+ }
+ }
+
+ return TRUE;
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnregtn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnregtn.c
new file mode 100644
index 0000000000..385416575c
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mnregtn.c
@@ -0,0 +1,856 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnregtn.c
+ *
+ * Common Northbridge register related functions for TN
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 64574 $ @e \$Date: 2012-01-25 01:01:51 -0600 (Wed, 25 Jan 2012) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "Gnb.h"
+#include "GnbCommonLib.h"
+#include "GnbRegistersTN.h"
+#include "GnbRegisterAccTN.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "mntn.h"
+#include "merrhdl.h"
+#include "cpuRegisters.h"
+#include "cpuFamRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+
+#define FILECODE PROC_MEM_NB_TN_MNREGTN_FILECODE
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define PHY_DIRECT_ADDRESS_MASK 0x0D000000ul
+
+STATIC CONST UINT8 InstancesPerTypeTN[8] = {8, 3, 1, 2, 2, 0, 1, 1};
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*-----------------------------------------------------------------------------*/
+/**
+ * MemNIsIdSupportedTn
+ * This function matches the CPU_LOGICAL_ID with certain criteria to
+ * determine if it is supported by this NBBlock.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *LogicalIdPtr - Pointer to the CPU_LOGICAL_ID
+ *
+ * @return TRUE - This node is a TN.
+ * @return FALSE - This node is not a TN.
+ *
+ */
+BOOLEAN
+MemNIsIdSupportedTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ )
+{
+ if (((LogicalIdPtr->Family & AMD_FAMILY_15_TN) != 0)
+ && ((LogicalIdPtr->Revision & (AMD_F15_OR_ALL | AMD_F15_TN_ALL | 0x0000000000100000ull) ) != 0)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------*/
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets or sets a value to a bit field in a PCI register.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] FieldName - Bit Field to be programmed
+ * @param[in] Field - Value to be programmed
+ * @param[in] IsSet - Indicates if the function will set or get
+ *
+ * @return value read, if the function is used as a "get"
+ */
+
+UINT32
+MemNCmnGetSetFieldTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ TSEFO Address;
+ PCI_ADDR PciAddr;
+ UINT8 Type;
+ UINT8 IsLinked;
+ UINT32 Value;
+ UINT32 Highbit;
+ UINT32 Lowbit;
+ UINT32 Mask;
+ UINT8 IsPhyDirectAccess;
+ UINT8 IsWholeRegAccess;
+ UINT8 NumOfInstances;
+ UINT8 Instance;
+ UINT8 IsMultipleMPstate;
+
+ Value = 0;
+ if (FieldName == BFDctAccessDone) {
+ // No need to poll DctAccessDone for TN due to enhancement in phy
+ Value = 1;
+ } else if ((FieldName < BFEndOfList) && (FieldName >= 0)) {
+ Address = NBPtr->NBRegTable[FieldName];
+ if (Address) {
+ Lowbit = TSEFO_END (Address);
+ Highbit = TSEFO_START (Address);
+ Type = (UINT8) TSEFO_TYPE (Address);
+ IsLinked = (UINT8) TSEFO_LINKED (Address);
+ IsPhyDirectAccess = (UINT8) TSEFO_DIRECT_EN (Address);
+ IsWholeRegAccess = (UINT8) TSEFO_WHOLE_REG_ACCESS (Address);
+ if (NBPtr->MemPstate == MEMORY_PSTATE0) {
+ IsMultipleMPstate = TSEFO_MULTI_MPSTATE_COPY (Address);
+ } else {
+ // Do not write in both instances when context is already in MP1
+ IsMultipleMPstate = 0;
+ }
+
+ Address = TSEFO_OFFSET (Address);
+
+ // By default, a bit field has only one instance
+ NumOfInstances = 1;
+
+ if ((Type == DCT_PHY_ACCESS) && IsPhyDirectAccess) {
+ Address |= PHY_DIRECT_ADDRESS_MASK;
+ if (IsWholeRegAccess) {
+ // In the case of whole regiter access (bit 0 to 15),
+ // HW broadcast and nibble mask will be used.
+ Address |= Lowbit << 16;
+ Lowbit = 0;
+ Highbit = 15;
+ } else {
+ // In the case only some bits on a register is accessed,
+ // BIOS will do read-mod-write to all chiplets manually.
+ // And nibble mask will be 1111b always.
+ if ((Address & 0xFFFF) == 0xE008) {
+ // Special case for PStateToAccess, which use nibble mask
+ Address |= 0x00040000;
+ } else {
+ Address |= 0x000F0000;
+ }
+ Field >>= Lowbit;
+ if ((Address & 0x0F00) == 0x0F00) {
+ // Broadcast mode
+ // Find out how many instances to write to
+ NumOfInstances = InstancesPerTypeTN[(Address >> 13) & 0x7];
+ if (!IsSet) {
+ // For read, only read from instance 0 in broadcast mode
+ NumOfInstances = 1;
+ }
+ }
+ }
+ }
+
+ ASSERT (NumOfInstances > 0);
+
+ for (Instance = 0; Instance < NumOfInstances; Instance++) {
+ if (Type == NB_ACCESS) {
+ PciAddr.AddressValue = Address;
+ PciAddr.Address.Device = NBPtr->PciAddr.Address.Device;
+ PciAddr.Address.Bus = NBPtr->PciAddr.Address.Bus;
+ PciAddr.Address.Segment = NBPtr->PciAddr.Address.Segment;
+ Address = PciAddr.AddressValue;
+ LibAmdPciRead (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
+ if ((FieldName != BFDctAddlDataReg) && (FieldName != BFDctAddlOffsetReg) && (FieldName != BFDctCfgSel)) {
+ IDS_HDT_CONSOLE (MEM_GETREG, "~Dev%x Dct%d Fn%d_%03x = %x\n",
+ NBPtr->PciAddr.Address.Device, NBPtr->Dct,
+ (Address >> 12) & 0xF, Address & 0xFFF, Value);
+ }
+ } else if (Type == DCT_PHY_ACCESS) {
+ if (IsPhyDirectAccess && (NumOfInstances > 1)) {
+ Address = (Address & 0x0FFFF0FF) | (((UINT32) Instance) << 8);
+ }
+ MemNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ Value = MemNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+ IDS_HDT_CONSOLE (MEM_GETREG, "~Dev%x Dct%d Fn2_9C_%x = %x\n", NBPtr->PciAddr.Address.Device, NBPtr->Dct, Address & 0x0FFFFFFF, Value);
+ } else {
+ // DCT_EXTRA_ACCESS is not supported on TN
+ ASSERT (FALSE);
+ }
+
+ if (IsSet) {
+ // A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case
+ if ((Highbit - Lowbit) != 31) {
+ Mask = (((UINT32)1 << (Highbit - Lowbit + 1)) - 1);
+ } else {
+ Mask = (UINT32)0xFFFFFFFF;
+ }
+ Value &= ~(Mask << Lowbit);
+ Value |= (Field & Mask) << Lowbit;
+
+ do {
+ if (Type == NB_ACCESS) {
+ PciAddr.AddressValue = Address;
+ LibAmdPciWrite (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
+ if ((FieldName != BFDctAddlDataReg) && (FieldName != BFDctAddlOffsetReg) && (FieldName != BFDctCfgSel)) {
+ IDS_HDT_CONSOLE (MEM_SETREG, "~Dev%x Dct%d Fn%d_%03x [%d:%d] = %x\n",
+ NBPtr->PciAddr.Address.Device, NBPtr->Dct,
+ (Address >> 12) & 0xF, Address & 0xFFF, Highbit, Lowbit, Field);
+ }
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+ MemNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ IDS_HDT_CONSOLE (MEM_SETREG, "~Dev%x Dct%d Fn2_9C_%x [%d:%d] = %x\n",
+ NBPtr->PciAddr.Address.Device, NBPtr->Dct,
+ Address & 0x0FFFFFFF, Highbit, Lowbit, Field);
+ } else {
+ // DCT_EXTRA_ACCESS is not supported on TN
+ ASSERT (FALSE);
+ }
+ if (IsLinked) {
+ MemNCmnGetSetFieldTN (NBPtr, 1, FieldName + 1, Field >> (Highbit - Lowbit + 1));
+ }
+ if (IsMultipleMPstate && (NBPtr->MemPstateStage == MEMORY_PSTATE_1ST_STAGE)) {
+ // if there are multiple Pstate register copies, program register in M1 context when the frequency is DDR667
+ if (NBPtr->MemPstate == MEMORY_PSTATE0) {
+ MemNChangeMemPStateContextNb (NBPtr, 1);
+ } else {
+ // Switch back to M0 context
+ MemNChangeMemPStateContextNb (NBPtr, 0);
+ }
+ }
+ } while ((NBPtr->MemPstate == MEMORY_PSTATE1) && IsMultipleMPstate && (NBPtr->MemPstateStage == MEMORY_PSTATE_1ST_STAGE));
+ } else {
+ Value = Value >> Lowbit; // Shift
+ // A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case
+ if ((Highbit - Lowbit) != 31) {
+ Value &= (((UINT32)1 << (Highbit - Lowbit + 1)) - 1);
+ }
+ if (IsLinked) {
+ Value |= MemNCmnGetSetFieldTN (NBPtr, 0, FieldName + 1, 0) << (Highbit - Lowbit + 1);
+ }
+ // For direct phy access, shift the bit back for compatibility reason.
+ if ((Type == DCT_PHY_ACCESS) && IsPhyDirectAccess) {
+ Value <<= Lowbit;
+ }
+ }
+ }
+ } else {
+ IDS_HDT_CONSOLE (MEM_UNDEF_BF, "\t\tUndefined BF enum: %x\n", FieldName);
+ }
+ } else {
+ ASSERT (FALSE); // Invalid bit field index
+ }
+ return Value;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes bit field translation table
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] NBRegTable[] - Pointer to the bit field data structure
+ *
+ */
+
+VOID
+MemNInitNBRegTableTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT TSEFO NBRegTable[]
+ )
+{
+ UINT16 i;
+
+ // Allocate heap for NB register table
+ if (!MemNAllocateNBRegTableNb (NBPtr, NbRegTabTN)) {
+ return; // escape if fails
+ }
+ NBRegTable = NBPtr->NBRegTable;
+
+ for (i = 0; i < BFEndOfList; i++) {
+ NBRegTable[i] = 0;
+ }
+
+ // ---------------------------------------------------------------------------
+ //
+ // FUNCTION 1
+ //
+ // ---------------------------------------------------------------------------
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x40), 31, 0, BFDramBaseReg0);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x44), 31, 0, BFDramLimitReg0);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0xF0), 31, 0, BFDramHoleAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x140), 7, 0, BFDramBaseHiReg0);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x144), 7, 0, BFDramLimitHiReg0);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x40), 0, 0, BFDramRngRE0);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x40), 1, 1, BFDramRngWE0);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x44), 2, 0, BFDramRngDstNode0);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0xF0), 31, 24, BFDramHoleBase);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0xF0), 15, 7, BFDramHoleOffset);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0xF0), 1, 1, BFDramMemHoistValid);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0xF0), 0, 0, BFDramHoleValid);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x10C), 5, 4, BFNbPsSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x10C), 3, 3, BFMemPsSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x10C), 0, 0, BFDctCfgSel);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x120), 20, 0, BFDramBaseAddr);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (1, 0x124), 20, 0, BFDramLimitAddr);
+ // ---------------------------------------------------------------------------
+ //
+ // FUNCTION 2
+ //
+ // ---------------------------------------------------------------------------
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x40), 31, 0, BFCSBaseAddr0Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x44), 31, 0, BFCSBaseAddr1Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x48), 31, 0, BFCSBaseAddr2Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x4C), 31, 0, BFCSBaseAddr3Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x50), 31, 0, BFCSBaseAddr4Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x54), 31, 0, BFCSBaseAddr5Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x58), 31, 0, BFCSBaseAddr6Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x5C), 31, 0, BFCSBaseAddr7Reg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x60), 31, 0, BFCSMask0Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x64), 31, 0, BFCSMask1Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x68), 31, 0, BFCSMask2Reg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x6C), 31, 0, BFCSMask3Reg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 17, 17, BFAddrCmdTriEn);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 0, BFDramInitRegReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 31, BFEnDramInit);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 30, 30, BFSendCtrlWord);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 29, 29, BFSendZQCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 28, 28, BFAssertCke);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 27, 27, BFDeassertMemRstX);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 26, 26, BFSendMrsCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 25, 25, BFSendAutoRefresh);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 23, 21, BFMrsChipSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 20, 18, BFMrsBank);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 17, 0, BFMrsAddress);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x80), 16, 0, BFDramBankAddrReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 31, 0, BFDramMRSReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 23, 23, BFPchgPDModeSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 1, 0, BFBurstCtrl);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x88), 29, 24, BFMemClkDis);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 18, 18, BFDisAutoRefresh);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 17, 16, BFTref);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 27, 27, BFDisDllShutdownSR);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 25, 25, BFPendRefPaybackS3En);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 24, 24, BFStagRefEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 23, 23, BFForceAutoPchg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 20, 20, BFDynPageCloseEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 17, 17, BFEnterSelfRef);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 16, 16, BFUnBuffDimm);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 1, 1, BFExitSelfRef);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31, 0, BFDramConfigHiReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31, 31, BFDphyMemPsSelEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 28, 24, BFDcqBypassMax);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 22, 22, BFBankSwizzleMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 21, 21, BFFreqChgInProg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 20, 20, BFSlowAccessMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 19, 19, BFDcqArbBypassEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 16, 16, BFPowerDownMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 15, 15, BFPowerDownEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 14, 14, BFDisDramInterface);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 11, 10, BFZqcsInterval);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 7, 7, BFMemClkFreqVal);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 4, 0, BFMemClkFreq);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x98), 31, 0, BFDctAddlOffsetReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x9C), 31, 0, BFDctAddlDataReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA4), 23, 20, BFBwCapCmdThrottleMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA4), 14, 12, BFCmdThrottleMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA4), 11, 11, BFBwCapEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA4), 8, 8, BFODTSEn);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 31, 31, BFPerRankTimingEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 29, 29, BFRefChCmdMgtDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 28, 28, BFFastSelfRefEntryDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 22, 22, BFPrtlChPDEnhEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 21, 21, BFAggrPDEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 20, 20, BFBankSwap);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 17, 16, BFMemPhyPllPdMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 15, 8, BFCtrlWordCS);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 5, 5, BFSubMemclkRegDly);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x10C), 0, 0, BFIntLvRgnSwapEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x10C), 9, 3, BFIntLvRgnBaseAddr);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x10C), 17, 11, BFIntLvRgnLmtAddr);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x10C), 26, 20, BFIntLvRgnSize);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 31, 11, BFDctSelBaseAddr);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 10, 10, BFMemCleared);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 9, 9, BFMemClrBusy);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 8, 8, BFDramEnabled);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 7, 6, BFDctSelIntLvAddr);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 5, 5, BFDctDatIntLv);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 3, 3, BFMemClrInit);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 2, 2, BFDctSelIntLvEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 1, 1, BFDctSelHi);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 0, 0, BFDctSelHiRngEn);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 31, 10, BFDctSelBaseOffset);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 9, 9, BFDctSelIntLvAddrHi);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x118), 31, 0, BFMctCfgLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x118), 27, 27, BFMctEccDisLatOptEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x118), 19, 19, BFLockDramCfg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x118), 18, 18, BFCC6SaveEn);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 31, 0, BFMctCfgHiReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x1B0), 31, 0, BFExtMctCfgLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x1B4), 31, 0, BFExtMctCfgHiReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x1B4), 27, 27, BFFlushWrOnS3StpGnt);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x1B4), 26, 26, BFEnSplitMctDatBuffers);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x200), 29, 24, BFTras);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x200), 20, 16, BFTrp);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x200), 12, 8, BFTrcd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x200), 4, 0, BFTcl);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x204), 27, 24, BFTrtp);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x204), 21, 16, BFFourActWindow);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x204), 11, 8, BFTrrd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x204), 5, 0, BFTrc);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x208), 26, 24, BFTrfc3);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x208), 18, 16, BFTrfc2);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x208), 10, 8, BFTrfc1);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x208), 2, 0, BFTrfc0);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x20C), 17, 16, BFWrDqDqsEarly);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x20C), 11, 8, BFTwtr);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x20C), 4, 0, BFTcwl);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x210), 31, 22, BFMaxLatency);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x210), 18, 16, BFDataTxFifoWrDly);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x210), 3, 0, BFRdPtrInit);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x214), 19, 16, BFTwrwrSdSc);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x214), 11, 8, BFTwrwrSdDc);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x214), 3, 0, BFTwrwrDd);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x218), 27, 24, BFTrdrdSdSc);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x218), 19, 16, BFTrdrdSdDc);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x218), 11, 8, BFTwrrd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x218), 3, 0, BFTrdrdDd);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x21C), 20, 16, BFTrwtWB);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x21C), 12, 8, BFTrwtTO);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x220), 12, 8, BFTmod);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x220), 3, 0, BFTmrd);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x224), 10, 8, BFTzqcs);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x224), 3, 0, BFTzqoper);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x228), 31, 24, BFTstag3);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x228), 23, 16, BFTstag2);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x228), 15, 8, BFTstag1);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x228), 7, 0, BFTstag0);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x22C), 4, 0, BFTwrDDR3);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x230), 31, 0, BFPhyRODTCSLow);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x234), 31, 0, BFPhyRODTCSHigh);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x238), 31, 0, BFPhyWODTCSLow);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x23C), 31, 0, BFPhyWODTCSHigh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x240), 14, 12, BFWrOdtOnDuration);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x240), 10, 8, BFWrOdtTrnOnDly);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x240), 6, 4, BFRdOdtOnDuration);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x240), 3, 0, BFRdOdtTrnOnDly);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x244), 3, 0, BFPrtlChPDDynDly);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x248), 31, 31, BFRxChMntClkEn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x248), 29, 24, BFAggrPDDelay);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x248), 21, 16, BFPchgPDEnDelay);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x248), 12, 8, BFTxpdll);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x248), 3, 0, BFTxp);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x24C), 29, 24, BFTcksrx);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x24C), 21, 16, BFTcksre);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x24C), 13, 8, BFTckesr);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x24C), 3, 0, BFTpd);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 12, 12, BFCmdSendInProg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 11, 11, BFSendCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 10, 10, BFTestStatus);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 9, 8, BFCmdTgt);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 7, 5, BFCmdType);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 4, 4, BFStopOnErr);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 3, 3, BFResetAllErr);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 2, 2, BFCmdTestEnable);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 13, 13, BFLfsrRollOver );
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x254), 26, 24, BFTgtChipSelectA);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x254), 23, 21, BFTgtBankA);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x254), 9, 0, BFTgtAddressA);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x258), 26, 24, BFTgtChipSelectB);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x258), 23, 21, BFTgtBankB);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x258), 9, 0, BFTgtAddressB);
+
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x260), 20, 0, BFCmdCount);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x264), 31, 25, BFErrDqNum);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x264), 24, 0, BFErrCnt);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x268), 17, 0, BFNibbleErrSts);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x26C), 17, 0, BFNibbleErr180Sts);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x270), 18, 0, BFDataPrbsSeed);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x274), 31, 0, BFDramDqMaskLow );
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x278), 31, 0, BFDramDqMaskHigh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x28C), 31, 31, BFSendActCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x28C), 30, 30, BFSendPchgCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x28C), 29, 22, BFCmdChipSelect);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x28C), 21, 19, BFCmdBank);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x28C), 17, 0, BFCmdAddress);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x28C), 31, 0, BFDramCommand2 );
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x290), 26, 24, BFErrBeatNum);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x290), 20, 0, BFErrCmdNum);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x294), 31, 0, BFDQErrLow);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x298), 31, 0, BFDQErrHigh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x2E0), 30, 30, BFFastMstateDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x2E0), 28, 24, BFM1MemClkFreq);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x2E0), 22, 20, BFMxMrsEn);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x2E8), 31, 16, BFMxMr1);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x2E8), 15, 0, BFMxMr0);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x2EC), 15, 0, BFMxMr2);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x2F0), 0, 0, BFEffArbDis);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x400), 11, 8, BFGmcTokenLimit);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x400), 3, 0, BFMctTokenLimit);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x404), 16, 0, BFGmcToDctControl1);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x408), 0, 0, BFCpuElevPrioDis);
+
+ // ---------------------------------------------------------------------------
+ //
+ // DCT PHY REGISTERS
+ //
+ // ---------------------------------------------------------------------------
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 31, 0, BFODCControl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 22, 20, BFDqsDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 18, 16, BFDataDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 14, 12, BFClkDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 10, 8, BFAddrCmdDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 6, 4, BFCsOdtDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 2, 0, BFCkeDrvStren);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x04, 31, 0, BFAddrTmgControl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 30, 29, BFDisablePredriverCal);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 13, 13, BFDqsRcvTrEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 12, 12, BFWrLvOdtEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 11, 8, BFWrLvOdt);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 7, 6, BFFenceTrSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 5, 4, BFTrDimmSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 3, 3, BFPhyFenceTrEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 2, 2, BFTrNibbleSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 0, 0, BFWrtLvTrEn);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0B, 31, 0, BFDramPhyStatusReg);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0C, 20, 16, BFPhyFence);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0C, 15, 12, BFCKETri);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0C, 11, 8, BFODTTri);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0C, 7, 0, BFChipSelTri);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D, 25, 24, BFRxDLLWakeupTime);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D, 22, 20, BFRxCPUpdPeriod);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D, 19, 16, BFRxMaxDurDllNoLock);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D, 9, 8, BFTxDLLWakeupTime);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D, 6, 4, BFTxCPUpdPeriod);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D, 3, 0, BFTxMaxDurDllNoLock);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x50, 31, 0, BFRstRcvFifo);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F13, 8, 8, BFRxSsbMntClkEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F13, 14, 14, BFProcOdtAdv);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F13, 7, 0, BFPhy0x0D0F0F13);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F30, 4, 4, BFEccDLLPwrDnConf);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FE013, 15, 0, BFPllRegWaitTime);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FE006, 15, 0, BFPllLockTime);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F02, 15, 0, BFDataByteTxPreDriverCal);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F06, 15, 0, BFDataByteTxPreDriverCal2Pad1);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F0A, 15, 0, BFDataByteTxPreDriverCal2Pad2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F8006, 15, 0, BFCmdAddr0TxPreDriverCal2Pad1);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F800A, 15, 0, BFCmdAddr0TxPreDriverCal2Pad2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F8106, 15, 0, BFCmdAddr1TxPreDriverCal2Pad1);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F810A, 15, 0, BFCmdAddr1TxPreDriverCal2Pad2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FC006, 15, 0, BFAddrTxPreDriverCal2Pad1);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FC00A, 15, 0, BFAddrTxPreDriverCal2Pad2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FC00E, 15, 0, BFAddrTxPreDriverCal2Pad3);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FC012, 15, 0, BFAddrTxPreDriverCal2Pad4);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F8002, 15, 0, BFCmdAddr0TxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F8102, 15, 0, BFCmdAddr1TxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FC002, 15, 0, BFAddrTxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F2002, 15, 0, BFClock0TxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F2102, 15, 0, BFClock1TxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F2202, 15, 0, BFClock2TxPreDriverCalPad0);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F812F, 15, 0, BFAddrCmdTri);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F10, 12, 12, BFEnRxPadStandby);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F10, 3, 0, BFDllNoLock);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D04E008, 8, 8, BFPStateToAccess);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FE00A, 4, 4, BFSkewMemClk);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F4003, 15, 0, BFChAM1FenceSave);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F4004, 15, 0, BFChBM1FenceSave);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F2030, 4, 4, BFPhyClkConfig0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F2130, 4, 4, BFPhyClkConfig1);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FC000, 8, 8, BFLowPowerDrvStrengthEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FE040, 3, 0, BFRate);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F1F, 8, 8, BFRx4thStgEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F1F, 4, 3, BFDataRxVioLvl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F1F, 2, 2, BFRxBypass3rd4thStg);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F2F1F, 4, 3, BFClkRxVioLvl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F4009, 3, 2, BFCsrComparator);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F4009, 15, 14, BFCmpVioLvl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F8F1F, 4, 3, BFCmdRxVioLvl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FC01F, 4, 3, BFAddrRxVioLvl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F31, 9, 0, BFDataFence2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FE019, 14, 0, BFFence2);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F30, 8, 8, BFBlockRxDqsLock);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F001C, 15, 0, BFDataByteDllPowerMgnByte0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F011C, 15, 0, BFDataByteDllPowerMgnByte1);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F021C, 15, 0, BFDataByteDllPowerMgnByte2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F031C, 15, 0, BFDataByteDllPowerMgnByte3);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F041C, 15, 0, BFDataByteDllPowerMgnByte4);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F051C, 15, 0, BFDataByteDllPowerMgnByte5);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F061C, 15, 0, BFDataByteDllPowerMgnByte6);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F071C, 15, 0, BFDataByteDllPowerMgnByte7);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0F0F1C, 15, 0, BFDataByteDllPowerMgnByteAll);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_DIRECT, 0x0D0FE018, 8, 8, BFPhyPSMasterChannel);
+
+
+ // ---------------------------------------------------------------------------
+ //
+ // FUNCTION 4
+ //
+ // ---------------------------------------------------------------------------
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (4, 0x128), 17, 12, BFCoreStateSaveDestNode);
+
+ // ---------------------------------------------------------------------------
+ //
+ // FUNCTION 5
+ //
+ // ---------------------------------------------------------------------------
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x84), 20, 16, BFDdrMaxRate);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x160), 18, 18, BFMemPstate0);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x164), 18, 18, BFMemPstate1);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x168), 18, 18, BFMemPstate2);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x16C), 18, 18, BFMemPstate3);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x160), 16, 10, BFNbVid0);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x164), 16, 10, BFNbVid1);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x168), 16, 10, BFNbVid2);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x16C), 16, 10, BFNbVid3);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x160), 21, 21, BFNbVid0Hi);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x164), 21, 21, BFNbVid1Hi);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x168), 21, 21, BFNbVid2Hi);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x16C), 21, 21, BFNbVid3Hi);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x170), 31, 0, BFNbPstateCtlReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x170), 31, 31, BFMemPstateDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x170), 14, 14, BFSwNbPstateLoDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x170), 7, 6, BFNbPstateHi);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x170), 4, 3, BFNbPstateLo);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x170), 1, 0, BFNbPstateMaxVal);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x174), 24, 24, BFCurMemPstate);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x174), 20, 19, BFCurNbPstate);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x174), 0, 0, BFNbPstateDis);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x188), 1, 0, BFNbOffsetTrim);
+
+ // ---------------------------------------------------------------------------
+ //
+ // LINK BITFIELD
+ //
+ // ---------------------------------------------------------------------------
+ LINK_TSEFO (NBRegTable, BFDctSelIntLvAddr, BFDctSelIntLvAddrHi);
+ LINK_TSEFO (NBRegTable, BFNbVid0, BFNbVid0Hi);
+ LINK_TSEFO (NBRegTable, BFNbVid1, BFNbVid1Hi);
+ LINK_TSEFO (NBRegTable, BFNbVid2, BFNbVid2Hi);
+ LINK_TSEFO (NBRegTable, BFNbVid3, BFNbVid3Hi);
+
+ // ---------------------------------------------------------------------------
+ //
+ // REGISTERS WITH MULTIPLE MEMORY PSTATE COPIES
+ //
+ // ---------------------------------------------------------------------------
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFODCControl);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFDqsDrvStren);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFDataDrvStren);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFClkDrvStren);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFAddrCmdDrvStren);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFCsOdtDrvStren);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFCkeDrvStren);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFAddrTmgControl);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFDisablePredriverCal);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFProcOdtAdv);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFDataRxVioLvl);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFRx4thStgEn);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFRxBypass3rd4thStg);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTras);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTrp);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTrcd);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTcl);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTrtp);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFFourActWindow);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTrrd);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTrc);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFWrDqDqsEarly);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTwtr);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTcwl);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFTwrDDR3);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFWrOdtOnDuration);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFWrOdtTrnOnDly);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFRdOdtOnDuration);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFRdOdtTrnOnDly);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFMxMr0);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFMxMr1);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFMxMr2);
+ // These Phy fence registers don't have mutiple memory Pstate copies
+ // But they need to be written again in M1 context
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFDataFence2);
+ MULTI_MPSTATE_COPY_TSEFO (NBRegTable, BFFence2);
+
+ IDS_OPTION_HOOK (IDS_INIT_MEM_REG_TABLE, NBPtr, &NBPtr->MemPtr->StdHeader);
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mns3tn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mns3tn.c
new file mode 100644
index 0000000000..2a48eb55cf
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mns3tn.c
@@ -0,0 +1,1498 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mns3tn.c
+ *
+ * TN memory specific function to support S3 resume
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "S3.h"
+#include "mfs3.h"
+#include "mntn.h"
+#include "cpuRegisters.h"
+#include "cpuFamRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "mnS3tn.h"
+#include "heapManager.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_MEM_NB_TN_MNS3TN_FILECODE
+#define DCT0_MEMPSTATE_MASK 0x10
+#define DCT1_MEMPSTATE_MASK 0x20
+#define DO_NOT_CARE 0
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+UINT16
+STATIC
+MemNS3GetRegLstPtrTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT DESCRIPTOR_GROUP *DescriptPtr
+ );
+
+AGESA_STATUS
+STATIC
+MemNS3GetDeviceRegLstTN (
+ IN UINT32 RegisterLstID,
+ OUT VOID **RegisterHeader
+ );
+
+VOID
+STATIC
+MemNS3SetDfltPhyRegTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN VOID *Value,
+ IN OUT VOID *ConfigPtr
+ );
+
+VOID
+STATIC
+MemNS3SetDynModeChangeTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ );
+
+VOID
+STATIC
+MemNS3SetPhyStatusRegTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ );
+
+VOID
+STATIC
+MemNS3DisableChannelTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ );
+
+VOID
+STATIC
+MemNS3GetConPCIMaskTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT DESCRIPTOR_GROUP *DescriptPtr
+ );
+
+VOID
+STATIC
+MemNS3ChangeMemPStateContextAndFlowNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ );
+
+VOID
+STATIC
+MemNS3GetCSRTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN VOID *Value,
+ IN OUT VOID *ConfigPtr
+ );
+
+VOID
+STATIC
+MemNS3SetCSRTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ );
+
+VOID
+STATIC
+MemNS3SetPhyFenceTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN VOID *Value,
+ IN OUT VOID *ConfigPtr
+ );
+BOOLEAN
+MemS3ResumeConstructNBBlockTN (
+ IN OUT VOID *S3NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ );
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+PCI_SPECIAL_CASE PciSpecialCaseFuncTN[] = {
+ {MemNS3GetCSRTN, MemNS3SetCSRTN},
+ {MemNS3GetBitFieldNb, MemNS3SetBitFieldNb},
+ {MemNS3GetNBPStateDepRegUnb, MemNS3SetNBPStateDepRegUnb},
+ { (VOID (*) (ACCESS_WIDTH, PCI_ADDR, VOID *, VOID *)) memDefRet, MemNS3SetDfltPhyRegTN},
+ {MemNS3ChangeMemPStateContextAndFlowNb, MemNS3ChangeMemPStateContextAndFlowNb},
+ { (VOID (*) (ACCESS_WIDTH, PCI_ADDR, VOID *, VOID *)) memDefRet, MemNS3SetDynModeChangeTN},
+ { (VOID (*) (ACCESS_WIDTH, PCI_ADDR, VOID *, VOID *)) memDefRet, MemNS3DisableChannelTN},
+ {MemNS3SaveNBRegiserUnb, MemNS3RestoreNBRegiserUnb},
+ {MemNS3GetBitFieldNb, MemNS3SetPreDriverCalUnb},
+ { (VOID (*) (ACCESS_WIDTH, PCI_ADDR, VOID *, VOID *)) memDefRet, MemNS3SetPhyStatusRegTN},
+ { (VOID (*) (ACCESS_WIDTH, PCI_ADDR, VOID *, VOID *)) memDefRet, MemNS3SetMemClkFreqValUnb},
+ {MemNS3ChangeMemPStateContextNb, MemNS3ChangeMemPStateContextNb},
+ {MemNS3GetBitFieldNb, MemNS3SetPhyFenceTN},
+ { (VOID (*) (ACCESS_WIDTH, PCI_ADDR, VOID *, VOID *)) memDefRet, MemNS3ReleaseNBPSUnb},
+ { (VOID (*) (ACCESS_WIDTH, PCI_ADDR, VOID *, VOID *)) memDefRet, MemNS3ForceNBP0Unb}
+};
+
+PCI_REG_DESCRIPTOR ROMDATA S3PciPreSelfRefDescriptorTN[] = {
+ {{14,3, 1}, DO_NOT_CARE, 0, 0},
+ {{0, 0, 0}, FUNC_2, 0x110, 0xFFFFF8E7},
+ {{0, 0, 0}, FUNC_1, 0x40, 0xFFFF0703},
+ {{0, 1, 0}, FUNC_1, 0x140, 0x000000FF},
+ {{0, 0, 0}, FUNC_1, 0x44, 0xFFFF0707},
+ {{0, 1, 0}, FUNC_1, 0x144, 0x000000FF},
+ {{0, 0, 0}, FUNC_1, 0xF0, 0xFF00FF87},
+ {{0, 0, 0}, FUNC_1, 0x120, 0x00FFFFFF},
+ {{0, 0, 0}, FUNC_1, 0x124, 0x00FFFFFF},
+ {{0, 0, 0}, FUNC_2, 0x10C, 0x07F3FBF9},
+ {{0, 0, 0}, FUNC_2, 0x114, 0xFFFFFE00},
+ {{0, 0, 0}, FUNC_2, 0x118, 0xFF73FFFF},
+ {{0, 0, 0}, FUNC_2, 0x11C, 0xAFFFFFFF},
+ {{0, 0, 0}, FUNC_2, 0x1B0, 0xFFD3FF3F},
+ {{0, 0, 0}, FUNC_2, 0x1B4, 0xFC7FFFFF},
+ {{0, 0, 0}, FUNC_2, 0xA4, 0x00F07900},
+};
+
+CONST PCI_REGISTER_BLOCK_HEADER ROMDATA S3PciPreSelfRefTN = {
+ 0,
+ (sizeof (S3PciPreSelfRefDescriptorTN) / sizeof (PCI_REG_DESCRIPTOR)),
+ S3PciPreSelfRefDescriptorTN,
+ PciSpecialCaseFuncTN
+};
+
+CONDITIONAL_PCI_REG_DESCRIPTOR ROMDATA S3CPciPreSelfDescriptorTN[] = {
+ // DCT 0
+ {{7, 0, 1}, DCT0, 0x40, 0x7FF8FFED, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x44, 0x7FF8FFED, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x48, 0x7FF8FFED, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x4C, 0x7FF8FFED, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x50, 0x7FF8FFED, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x54, 0x7FF8FFED, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x58, 0x7FF8FFED, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x5C, 0x7FF8FFED, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x60, 0x7FF8FFE0, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x64, 0x7FF8FFE0, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x68, 0x7FF8FFE0, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x6C, 0x7FF8FFE0, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x78, 0x00020000, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x80, 0x0000FFFF, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x84, 0x00800003, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x88, 0x3F000000, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x8C, 0x00070000, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x90, 0x0BF70000, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0xA8, 0xBC730024, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x200, 0x3F1F1F1F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x204, 0x0F3F0F3F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x208, 0x07070707, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x20C, 0x00030F1F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{2, 0, 1}, DCT0, SET_S3_NB_PSTATE_OFFSET (0x210, 0), 0xFFC7000F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{2, 0, 1}, DCT0, SET_S3_NB_PSTATE_OFFSET (0x210, 1), 0xFFC7000F, DCT0_NBPSTATE_SUPPORT_MASK, DCT0_ANY_DIMM_MASK},
+ {{2, 0, 1}, DCT0, SET_S3_NB_PSTATE_OFFSET (0x210, 2), 0xFFC7000F, DCT0_NBPSTATE_SUPPORT_MASK, DCT0_ANY_DIMM_MASK},
+ {{2, 0, 1}, DCT0, SET_S3_NB_PSTATE_OFFSET (0x210, 3), 0xFFC7000F, DCT0_NBPSTATE_SUPPORT_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x214, 0x000F0F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x218, 0x0F0F0F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x21C, 0x001F1F00, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x220, 0x00001F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x224, 0x0000070F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x228, 0xFFFFFFFF, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT0, 0x22C, 0x0000001F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x230, 0x0F0F0F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x234, 0x0F0F0F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x238, 0x0F0F0F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x23C, 0x0F0F0F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x240, 0x000077FF, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT0, 0x244, 0x0000000F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x248, 0xBF3F1F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x24C, 0x3F3F3F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x2E0, 0x5F700000, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x2E8, 0xFFFFFFFF, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x2EC, 0x0000FFFF, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT0, 0x2F0, 0x00000001, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x400, 0x00000F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x404, 0x0000FFFF, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT0, 0x408, 0x00000003, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x420, 0x00000F0F, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+
+ // DCT 1
+ {{7, 0, 1}, DCT1, 0x40, 0x7FF8FFED, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x44, 0x7FF8FFED, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x48, 0x7FF8FFED, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x4C, 0x7FF8FFED, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x50, 0x7FF8FFED, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x54, 0x7FF8FFED, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x58, 0x7FF8FFED, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x5C, 0x7FF8FFED, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x60, 0x7FF8FFE0, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x64, 0x7FF8FFE0, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x68, 0x7FF8FFE0, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x6C, 0x7FF8FFE0, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x78, 0x00020000, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x80, 0x0000FFFF, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x84, 0x00800003, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x88, 0x3F000000, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x8C, 0x00070000, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x90, 0x0BF70000, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0xA8, 0xBC730024, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x200, 0x3F1F1F1F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x204, 0x0F3F0F3F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x208, 0x07070707, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x20C, 0x00030F1F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{2, 0, 1}, DCT1, SET_S3_NB_PSTATE_OFFSET (0x210, 0), 0xFFC7000F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{2, 0, 1}, DCT1, SET_S3_NB_PSTATE_OFFSET (0x210, 1), 0xFFC7000F, DCT1_NBPSTATE_SUPPORT_MASK, DCT1_ANY_DIMM_MASK},
+ {{2, 0, 1}, DCT1, SET_S3_NB_PSTATE_OFFSET (0x210, 2), 0xFFC7000F, DCT1_NBPSTATE_SUPPORT_MASK, DCT1_ANY_DIMM_MASK},
+ {{2, 0, 1}, DCT1, SET_S3_NB_PSTATE_OFFSET (0x210, 3), 0xFFC7000F, DCT1_NBPSTATE_SUPPORT_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x214, 0x000F0F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x218, 0x0F0F0F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x21C, 0x001F1F00, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x220, 0x00001F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x224, 0x0000070F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x228, 0xFFFFFFFF, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT1, 0x22C, 0x0000001F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x230, 0x0F0F0F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x234, 0x0F0F0F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x238, 0x0F0F0F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x23C, 0x0F0F0F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x240, 0x000077FF, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT1, 0x244, 0x0000000F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x248, 0xBF3F1F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x24C, 0x3F3F3F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x2E0, 0x5F700000, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x2E8, 0xFFFFFFFF, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x2EC, 0x0000FFFF, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT1, 0x2F0, 0x00000001, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x400, 0x00000F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x404, 0x0000FFFF, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT1, 0x408, 0x00000003, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x420, 0x00000F0F, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+
+ // Phy Initialization
+ // 1. Program D18F2x9C_x0D0F_E013_dct[1:0] = 0118h.
+ {{1, 2, 1}, DCT0, BFPllRegWaitTime, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFPllRegWaitTime, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ // 2. Force the phy to M0 with the following sequence:
+ // A. Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 190h.
+ {{3, 3, 1}, DCT0, BFPllLockTime, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{3, 3, 1}, DCT1, BFPllLockTime, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ // B. For each DCT: Program D18F2x9C_x0000_000B_dct[1:0] = 80800000h.
+ {{9, 3, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x0B), 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{9, 3, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x0B), 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ // C. Program D18F2x9C_x0D0F_E018_dct[0][PhyPSMasterChannel] = 0.
+ {{3, 3, 1}, DCT0, BFPhyPSMasterChannel, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ // D. Program D18F2x9C_x0000_000B_dct[0] = 40000000h.
+ // E. For each DCT: Program D18F2x9C_x0000_000B_dct[1:0] = 80000000h
+ {{5, 3, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x0B), 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{5, 3, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x0B), 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+
+ // 3. Phy voltage related
+ {{1, 1, 1}, DCT0, BFDataRxVioLvl, 0x00000018, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFClkRxVioLvl, 0x00000018, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFCmpVioLvl, 0x0000C000, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFCmdRxVioLvl, 0x00000018, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFCsrComparator, 0x0000000C, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFAddrRxVioLvl, 0x00000018, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFDataRxVioLvl, 0x00000018, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFClkRxVioLvl, 0x00000018, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFCmpVioLvl, 0x0000C000, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFCmdRxVioLvl, 0x00000018, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFAddrRxVioLvl, 0x00000018, DCT1_MASK, ANY_DIMM_MASK},
+
+ // 4. Frequency Change
+ // Check if a channel needs to be disabled
+ {{1, 1, 1}, DCT0, BFCKETri, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{6, 3, 1}, DCT0, 0, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFCKETri, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{6, 3, 1}, DCT1, 0, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFPhyClkConfig0, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFPhyClkConfig1, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFPhyClkConfig0, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFPhyClkConfig1, 0, DCT1_MASK, ANY_DIMM_MASK},
+
+ {{7, 0, 1}, DCT0, 0x94, 0x9FF9CC1F, DCT0_MASK, ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x94, 0x9FF9CC1F, DCT1_MASK, ANY_DIMM_MASK},
+
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x04), 0x003F3F3F, DCT0_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x04), 0x003F3F3F, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFProcOdtAdv, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFProcOdtAdv, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFSkewMemClk, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFSkewMemClk, 0, DCT1_MASK, ANY_DIMM_MASK},
+
+ // Enable MemClk
+ {{10, 0, 1}, DCT0, 0x94, 0, DCT0_MASK, DCT0_ANY_DIMM_MASK},
+ {{10, 0, 1}, DCT1, 0x94, 0, DCT1_MASK, DCT1_ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFPllLockTime, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFPllLockTime, 0, DCT1_MASK, ANY_DIMM_MASK},
+
+ // DCT 0
+ // 5. Phy Fence
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x0C), 0x7FFF3FFF, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataFence2, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFFence2, 0x00007C1F, DCT0_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x04), 0x003F3F3F, DCT0_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x00), 0x70777777, DCT0_MASK, ANY_DIMM_MASK},
+ // 6. Phy Compensation Init
+ {{3, 3, 1}, DCT0, BFDisablePredriverCal, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteTxPreDriverCal2Pad1, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteTxPreDriverCal2Pad2, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT0, BFDataByteTxPreDriverCal, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFCmdAddr0TxPreDriverCal2Pad1, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFCmdAddr0TxPreDriverCal2Pad2, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFCmdAddr1TxPreDriverCal2Pad1, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFCmdAddr1TxPreDriverCal2Pad2, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFAddrTxPreDriverCal2Pad1, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFAddrTxPreDriverCal2Pad2, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFAddrTxPreDriverCal2Pad3, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFAddrTxPreDriverCal2Pad4, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT0, BFCmdAddr0TxPreDriverCalPad0, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT0, BFCmdAddr1TxPreDriverCalPad0, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT0, BFAddrTxPreDriverCalPad0, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT0, BFClock0TxPreDriverCalPad0, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT0, BFClock1TxPreDriverCalPad0, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT0, BFClock2TxPreDriverCalPad0, 0, DCT0_MASK, ANY_DIMM_MASK},
+
+ // DCT 1
+ // 5. Phy Fence
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x0C), 0x7FFF0FFF, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataFence2, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFFence2, 0x00007C1F, DCT1_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x04), 0x003F3F3F, DCT1_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x00), 0x70777777, DCT1_MASK, ANY_DIMM_MASK},
+ // 6. Phy Compensation Init
+ {{1, 2, 1}, DCT1, BFDataByteTxPreDriverCal2Pad1, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteTxPreDriverCal2Pad2, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT1, BFDataByteTxPreDriverCal, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFCmdAddr0TxPreDriverCal2Pad1, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFCmdAddr0TxPreDriverCal2Pad2, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFCmdAddr1TxPreDriverCal2Pad1, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFCmdAddr1TxPreDriverCal2Pad2, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFAddrTxPreDriverCal2Pad1, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFAddrTxPreDriverCal2Pad2, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFAddrTxPreDriverCal2Pad3, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFAddrTxPreDriverCal2Pad4, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT1, BFCmdAddr0TxPreDriverCalPad0, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT1, BFCmdAddr1TxPreDriverCalPad0, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT1, BFAddrTxPreDriverCalPad0, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT1, BFClock0TxPreDriverCalPad0, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT1, BFClock1TxPreDriverCalPad0, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{8, 2, 1}, DCT1, BFClock2TxPreDriverCalPad0, 0, DCT0_MASK, ANY_DIMM_MASK},
+
+ {{1, 1, 1}, DCT0, BFDisablePredriverCal, 0, DCT0_MASK + DCT1_MASK, ANY_DIMM_MASK},
+
+ // Program MemPstate 1 registers
+ // Switch to MemPstate context 1
+ {{11, 3, 1}, DO_NOT_CARE, 1, DO_NOT_CARE, DCT0_MEMPSTATE_MASK + DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFRate, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFRate, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFProcOdtAdv, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFProcOdtAdv, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFDataRxVioLvl, 0x00000018, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFDataRxVioLvl, 0x00000018, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x200, 0x3F1F1F1F, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x204, 0x0F3F0F3F, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x208, 0x07070707, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x20C, 0x00030F1F, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x214, 0x000F0F0F, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x218, 0x0F0F0F0F, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x21C, 0x001F1F00, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT0, 0x22C, 0x0000001F, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x240, 0x000077FF, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x248, 0xBF3F1F0F, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT0, 0x2E8, 0xFFFFFFFF, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT0, 0x2EC, 0x0000FFFF, DCT0_MEMPSTATE_MASK, DCT0_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x200, 0x3F1F1F1F, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x204, 0x0F3F0F3F, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x208, 0x07070707, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x20C, 0x00030F1F, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x214, 0x000F0F0F, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x218, 0x0F0F0F0F, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x21C, 0x001F1F00, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 1, 1}, DCT1, 0x22C, 0x0000001F, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x240, 0x000077FF, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x248, 0xBF3F1F0F, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 0, 1}, DCT1, 0x2E8, 0xFFFFFFFF, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ {{7, 2, 1}, DCT1, 0x2EC, 0x0000FFFF, DCT1_MEMPSTATE_MASK, DCT1_ANY_DIMM_MASK},
+ // Compute Phy fence for MemPstate 1
+ // DCT 0
+ {{12, 2, 1}, DCT1, BFChAM1FenceSave, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x04), 0x003F3F3F, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x00), 0x70777777, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ // DCT 1
+ {{12, 2, 1}, DCT1, BFChBM1FenceSave, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x04), 0x003F3F3F, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x00), 0x70777777, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+
+ {{1, 1, 1}, DCT0, BFDisablePredriverCal, 0, DCT0_MEMPSTATE_MASK + DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ // Switch back to MemPstate context 0
+ {{11, 3, 1}, DO_NOT_CARE, 0, DO_NOT_CARE, DCT0_MEMPSTATE_MASK + DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+
+ // Set Fence back to Fence of M0 to prepare for fine delay restore for M0
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x0C), 0x7FFF3FFF, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataFence2, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFFence2, 0x00007C1F, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x0C), 0x7FFF0FFF, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataFence2, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFFence2, 0x00007C1F, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK}
+};
+
+CONST CPCI_REGISTER_BLOCK_HEADER ROMDATA S3CPciPreSelfRefTN = {
+ 0,
+ (sizeof (S3CPciPreSelfDescriptorTN) / sizeof (CONDITIONAL_PCI_REG_DESCRIPTOR)),
+ S3CPciPreSelfDescriptorTN,
+ PciSpecialCaseFuncTN
+};
+
+CONDITIONAL_PCI_REG_DESCRIPTOR ROMDATA S3CPciPostSelfDescriptorTN[] = {
+ // DCT0
+ {{12, 2, 1}, DCT1, BFChAM1FenceSave, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFRx4thStgEn, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFRxBypass3rd4thStg, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x10), 0x03FF03FF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x11), 0x03FF03FF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x13), 0x03FF03FF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x14), 0x03FF03FF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x16), 0x03FF03FF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x17), 0x03FF03FF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x19), 0x03FF03FF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x1A), 0x03FF03FF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x20), 0x03FF03FF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x21), 0x03FF03FF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x23), 0x03FF03FF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x24), 0x03FF03FF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x26), 0x03FF03FF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x27), 0x03FF03FF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x29), 0x03FF03FF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x2A), 0x03FF03FF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x01), 0xFFFFFFFF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x02), 0xFFFFFFFF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x101), 0xFFFFFFFF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x102), 0xFFFFFFFF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x201), 0xFFFFFFFF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x202), 0xFFFFFFFF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x301), 0xFFFFFFFF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x302), 0xFFFFFFFF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x05), 0x3E3E3E3E, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x06), 0x3E3E3E3E, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x105), 0x3E3E3E3E, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x106), 0x3E3E3E3E, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x205), 0x3E3E3E3E, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x206), 0x3E3E3E3E, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x305), 0x3E3E3E3E, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x306), 0x3E3E3E3E, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x30), 0x00FF00FF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x31), 0x00FF00FF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x33), 0x00FF00FF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x34), 0x00FF00FF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x36), 0x00FF00FF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x37), 0x00FF00FF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x39), 0x00FF00FF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x3A), 0x00FF00FF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x40), 0x00FF00FF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x41), 0x00FF00FF, DCT0_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x43), 0x00FF00FF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x44), 0x00FF00FF, DCT0_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x46), 0x00FF00FF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x47), 0x00FF00FF, DCT0_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x49), 0x00FF00FF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x4A), 0x00FF00FF, DCT0_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x0D), 0x037F037F, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFPhy0x0D0F0F13, 0x00000083, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFRxSsbMntClkEn, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFLowPowerDrvStrengthEn, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFEnRxPadStandby, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte0, 0xBFBF, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte1, 0xBFBF, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte2, 0xBFBF, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte3, 0xBFBF, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte4, 0xBFBF, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte5, 0xBFBF, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte6, 0xBFBF, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte7, 0xBFBF, DCT0_MASK, ANY_DIMM_MASK},
+
+ // DCT1
+ {{12, 2, 1}, DCT1, BFChBM1FenceSave, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFRx4thStgEn, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFRxBypass3rd4thStg, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x10), 0x03FF03FF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x11), 0x03FF03FF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x13), 0x03FF03FF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x14), 0x03FF03FF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x16), 0x03FF03FF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x17), 0x03FF03FF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x19), 0x03FF03FF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x1A), 0x03FF03FF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x20), 0x03FF03FF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x21), 0x03FF03FF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x23), 0x03FF03FF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x24), 0x03FF03FF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x26), 0x03FF03FF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x27), 0x03FF03FF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x29), 0x03FF03FF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x2A), 0x03FF03FF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x01), 0xFFFFFFFF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x02), 0xFFFFFFFF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x101), 0xFFFFFFFF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x102), 0xFFFFFFFF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x201), 0xFFFFFFFF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x202), 0xFFFFFFFF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x301), 0xFFFFFFFF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x302), 0xFFFFFFFF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x05), 0x3E3E3E3E, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x06), 0x3E3E3E3E, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x105), 0x3E3E3E3E, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x106), 0x3E3E3E3E, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x205), 0x3E3E3E3E, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x206), 0x3E3E3E3E, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x305), 0x3E3E3E3E, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x306), 0x3E3E3E3E, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x30), 0x00FF00FF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x31), 0x00FF00FF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x33), 0x00FF00FF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x34), 0x00FF00FF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x36), 0x00FF00FF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x37), 0x00FF00FF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x39), 0x00FF00FF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x3A), 0x00FF00FF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x40), 0x00FF00FF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x41), 0x00FF00FF, DCT1_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x43), 0x00FF00FF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x44), 0x00FF00FF, DCT1_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x46), 0x00FF00FF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x47), 0x00FF00FF, DCT1_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x49), 0x00FF00FF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x4A), 0x00FF00FF, DCT1_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x0D), 0x037F037F, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFPhy0x0D0F0F13, 0x00000083, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFRxSsbMntClkEn, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFLowPowerDrvStrengthEn, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFEnRxPadStandby, 0, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte0, 0xBFBF, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte1, 0xBFBF, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte2, 0xBFBF, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte3, 0xBFBF, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte4, 0xBFBF, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte5, 0xBFBF, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte6, 0xBFBF, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte7, 0xBFBF, DCT1_MASK, ANY_DIMM_MASK},
+
+ {{11, 3, 1}, DO_NOT_CARE, 1, DO_NOT_CARE, DCT0_MEMPSTATE_MASK + DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+
+ // DCT0
+ {{12, 2, 1}, DCT1, BFChAM1FenceSave, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFRx4thStgEn, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFRxBypass3rd4thStg, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x10), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x11), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x13), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x14), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x16), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x17), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x19), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x1A), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x20), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x21), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x23), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x24), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x26), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x27), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x29), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x2A), 0x03FF03FF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x01), 0xFFFFFFFF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x02), 0xFFFFFFFF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x101), 0xFFFFFFFF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x102), 0xFFFFFFFF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x201), 0xFFFFFFFF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x202), 0xFFFFFFFF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x301), 0xFFFFFFFF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x302), 0xFFFFFFFF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x05), 0x3E3E3E3E, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x06), 0x3E3E3E3E, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x105), 0x3E3E3E3E, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x106), 0x3E3E3E3E, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x205), 0x3E3E3E3E, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x206), 0x3E3E3E3E, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x305), 0x3E3E3E3E, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x306), 0x3E3E3E3E, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x30), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x31), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x33), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x34), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x36), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x37), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x39), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x3A), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x40), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x41), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x01},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x43), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x44), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x04},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x46), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x47), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x10},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x49), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x4A), 0x00FF00FF, DCT0_MEMPSTATE_MASK, 0x40},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 0, 0x0D), 0x037F037F, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFPhy0x0D0F0F13, 0x00000083, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFRxSsbMntClkEn, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFLowPowerDrvStrengthEn, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFEnRxPadStandby, 0, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte0, 0xBFBF, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte1, 0xBFBF, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte2, 0xBFBF, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte3, 0xBFBF, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte4, 0xBFBF, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte5, 0xBFBF, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte6, 0xBFBF, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT0, BFDataByteDllPowerMgnByte7, 0xBFBF, DCT0_MEMPSTATE_MASK, ANY_DIMM_MASK},
+
+ // DCT1
+ {{12, 2, 1}, DCT1, BFChBM1FenceSave, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFRx4thStgEn, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFRxBypass3rd4thStg, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x10), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x11), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x13), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x14), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x16), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x17), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x19), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x1A), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x20), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x21), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x23), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x24), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x26), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x27), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x29), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x2A), 0x03FF03FF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x01), 0xFFFFFFFF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x02), 0xFFFFFFFF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x101), 0xFFFFFFFF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x102), 0xFFFFFFFF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x201), 0xFFFFFFFF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x202), 0xFFFFFFFF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x301), 0xFFFFFFFF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x302), 0xFFFFFFFF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x05), 0x3E3E3E3E, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x06), 0x3E3E3E3E, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x105), 0x3E3E3E3E, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x106), 0x3E3E3E3E, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x205), 0x3E3E3E3E, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x206), 0x3E3E3E3E, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x305), 0x3E3E3E3E, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x306), 0x3E3E3E3E, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x30), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x31), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x33), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x34), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x36), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x37), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x39), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x3A), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x40), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x41), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x02},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x43), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x44), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x08},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x46), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x47), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x20},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x49), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x4A), 0x00FF00FF, DCT1_MEMPSTATE_MASK, 0x80},
+ {{0, 0, 1}, FUNC_2, SET_S3_SPECIAL_OFFSET (DCT_PHY_FLAG, 1, 0x0D), 0x037F037F, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFPhy0x0D0F0F13, 0x00000083, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFRxSsbMntClkEn, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFLowPowerDrvStrengthEn, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFEnRxPadStandby, 0, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte0, 0xBFBF, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte1, 0xBFBF, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte2, 0xBFBF, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte3, 0xBFBF, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte4, 0xBFBF, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte5, 0xBFBF, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte6, 0xBFBF, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+ {{1, 2, 1}, DCT1, BFDataByteDllPowerMgnByte7, 0xBFBF, DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+
+ {{11, 3, 1}, DO_NOT_CARE, 0, DO_NOT_CARE, DCT0_MEMPSTATE_MASK + DCT1_MEMPSTATE_MASK, ANY_DIMM_MASK},
+
+ {{1, 1, 1}, DCT0, BFAddrCmdTri, 0x0000000A1, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT0, BFDisDllShutdownSR, 0, DCT0_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFAddrCmdTri, 0x0000000A1, DCT1_MASK, ANY_DIMM_MASK},
+ {{1, 1, 1}, DCT1, BFDisDllShutdownSR, 0, DCT1_MASK, ANY_DIMM_MASK},
+
+ {{0, 0, 0}, FUNC_2, 0x118, 0x00040000, ANY_DIMM_MASK, ANY_DIMM_MASK},
+ {{0, 0, 0}, FUNC_2, 0x118, 0x00080000, ANY_DIMM_MASK, ANY_DIMM_MASK},
+
+ {{13, 3, 1}, DO_NOT_CARE, 0, DO_NOT_CARE, ANY_DIMM_MASK, ANY_DIMM_MASK}
+};
+
+CONST CPCI_REGISTER_BLOCK_HEADER ROMDATA S3CPciPostSelfRefTN = {
+ 0,
+ (sizeof (S3CPciPostSelfDescriptorTN) / sizeof (CONDITIONAL_PCI_REG_DESCRIPTOR)),
+ S3CPciPostSelfDescriptorTN,
+ PciSpecialCaseFuncTN
+};
+
+MSR_REG_DESCRIPTOR ROMDATA S3MSRPreSelfRefDescriptorTN[] = {
+ {{0, 0, 0}, 0xC0010010, 0x00000000007F0000},
+ {{0, 0, 0}, 0xC001001A, 0x0000FFFFFF800000},
+ {{0, 0, 0}, 0xC001001D, 0x0000FFFFFF800000},
+ {{0, 0, 0}, 0xC001001F, 0x0044601080000600}
+};
+
+CONST MSR_REGISTER_BLOCK_HEADER ROMDATA S3MSRPreSelfRefTN = {
+ 0,
+ (sizeof (S3MSRPreSelfRefDescriptorTN) / sizeof (MSR_REG_DESCRIPTOR)),
+ S3MSRPreSelfRefDescriptorTN,
+ NULL
+};
+
+VOID *MemS3RegListTN[] = {
+ (VOID *)&S3PciPreSelfRefTN,
+ NULL,
+ (VOID *)&S3CPciPreSelfRefTN,
+ (VOID *)&S3CPciPostSelfRefTN,
+ (VOID *)&S3MSRPreSelfRefTN,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the northbridge block for S3 resume
+ *
+ * @param[in,out] *S3NBPtr - Pointer to MEM_NB_BLOCK.
+ * @param[in,out] *MemPtr - Pointer to MEM_DATA_STRUCT.
+ * @param[in] NodeID - Node ID of the target node.
+ *
+ * @return BOOLEAN
+ * TRUE - This is the correct constructor for the targeted node.
+ * FALSE - This isn't the correct constructor for the targeted node.
+ */
+BOOLEAN
+MemS3ResumeConstructNBBlockTN (
+ IN OUT VOID *S3NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ )
+{
+ INT32 i;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = ((S3_MEM_NB_BLOCK *)S3NBPtr)->NBPtr;
+
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemNIsIdSupportedTN (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
+ return FALSE;
+ }
+
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->MCTPtr = &(MemPtr->DiesPerSystem[NodeID]);
+ NBPtr->PciAddr.AddressValue = MemPtr->DiesPerSystem[NodeID].PciAddr.AddressValue;
+ MemNInitNBRegTableTN (NBPtr, NBPtr->NBRegTable);
+ NBPtr->Node = ((UINT8) NBPtr->PciAddr.Address.Device) - 24;
+ NBPtr->Dct = 0;
+ NBPtr->Channel = 0;
+ NBPtr->Ganged = FALSE;
+ NBPtr->NodeCount = MAX_NODES_SUPPORTED_TN;
+ NBPtr->DctCount = MAX_DCTS_PER_NODE_TN;
+ NBPtr->MemPstate = MEMORY_PSTATE0;
+ NBPtr->MemPstateStage = 0;
+ NBPtr->NbPsCtlReg = 0;
+
+ NBPtr->IsSupported[SetDllShutDown] = TRUE;
+
+ for (i = 0; i < EnumSize; i++) {
+ NBPtr->IsSupported[i] = FALSE;
+ }
+
+ for (i = 0; i < NumberOfHooks; i++) {
+ NBPtr->FamilySpecificHook[i] = (BOOLEAN (*) (MEM_NB_BLOCK *, VOID *)) memDefTrue;
+ }
+
+ LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &MemPtr->StdHeader);
+
+ NBPtr->SwitchDCT = MemNSwitchDCTNb;
+ NBPtr->SwitchChannel = MemNSwitchChannelNb;
+ NBPtr->MemNCmnGetSetFieldNb = MemNCmnGetSetFieldTN;
+ NBPtr->GetBitField = MemNGetBitFieldNb;
+ NBPtr->SetBitField = MemNSetBitFieldNb;
+ NBPtr->MemNIsIdSupportedNb = MemNIsIdSupportedTN;
+ ((S3_MEM_NB_BLOCK *)S3NBPtr)->MemS3ExitSelfRefReg = (VOID (*) (MEM_NB_BLOCK *, AMD_CONFIG_PARAMS *)) memDefRet;
+ ((S3_MEM_NB_BLOCK *)S3NBPtr)->MemS3GetConPCIMask = MemNS3GetConPCIMaskTN;
+ ((S3_MEM_NB_BLOCK *)S3NBPtr)->MemS3GetConMSRMask = (VOID (*) (MEM_NB_BLOCK *, DESCRIPTOR_GROUP *)) memDefRet;
+ ((S3_MEM_NB_BLOCK *)S3NBPtr)->MemS3Resume = MemNS3ResumeUNb;
+ ((S3_MEM_NB_BLOCK *)S3NBPtr)->MemS3RestoreScrub = (VOID (*) (MEM_NB_BLOCK *, UINT8)) memDefRet;
+ ((S3_MEM_NB_BLOCK *)S3NBPtr)->MemS3GetRegLstPtr = MemNS3GetRegLstPtrTN;
+ ((S3_MEM_NB_BLOCK *)S3NBPtr)->MemS3GetDeviceRegLst = MemNS3GetDeviceRegLstTN;
+ ((S3_MEM_NB_BLOCK *)S3NBPtr)->MemS3SpecialCaseHeapSize = 0;
+ NBPtr->FamilySpecificHook[DCTSelectSwitch] = MemNS3DctCfgSelectUnb;
+
+ MemNSetBitFieldNb (NBPtr, BFDctCfgSel, 0);
+ MemNSwitchDCTNb (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BFMemPsSel, 0);
+
+ if (MemNGetBitFieldNb (NBPtr, BFMemPstateDis) != 1) {
+ NBPtr->MemPstateStage = MEMORY_PSTATE_S3_STAGE;
+ MemNBrdcstSetUnConditionalNb (NBPtr, BFPStateToAccess, 0);
+ }
+
+ return TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------*/
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns the register list for each device for TN
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in, out] *DescriptPtr - Pointer to DESCRIPTOR_GROUP
+ * @return UINT16 - size of the device descriptor on the target node.
+ */
+UINT16
+STATIC
+MemNS3GetRegLstPtrTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT DESCRIPTOR_GROUP *DescriptPtr
+ )
+{
+ UINT8 i;
+ UINT16 Size;
+ Size = 0;
+ for (i = PRESELFREF; i <= POSTSELFREF; i ++) {
+ DescriptPtr->PCIDevice[i].Type = (UINT8) (DEV_TYPE_PCI_PRE_ESR + i);
+ DescriptPtr->PCIDevice[i].Node = NBPtr->Node;
+ DescriptPtr->PCIDevice[i].RegisterListID = 0xFFFFFFFF;
+ if ((PCI_REGISTER_BLOCK_HEADER *) MemS3RegListTN[PCI_LST_ESR_TN - PCI_LST_ESR_TN + i] != NULL) {
+ DescriptPtr->PCIDevice[i].RegisterListID = PCI_LST_ESR_TN + i;
+ Size += sizeof (PCI_DEVICE_DESCRIPTOR);
+ }
+ DescriptPtr->CPCIDevice[i].Type = (UINT8) (DEV_TYPE_CPCI_PRE_ESR + i);
+ DescriptPtr->CPCIDevice[i].Node = NBPtr->Node;
+ DescriptPtr->CPCIDevice[i].RegisterListID = 0xFFFFFFFF;
+ if ((CPCI_REGISTER_BLOCK_HEADER *) MemS3RegListTN[CPCI_LST_ESR_TN - PCI_LST_ESR_TN + i] != NULL) {
+ DescriptPtr->CPCIDevice[i].RegisterListID = CPCI_LST_ESR_TN + i;
+ Size += sizeof (CONDITIONAL_PCI_DEVICE_DESCRIPTOR);
+ }
+ DescriptPtr->MSRDevice[i].Type = (UINT8) (DEV_TYPE_MSR_PRE_ESR + i);
+ DescriptPtr->MSRDevice[i].RegisterListID = 0xFFFFFFFF;
+ if ((MSR_REGISTER_BLOCK_HEADER *) MemS3RegListTN[MSR_LST_ESR_TN - PCI_LST_ESR_TN + i] != NULL) {
+ DescriptPtr->MSRDevice[i].RegisterListID = MSR_LST_ESR_TN + i;
+ Size += sizeof (MSR_DEVICE_DESCRIPTOR);
+ }
+ DescriptPtr->CMSRDevice[i].Type = (UINT8) (DEV_TYPE_CMSR_PRE_ESR + i);
+ DescriptPtr->CMSRDevice[i].RegisterListID = 0xFFFFFFFF;
+ if ((CMSR_REGISTER_BLOCK_HEADER *) MemS3RegListTN[CMSR_LST_ESR_TN - PCI_LST_ESR_TN + i] != NULL) {
+ DescriptPtr->CMSRDevice[i].RegisterListID = CMSR_LST_ESR_TN + i;
+ Size += sizeof (CONDITIONAL_MSR_DEVICE_DESCRIPTOR);
+ }
+ }
+ return Size;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function return the register list according to the register ID.
+ *
+ * @param[in] RegisterLstID - value of the Register list ID.
+ * @param[out] **RegisterHeader - pointer to the address of the register list.
+ * @return AGESA_STATUS
+ * - AGESA_FATAL
+ * - AGESA_SUCCESS
+ */
+AGESA_STATUS
+STATIC
+MemNS3GetDeviceRegLstTN (
+ IN UINT32 RegisterLstID,
+ OUT VOID **RegisterHeader
+ )
+{
+ if (RegisterLstID >= (sizeof (MemS3RegListTN) / sizeof (VOID *))) {
+ ASSERT(FALSE); // RegisterListID exceeded size of Register list
+ return AGESA_FATAL;
+ }
+ if (MemS3RegListTN[RegisterLstID] != NULL) {
+ *RegisterHeader = MemS3RegListTN[RegisterLstID];
+ return AGESA_SUCCESS;
+ }
+ ASSERT(FALSE); // Device register list error
+ return AGESA_FATAL;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function that set PllLockTime or PhyPSMasterChannel or disable auto compensation.
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+STATIC
+MemNS3SetDfltPhyRegTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT16 RegValue;
+ BIT_FIELD_NAME BitField;
+
+ IDS_SKIP_HOOK (IDS_BEFORE_S3_SPECIAL, &Address, ConfigPtr) {
+ BitField = (BIT_FIELD_NAME) Address.Address.Register;
+ RegValue = 0;
+
+ if (BitField == BFPllLockTime) {
+ RegValue = 0x190;
+ } else if (BitField == BFPhyPSMasterChannel) {
+ } else if (BitField == BFDisablePredriverCal) {
+ RegValue = 3;
+ } else {
+ ASSERT (FALSE);
+ }
+ MemNS3SetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets bit 31 [DynModeChange] of F2x9C_xB
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+STATIC
+MemNS3SetDynModeChangeTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT32 RegValue;
+
+ IDS_SKIP_HOOK (IDS_BEFORE_S3_SPECIAL, &Address, ConfigPtr) {
+ if ((Address.Address.Register & 0x400) == 0) {
+ RegValue = 0x40000000;
+ MemNS3SetCSRTN (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
+ }
+ RegValue = 0x80000000;
+ MemNS3SetCSRTN (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets F2x9C_xB to 0x80800000
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+STATIC
+MemNS3SetPhyStatusRegTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT32 RegValue;
+
+ IDS_SKIP_HOOK (IDS_BEFORE_S3_SPECIAL, &Address, ConfigPtr) {
+ RegValue = 0x80800000;
+ MemNS3SetCSRTN (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function does the channel disable sequence
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+STATIC
+MemNS3DisableChannelTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ LOCATE_HEAP_PTR LocateBufferPtr;
+ S3_MEM_NB_BLOCK *S3NBPtr;
+ UINT32 RegValue;
+ UINT8 Die;
+
+ // See which Node should be accessed
+ Die = (UINT8) (Address.Address.Device - 24);
+
+ LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
+ if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
+ S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
+ NBPtr = S3NBPtr[Die].NBPtr;
+
+ // Function field contains the DCT number
+ NBPtr->SwitchDCT (NBPtr, (UINT8) Address.Address.Function);
+ RegValue = MemNGetBitFieldNb (NBPtr, BFCKETri);
+ // if CKETri is 0b1111, this channel is disabled
+ if (RegValue == 0xF) {
+ //Wait for 24 MEMCLKs, which is 60ns under 400MHz
+ MemFS3Wait10ns (6, NBPtr->MemPtr);
+ MemNSetBitFieldNb (NBPtr, BFMemClkDis, 0xFF);
+ MemNSetBitFieldNb (NBPtr, BFDisDramInterface, 1);
+ if (NBPtr->Dct == 0) {
+ MemNSetBitFieldNb (NBPtr, BFPhyPSMasterChannel, 0x100);
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function changes memory Pstate context
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+VOID
+STATIC
+MemNS3ChangeMemPStateContextAndFlowNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ LOCATE_HEAP_PTR LocateBufferPtr;
+ S3_MEM_NB_BLOCK *S3NBPtr;
+ UINT8 Die;
+
+ // See which Node should be accessed
+ Die = (UINT8) (Address.Address.Device - 24);
+
+ LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
+
+ if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
+ S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
+ NBPtr = S3NBPtr[Die].NBPtr;
+ if (NBPtr->MemPstate == MEMORY_PSTATE0) {
+ // If MemoryPstate is not disabled, switch to MemPState 1 context, and reprocess the register list
+ MemNChangeMemPStateContextNb (NBPtr, 1);
+ *(UINT32 *) Value = RESTART_FROM_BEGINNING_LIST;
+ } else {
+ // Switch back to MemPstate0 Context
+ MemNChangeMemPStateContextNb (NBPtr, 0);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns the conditional PCI device mask
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in, out] *DescriptPtr - Pointer to DESCRIPTOR_GROUP
+ * @return none
+ */
+VOID
+STATIC
+MemNS3GetConPCIMaskTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT DESCRIPTOR_GROUP *DescriptPtr
+ )
+{
+ BIT_FIELD_NAME bitfield;
+ UINT32 RegVal;
+ UINT8 DCT;
+ UINT8 DimmMask;
+ UINT8 BadDimmMask;
+ UINT8 NbPsCapMsk;
+ UINT8 MemPstateMsk;
+ UINT8 CsPerDelay;
+
+ NbPsCapMsk = 0;
+ MemPstateMsk = 0;
+ DimmMask = 0;
+ BadDimmMask = 0;
+ CsPerDelay = 1;
+
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ MemNSwitchDCTNb (NBPtr, DCT);
+ if (MemNGetBitFieldNb (NBPtr, BFMemClkFreqVal)) {
+ if (MemNGetBitFieldNb (NBPtr, BFPerRankTimingEn) == 0) {
+ CsPerDelay = 2;
+ }
+ for (bitfield = BFCSBaseAddr0Reg; bitfield <= BFCSBaseAddr7Reg; bitfield ++) {
+ RegVal = MemNGetBitFieldNb (NBPtr, bitfield);
+ if (RegVal & 0x1) {
+ DimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) / CsPerDelay) << 1) + DCT));
+ } else if (RegVal & 0x4) {
+ BadDimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) / CsPerDelay) << 1) + DCT));
+ }
+ }
+ }
+ }
+ // Check if the system is capable of doing NB Pstate change
+ if (MemNGetBitFieldNb (NBPtr, BFNbPstateDis) == 0) {
+ NbPsCapMsk = DCT0_NBPSTATE_SUPPORT_MASK;
+ }
+ if (MemNGetBitFieldNb (NBPtr, BFMemPstateDis) == 0) {
+ MemPstateMsk = DCT0_MEMPSTATE_MASK;
+ }
+
+ MemNSwitchDCTNb (NBPtr, 0);
+ // Set channel mask
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 = 0;
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 = 0;
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ if (DimmMask & (0x55 << DCT)) {
+ // Set mask before exit self refresh
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= (NbPsCapMsk | MemPstateMsk | 1) << DCT;
+ // Set mask after exit self refresh
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= (NbPsCapMsk | MemPstateMsk | 1) << DCT;
+ } else if (BadDimmMask & (0x55 << DCT)) {
+ // Need to save function 2 registers for bad dimm
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= 1 << DCT;
+ }
+ }
+
+ // Set dimm mask
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask2 = DimmMask;
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 = DimmMask;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function read the value of CSR register.
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in] *Value - Pointer to the value be read.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+STATIC
+MemNS3GetCSRTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT8 TempValue;
+ UINT8 Dct;
+ UINT32 ExtendOffset;
+ UINT32 TempFunc;
+
+ ExtendOffset = Address.Address.Register;
+ TempFunc = Address.Address.Function;
+
+ // Switch Dct
+ Address.Address.Function = FUNC_1;
+ Address.Address.Register = 0x10C;
+ Dct = 0;
+ if (ExtendOffset & 0x400) {
+ Dct = 1;
+ }
+ LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+ TempValue = (TempValue & 0xFE) | Dct;
+ LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+ Address.Address.Function = TempFunc;
+
+ Address.Address.Register = 0x98;
+ ExtendOffset &= 0x3FF;
+ LibAmdPciWrite (AccessS3SaveWidth32, Address, &ExtendOffset, ConfigPtr);
+ IDS_OPTION_HOOK (IDS_AFTER_DCT_PHY_ACCESS, NULL, ConfigPtr);
+ Address.Address.Register = 0x9C;
+ LibAmdPciRead (AccessWidth, Address, Value, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function write to a CSR register
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value be read.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+STATIC
+MemNS3SetCSRTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT8 TempValue;
+ UINT8 Dct;
+ UINT32 ExtendOffset;
+ UINT32 ValueWrite;
+ UINT32 TempFunc;
+
+ ExtendOffset = Address.Address.Register;
+
+ TempFunc = Address.Address.Function;
+ // Switch Dct
+ Address.Address.Function = FUNC_1;
+ Address.Address.Register = 0x10C;
+ Dct = 0;
+ if (ExtendOffset & 0x400) {
+ Dct = 1;
+ }
+ LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+ TempValue = (TempValue & 0xFE) | Dct;
+ LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+
+ Address.Address.Function = TempFunc;
+ Address.Address.Register = 0x9C;
+
+ ExtendOffset &= 0x3FF;
+ ExtendOffset |= 0x40000000;
+ switch (AccessWidth) {
+ case AccessS3SaveWidth8:
+ ValueWrite = *(UINT8 *) Value;
+ break;
+ case AccessS3SaveWidth16:
+ ValueWrite = *(UINT16 *) Value;
+ break;
+ case AccessS3SaveWidth32:
+ ValueWrite = *(UINT32 *) Value;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ LibAmdPciWrite (AccessS3SaveWidth32, Address, &ValueWrite, ConfigPtr);
+ Address.Address.Register = 0x98;
+ LibAmdPciWrite (AccessS3SaveWidth32, Address, &ExtendOffset, ConfigPtr);
+ IDS_OPTION_HOOK (IDS_AFTER_DCT_PHY_ACCESS, NULL, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function that set PllLockTime or PhyPSMasterChannel or disable auto compensation.
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+STATIC
+MemNS3SetPhyFenceTN (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT16 FenceValue;
+ UINT16 Fence2Data;
+ UINT16 Fence2Reg;
+ BIT_FIELD_NAME BitField;
+ MEM_NB_BLOCK *NBPtr;
+ LOCATE_HEAP_PTR LocateBufferPtr;
+ S3_MEM_NB_BLOCK *S3NBPtr;
+
+ BitField = (BIT_FIELD_NAME) Address.Address.Register;
+ FenceValue = *(UINT16 *) Value;
+ // See which Node should be accessed
+
+ LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
+
+ if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
+ S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
+ NBPtr = S3NBPtr[0].NBPtr;
+
+ // Do nothing if currently in memory pstate 0 context
+ if (NBPtr->MemPstate == MEMORY_PSTATE0) {
+ return;
+ }
+
+ if (BitField == BFChAM1FenceSave) {
+ MemNSwitchDCTNb (NBPtr, 0);
+ } else {
+ MemNSwitchDCTNb (NBPtr, 1);
+ }
+ MAKE_TSEFO (NBPtr->NBRegTable, DCT_PHY_ACCESS, 0x0C, 30, 16, BFPhyFence);
+ MemNSetBitFieldNb (NBPtr, BFPhyFence, FenceValue);
+
+ // Program Fence 2 for MState 1
+ Fence2Data = 0;
+ if ((FenceValue & 0x1F) < 16) {
+ Fence2Data |= (FenceValue & 0x1F) | 0x10;
+ }
+ if (((FenceValue >> 5) & 0x1F) < 16) {
+ Fence2Data |= (((FenceValue >> 5) & 0x1F) | 0x10) << 10;
+ }
+ if (((FenceValue >> 10) & 0x1F) < 16) {
+ Fence2Data |= (((FenceValue >> 10) & 0x1F) | 0x10) << 5;
+ }
+ MemNSetBitFieldNb (NBPtr, BFDataFence2, Fence2Data);
+
+ // Program another Fence 2 register for Mstate 1
+ Fence2Reg = (UINT16) MemNGetBitFieldNb (NBPtr, BFFence2);
+ Fence2Reg = (Fence2Reg &~(UINT16) ((0x1F << 10) | 0x1F)) | (Fence2Data & 0x1F) | (((Fence2Data >> 5) & 0x1F) << 10);
+ MemNSetBitFieldNb (NBPtr, BFFence2, Fence2Reg);
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mntn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mntn.c
new file mode 100644
index 0000000000..63f255bc0a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mntn.c
@@ -0,0 +1,618 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mntn.c
+ *
+ * Common Northbridge functions for TN
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 64574 $ @e \$Date: 2012-01-25 01:01:51 -0600 (Wed, 25 Jan 2012) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "mntn.h"
+#include "mu.h"
+#include "S3.h"
+#include "cpuRegisters.h"
+#include "cpuFamRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "heapManager.h"
+#include "GeneralServices.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_MEM_NB_TN_MNTN_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+BOOLEAN
+STATIC
+MemNRegAccessFenceTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ );
+
+/**
+ * Array for frequency change related parameters.
+ */
+CONST MEM_FREQ_CHANGE_PARAM FreqChangeParamTN = {0x0190, 0, 0, 0, 0, 0, 0, 0};
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+extern BUILD_OPT_CFG UserOptions;
+extern PSO_ENTRY DefaultPlatformMemoryConfiguration[];
+extern OPTION_MEM_FEATURE_NB* memNTrainFlowControl[];
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the northbridge block
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *MemPtr - Pointer to the MEM_DATA_STRUCT
+ * @param[in] *FeatPtr - Pointer to the MEM_FEAT_BLOCK_NB
+ * @param[in] *SharedPtr - Pointer to the MEM_SHARED_DATA
+ * @param[in] NodeID - UINT8 indicating node ID of the NB object.
+ *
+ * @return Boolean indicating that this is the correct memory
+ * controller type for the node number that was passed in.
+ */
+
+BOOLEAN
+MemConstructNBBlockTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN MEM_FEAT_BLOCK_NB *FeatPtr,
+ IN MEM_SHARED_DATA *SharedPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 Dct;
+ UINT8 Channel;
+ UINT8 SpdSocketIndex;
+ UINT8 SpdChannelIndex;
+ DIE_STRUCT *MCTPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem->SocketId, &(MemPtr->DiesPerSystem->LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemNIsIdSupportedTN (NBPtr, &(MemPtr->DiesPerSystem->LogicalCpuid))) {
+ return FALSE;
+ }
+
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->RefPtr = MemPtr->ParameterListPtr;
+ NBPtr->SharedPtr = SharedPtr;
+
+ MCTPtr = MemPtr->DiesPerSystem;
+ NBPtr->MCTPtr = MCTPtr;
+ NBPtr->MCTPtr->NodeId = NodeID;
+ NBPtr->PciAddr.AddressValue = MCTPtr->PciAddr.AddressValue;
+ NBPtr->VarMtrrHiMsk = GetVarMtrrHiMsk (&(MemPtr->DiesPerSystem->LogicalCpuid), &(MemPtr->StdHeader));
+
+ //
+ // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
+ //
+ AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_TN * (
+ sizeof (DCT_STRUCT) + (
+ MAX_CHANNELS_PER_DCT_TN * (sizeof (CH_DEF_STRUCT) + sizeof (MEM_PS_BLOCK) + sizeof (CH_TIMING_STRUCT))
+ )
+ );
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0);
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
+ PutEventLog (AGESA_FATAL, MEM_ERROR_HEAP_ALLOCATE_FOR_DCT_STRUCT_AND_CH_DEF_STRUCTs, NBPtr->Node, 0, 0, 0, &MemPtr->StdHeader);
+ SetMemError (AGESA_FATAL, MCTPtr);
+ ASSERT(FALSE); // Could not allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
+ return FALSE;
+ }
+
+ MCTPtr->DctCount = MAX_DCTS_PER_NODE_TN;
+ MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_TN * sizeof (DCT_STRUCT);
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MCTPtr->DctData[Dct].Dct = Dct;
+ MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_TN;
+ MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[0].Dct = Dct;
+ AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_TN * sizeof (CH_DEF_STRUCT);
+ MCTPtr->DctData[Dct].TimingsMemPs1 = (CH_TIMING_STRUCT *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_TN * sizeof (CH_TIMING_STRUCT);
+ }
+ NBPtr->PSBlock = (MEM_PS_BLOCK *) AllocHeapParams.BufferPtr;
+
+ //
+ // Initialize Socket List
+ //
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ MemPtr->SocketList[MCTPtr->SocketId].ChannelPtr[(MCTPtr->DieId * 2) + Dct] = &(MCTPtr->DctData[Dct].ChData[0]);
+ MemPtr->SocketList[MCTPtr->SocketId].TimingsPtr[(MCTPtr->DieId * 2) + Dct] = &(MCTPtr->DctData[Dct].Timings);
+ MCTPtr->DctData[Dct].ChData[0].ChannelID = (MCTPtr->DieId * 2) + Dct;
+ }
+
+ MemNInitNBDataTN (NBPtr);
+
+ FeatPtr->InitCPG (NBPtr);
+ FeatPtr->InitHwRxEn (NBPtr);
+ FeatPtr->excel221 (NBPtr);
+
+ NBPtr->FeatPtr = FeatPtr;
+
+ //
+ // Calculate SPD Offsets per channel and assign pointers to the data. At this point, we calculate the Node-Dct-Channel
+ // centric offsets and store the pointers to the first DIMM of each channel in the Channel Definition struct for that
+ // channel. This pointer is then used later to calculate the offsets to be used for each logical dimm once the
+ // dimm types(QR or not) are known. This is done in the Technology block constructor.
+ //
+ // Calculate the SpdSocketIndex separately from the SpdChannelIndex.
+ // This will facilitate modifications due to some processors that might
+ // map the DCT-CHANNEL differently.
+ //
+ SpdSocketIndex = GetSpdSocketIndex (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, &MemPtr->StdHeader);
+ //
+ // Traverse the Dct/Channel structures
+ //
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_TN; Dct++) {
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_TN; Channel++) {
+ //
+ // Calculate the number of Dimms on this channel using the
+ // die/dct/channel to Socket/channel conversion.
+ //
+ SpdChannelIndex = GetSpdChannelIndex (NBPtr->RefPtr->PlatformMemoryConfiguration,
+ NBPtr->MCTPtr->SocketId,
+ MemNGetSocketRelativeChannelNb (NBPtr, Dct, Channel),
+ &MemPtr->StdHeader);
+ NBPtr->MCTPtr->DctData[Dct].ChData[Channel].SpdPtr = &(MemPtr->SpdDataStructure[SpdSocketIndex + SpdChannelIndex]);
+ }
+ }
+
+ //
+ // Initialize Dct and DctCfgSel bit
+ //
+ MemNSetBitFieldNb (NBPtr, BFDctCfgSel, 0);
+ MemNSwitchDCTNb (NBPtr, 0);
+
+ if (MemNGetBitFieldNb (NBPtr, BFMemPstateDis) == 1) {
+ // MemPstate is disabled
+ NBPtr->MemPstateStage = 0;
+ }
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes member functions and variables of NB block.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNInitNBDataTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ NBPtr->DctCachePtr = NBPtr->DctCache;
+ NBPtr->PsPtr = NBPtr->PSBlock;
+
+ MemNInitNBRegTableTN (NBPtr, NBPtr->NBRegTable);
+ NBPtr->Node = ((UINT8) NBPtr->PciAddr.Address.Device) - 24;
+ NBPtr->Dct = 0;
+ NBPtr->Channel = 0;
+ NBPtr->DctCount = MAX_DCTS_PER_NODE_TN;
+ NBPtr->ChannelCount = MAX_CHANNELS_PER_DCT_TN;
+ NBPtr->NodeCount = MAX_NODES_SUPPORTED_TN;
+ NBPtr->Ganged = FALSE;
+ NBPtr->PosTrnPattern = POS_PATTERN_256B;
+ NBPtr->MemCleared = FALSE;
+ NBPtr->StartupSpeed = DDR667_FREQUENCY;
+ NBPtr->RcvrEnDlyLimit = 0x1FF;
+ NBPtr->DefDctSelIntLvAddr = 4;
+ NBPtr->NbFreqChgState = 0;
+ NBPtr->FreqChangeParam = (MEM_FREQ_CHANGE_PARAM *) &FreqChangeParamTN;
+ NBPtr->MaxRxEnSeedTotal = 0x1FF;
+ NBPtr->MinRxEnSeedGross = 0;
+ NBPtr->CsRegMsk = 0x7FF8FFE0;
+ NBPtr->RdDqsDlyRetrnStat = RDDQSDLY_RTN_NEEDED;
+ NBPtr->MemPstate = MEMORY_PSTATE0;
+ NBPtr->MemPstateStage = MEMORY_PSTATE_1ST_STAGE;
+ NBPtr->CsPerChannel = MAX_CS_PER_CHANNEL_TN;
+ NBPtr->CsPerDelay = 1;
+ NBPtr->TotalMaxVrefRange = 0x20;
+ NBPtr->TotalRdDQSDlyRange = 0x40;
+ NBPtr->PhaseLaneMask = 0x3FFFF;
+ NBPtr->MaxDiamondStep = 3;
+
+ LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &NBPtr->MemPtr->StdHeader);
+ MemNInitNBDataNb (NBPtr);
+
+ NBPtr->SetMaxLatency = MemNSetMaxLatencyTN;
+ NBPtr->getMaxLatParams = MemNGetMaxLatParamsTN;
+ NBPtr->InitializeMCT = MemNInitializeMctTN;
+ NBPtr->FinalizeMCT = MemNFinalizeMctTN;
+ NBPtr->SendMrsCmd = MemNSendMrsCmdUnb;
+ NBPtr->sendZQCmd = MemNSendZQCmdNb;
+ NBPtr->WritePattern = MemNWritePatternTN;
+ NBPtr->ReadPattern = MemNReadPatternTN;
+ NBPtr->GenHwRcvEnReads = (VOID (*) (MEM_NB_BLOCK *, UINT32)) memDefRet;
+ NBPtr->CompareTestPattern = MemNCompareTestPatternNb;
+ NBPtr->InsDlyCompareTestPattern = MemNInsDlyCompareTestPatternNb;
+ NBPtr->StitchMemory = MemNStitchMemoryNb;
+ NBPtr->AutoConfig = MemNAutoConfigTN;
+ NBPtr->PlatformSpec = MemNPlatformSpecUnb;
+ NBPtr->InitMCT = MemNInitMCTNb;
+ NBPtr->DisableDCT = MemNDisableDCTUnb;
+ NBPtr->StartupDCT = MemNStartupDCTUnb;
+ NBPtr->SyncTargetSpeed = MemNSyncTargetSpeedNb;
+ NBPtr->ChangeFrequency = MemNChangeFrequencyUnb;
+ NBPtr->RampUpFrequency = MemNRampUpFrequencyUnb;
+ NBPtr->ChangeNbFrequency = MemNChangeNbFrequencyUnb;
+ NBPtr->ChangeNbFrequencyWrap = MemNChangeNbFrequencyWrapUnb;
+ NBPtr->ProgramNbPsDependentRegs = MemNProgramNbPstateDependentRegistersTN;
+ NBPtr->ProgramCycTimings = MemNProgramCycTimingsUnb;
+ NBPtr->SyncDctsReady = (BOOLEAN (*) (MEM_NB_BLOCK *)) memDefTrue;
+ NBPtr->HtMemMapInit = MemNHtMemMapInitTN;
+ NBPtr->SyncAddrMapToAllNodes = (BOOLEAN (*) (MEM_NB_BLOCK *)) memDefTrue;
+ NBPtr->CpuMemTyping = MemNCPUMemTypingNb;
+ NBPtr->BeforeDqsTraining = MemNBeforeDQSTrainingTN;
+ NBPtr->AfterDqsTraining = MemNAfterDQSTrainingTN;
+ NBPtr->OtherTiming = MemNOtherTimingTN;
+ NBPtr->UMAMemTyping = MemNUMAMemTypingNb;
+ NBPtr->GetSocketRelativeChannel = MemNGetSocketRelativeChannelNb;
+ NBPtr->TechBlockSwitch = MemNTechBlockSwitchTN;
+ NBPtr->MemNCmnGetSetFieldNb = MemNCmnGetSetFieldTN;
+ NBPtr->SetEccSymbolSize = (VOID (*) (MEM_NB_BLOCK *)) memDefRet;
+ NBPtr->TrainingFlow = MemNTrainingFlowUnb;
+ NBPtr->PollBitField = MemNPollBitFieldNb;
+ NBPtr->BrdcstCheck = MemNBrdcstCheckNb;
+ NBPtr->BrdcstSet = MemNBrdcstSetNb;
+ NBPtr->GetTrainDly = MemNGetTrainDlyNb;
+ NBPtr->SetTrainDly = MemNSetTrainDlyNb;
+ NBPtr->PhyFenceTraining = MemNPhyFenceTrainingUnb;
+ NBPtr->GetSysAddr = MemNGetMCTSysAddrNb;
+ NBPtr->RankEnabled = MemNRankEnabledNb;
+ NBPtr->MemNBeforeDramInitNb = MemNBeforeDramInitTN;
+ NBPtr->MemNcmnGetSetTrainDly = MemNcmnGetSetTrainDlyUnb;
+ NBPtr->MemPPhyFenceTrainingNb = (VOID (*) (MEM_NB_BLOCK *)) memDefRet;
+ NBPtr->MemNInitPhyComp = MemNInitPhyCompTN;
+ NBPtr->MemNBeforePlatformSpecNb = (VOID (*) (MEM_NB_BLOCK *)) memDefRet;
+ NBPtr->MemNPlatformSpecificFormFactorInitNb = MemNPlatformSpecificFormFactorInitTblDrvNb;
+ NBPtr->MemNPFenceAdjustNb = MemNPFenceAdjustTN;
+ NBPtr->GetTrainDlyParms = MemNGetTrainDlyParmsUnb;
+ NBPtr->TrainingPatternInit = MemNTrainingPatternInitNb;
+ NBPtr->TrainingPatternFinalize = MemNTrainingPatternFinalizeNb;
+ NBPtr->GetApproximateWriteDatDelay = MemNGetApproximateWriteDatDelayNb;
+ NBPtr->FlushPattern = MemNFlushPatternNb;
+ NBPtr->MinDataEyeWidth = MemNMinDataEyeWidthNb;
+ NBPtr->MemNCapSpeedBatteryLife = MemNCapSpeedBatteryLifeTN;
+ NBPtr->GetUmaSize = MemNGetUmaSizeTN;
+ NBPtr->GetMemClkFreqId = MemNGetMemClkFreqIdUnb;
+ NBPtr->EnableSwapIntlvRgn = MemNEnableSwapIntlvRgnNb;
+ NBPtr->WaitXMemClks = MemNWaitXMemClksNb;
+ NBPtr->MemNGetDramTerm = MemNGetDramTermTblDrvNb;
+ NBPtr->MemNGetDynDramTerm = MemNGetDynDramTermTblDrvNb;
+ NBPtr->MemNGetMR0CL = MemNGetMR0CLTblDrvNb;
+ NBPtr->MemNGetMR0WR = MemNGetMR0WRTblDrvNb;
+ NBPtr->MemNSaveMR0 = (VOID (*) (MEM_NB_BLOCK *, UINT32)) memDefRet;
+ NBPtr->MemNGetMR2CWL = MemNGetMR2CWLUnb;
+ NBPtr->AllocateC6Storage = MemNAllocateC6StorageTN;
+ NBPtr->MemNBeforePlatformSpecNb = MemNBeforePlatformSpecTN;
+ NBPtr->MemNGetMemoryWidth = MemNGetMemoryWidthUnb;
+
+ NBPtr->IsSupported[SetDllShutDown] = TRUE;
+ NBPtr->IsSupported[CheckMaxDramRate] = TRUE;
+ NBPtr->IsSupported[CheckPhyFenceTraining] = TRUE;
+ NBPtr->IsSupported[CheckSendAllMRCmds] = TRUE;
+ NBPtr->IsSupported[CheckFindPSOverideWithSocket] = TRUE;
+ NBPtr->IsSupported[FenceTrnBeforeDramInit] = TRUE;
+ NBPtr->IsSupported[UnifiedNbFence] = TRUE;
+ NBPtr->IsSupported[CheckODTControls] = TRUE;
+ NBPtr->IsSupported[CheckDramTerm] = TRUE;
+ NBPtr->IsSupported[CheckDramTermDyn] = TRUE;
+ NBPtr->IsSupported[CheckQoff] = TRUE;
+ NBPtr->IsSupported[CheckDrvImpCtrl] = TRUE;
+ NBPtr->IsSupported[CheckSetSameDctODTsEn] = TRUE;
+ NBPtr->IsSupported[WLSeedAdjust] = TRUE;
+ NBPtr->IsSupported[WLNegativeDelay] = TRUE;
+ NBPtr->IsSupported[TwoStageDramInit] = TRUE;
+ NBPtr->IsSupported[ForceEnMemHoleRemapping] = TRUE;
+ NBPtr->IsSupported[ProgramCsrComparator] = TRUE;
+ NBPtr->IsSupported[AdjustTrp] = TRUE; // erratum 638
+ NBPtr->IsSupported[ForcePhyToM0] = TRUE;
+
+ NBPtr->FamilySpecificHook[ExitPhyAssistedTraining] = MemNExitPhyAssistedTrainingTN;
+ NBPtr->FamilySpecificHook[DCTSelectSwitch] = MemNDctCfgSelectUnb;
+ NBPtr->FamilySpecificHook[AfterSaveRestore] = MemNAfterSaveRestoreUnb;
+ NBPtr->FamilySpecificHook[OverrideRcvEnSeed] = MemNOverrideRcvEnSeedTN;
+ NBPtr->FamilySpecificHook[OverrideWLSeed] = MemNOverrideWLSeedTN;
+ NBPtr->FamilySpecificHook[CalcWrDqDqsEarly] = MemNCalcWrDqDqsEarlyUnb;
+ NBPtr->FamilySpecificHook[AdjustRdDqsDlyOffset] = MemNAdjustRdDqsDlyOffsetUnb;
+ NBPtr->FamilySpecificHook[GetDdrMaxRate] = MemNGetMaxDdrRateUnb;
+ NBPtr->FamilySpecificHook[SetSkewMemClk] = MemNSetSkewMemClkUnb;
+ NBPtr->FamilySpecificHook[AfterMemClkFreqVal] = MemNAdjustPllLockTimeTN;
+ NBPtr->FamilySpecificHook[AdjustCSIntLvLowAddr] = MemNCSIntLvLowAddrAdjTN;
+ NBPtr->FamilySpecificHook[ReleaseNbPstate] = MemNReleaseNbPstateTN;
+ NBPtr->FamilySpecificHook[InitializeRxEnSeedlessTraining] = MemNInitializeRxEnSeedlessTrainingUnb;
+ NBPtr->FamilySpecificHook[TrackRxEnSeedlessRdWrNoWindBLError] = MemNTrackRxEnSeedlessRdWrNoWindBLErrorUnb;
+ NBPtr->FamilySpecificHook[TrackRxEnSeedlessRdWrSmallWindBLError] = MemNTrackRxEnSeedlessRdWrSmallWindBLErrorUnb;
+ NBPtr->FamilySpecificHook[InitialzeRxEnSeedlessByteLaneError] = MemNInitialzeRxEnSeedlessByteLaneErrorUnb;
+ NBPtr->FamilySpecificHook[MemPstateStageChange] = MemNMemPstateStageChangeTN;
+ NBPtr->FamilySpecificHook[ProgramFence2RxDll] = MemNProgramFence2RxDllTN;
+ NBPtr->FamilySpecificHook[RdDqsDlyRestartChk] = MemNRdDqsDlyRestartChkTN;
+ NBPtr->FamilySpecificHook[BeforeWrDatTrn] = MemNHookBfWrDatTrnTN;
+ NBPtr->FamilySpecificHook[RegAccessFence] = MemNRegAccessFenceTN;
+ NBPtr->FamilySpecificHook[AdjustWrDqsBeforeSeedScaling] = MemNAdjustWrDqsBeforeSeedScalingUnb;
+ NBPtr->FamilySpecificHook[WLMR1] = MemNWLMR1TN;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the default values in the MEM_DATA_STRUCT
+ *
+ * @param[in,out] *MemPtr - Pointer to the MEM_DATA_STRUCT
+ *
+ */
+VOID
+MemNInitDefaultsTN (
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ )
+{
+ UINT8 Socket;
+ UINT8 Channel;
+ MEM_PARAMETER_STRUCT *RefPtr;
+ ASSERT (MemPtr != NULL);
+ RefPtr = MemPtr->ParameterListPtr;
+
+ // Memory Map/Mgt.
+ // Mask Bottom IO with 0xF8 to force hole size to have granularity of 128MB
+ RefPtr->BottomIo = 0xE0;
+ RefPtr->UmaMode = UserOptions.CfgUmaMode;
+ RefPtr->UmaSize = UserOptions.CfgUmaSize;
+ RefPtr->MemHoleRemapping = TRUE;
+ RefPtr->LimitMemoryToBelow1Tb = UserOptions.CfgLimitMemoryToBelow1Tb;
+
+ // Dram Timing
+ RefPtr->UserTimingMode = UserOptions.CfgTimingModeSelect;
+ RefPtr->MemClockValue = UserOptions.CfgMemoryClockSelect;
+ for (Socket = 0; Socket < MAX_SOCKETS_SUPPORTED; Socket++) {
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_SOCKET; Channel++) {
+ MemPtr->SocketList[Socket].ChannelPtr[Channel] = NULL;
+ MemPtr->SocketList[Socket].TimingsPtr[Channel] = NULL;
+ }
+ }
+
+ // Memory Clear
+ RefPtr->EnableMemClr = TRUE;
+
+ // TableBasedAlterations
+ RefPtr->TableBasedAlterations = NULL;
+
+ // Platform config table
+ RefPtr->PlatformMemoryConfiguration = DefaultPlatformMemoryConfiguration;
+
+ // Memory Restore
+ RefPtr->MemRestoreCtl = FALSE;
+ RefPtr->SaveMemContextCtl = FALSE;
+ AmdS3ParamsInitializer (&RefPtr->MemContext);
+
+ // Dram Configuration
+ RefPtr->EnableBankIntlv = UserOptions.CfgMemoryEnableBankInterleaving;
+ RefPtr->EnableNodeIntlv = UserOptions.CfgMemoryEnableNodeInterleaving;
+ RefPtr->EnableChannelIntlv = UserOptions.CfgMemoryChannelInterleaving;
+ RefPtr->EnableBankSwizzle = UserOptions.CfgBankSwizzle;
+ RefPtr->EnableParity = UserOptions.CfgMemoryParityEnable;
+ RefPtr->EnableOnLineSpareCtl = UserOptions.CfgOnlineSpare;
+
+ // Dram Power
+ RefPtr->EnablePowerDown = UserOptions.CfgMemoryPowerDown;
+
+ // ECC
+ RefPtr->EnableEccFeature = UserOptions.CfgEnableEccFeature;
+
+ // Vref
+ RefPtr->ExternalVrefCtl = UserOptions.CfgExternalVrefCtlFeature;
+
+ //Training Mode
+ RefPtr->ForceTrainMode = UserOptions.CfgForceTrainMode;
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * This function writes training pattern
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Pattern[] - Pattern to write
+ * @param[in] Address - System Address [47:16]
+ * @param[in] ClCount - Number of cache lines
+ *
+ */
+
+VOID
+MemNWritePatternTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address,
+ IN UINT8 Pattern[],
+ IN UINT16 ClCount
+ )
+{
+ Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
+ MemUWriteCachelines (Address, Pattern, ClCount);
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * This function reads training pattern
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Buffer[] - Buffer to fill
+ * @param[in] Address - System Address [47:16]
+ * @param[in] ClCount - Number of cache lines
+ *
+ */
+
+VOID
+MemNReadPatternTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ )
+{
+ Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
+ MemUReadCachelines (Buffer, Address, ClCount);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initiates DQS training for TN
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+BOOLEAN
+memNEnableTrainSequenceTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ BOOLEAN Retval;
+ Retval = TRUE;
+ if (!MemNIsIdSupportedTN (NBPtr, &(NBPtr->MemPtr->DiesPerSystem[NBPtr->MCTPtr->NodeId].LogicalCpuid))) {
+ Retval = FALSE;
+ }
+ return Retval;
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function makes sure that previous phy register writes are done.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ *
+ */
+
+BOOLEAN
+STATIC
+MemNRegAccessFenceTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ // If subsequent writes to this array are scheduled, such as when writing several byte lanes during dram
+ // training, then it is recommended to issue a dummy register read to ensure the last write.
+ NBPtr->GetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (0, 0));
+
+ return TRUE;
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mntn.h b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mntn.h
new file mode 100644
index 0000000000..4d4316bfdb
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/TN/mntn.h
@@ -0,0 +1,341 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mntn.h
+ *
+ * Northbridge TN
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/TN)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+ *
+ * AMD is granting you permission to use this software (the Materials)
+ * pursuant to the terms and conditions of your Software License Agreement
+ * with AMD. This header does *NOT* give you permission to use the Materials
+ * or any rights under AMD's intellectual property. Your use of any portion
+ * of these Materials shall constitute your acceptance of those terms and
+ * conditions. If you do not agree to the terms and conditions of the Software
+ * License Agreement, please do not use any portion of these Materials.
+ *
+ * CONFIDENTIALITY: The Materials and all other information, identified as
+ * confidential and provided to you by AMD shall be kept confidential in
+ * accordance with the terms and conditions of the Software License Agreement.
+ *
+ * LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+ * PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+ * MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+ * OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+ * IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+ * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+ * INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+ * GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+ * RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+ * EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+ * THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+ *
+ * AMD does not assume any responsibility for any errors which may appear in
+ * the Materials or any other related information provided to you by AMD, or
+ * result from use of the Materials or any related information.
+ *
+ * You agree that you will not reverse engineer or decompile the Materials.
+ *
+ * NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+ * further information, software, technical information, know-how, or show-how
+ * available to you. Additionally, AMD retains the right to modify the
+ * Materials at any time, without notice, and is not obligated to provide such
+ * modified Materials to you.
+ *
+ * U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+ * "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+ * subject to the restrictions as set forth in FAR 52.227-14 and
+ * DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+ * Government constitutes acknowledgement of AMD's proprietary rights in them.
+ *
+ * EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+ * direct product thereof will be exported directly or indirectly, into any
+ * country prohibited by the United States Export Administration Act and the
+ * regulations thereunder, without the required authorization from the U.S.
+ * government nor will be used for any purpose prohibited by the same.
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MNTN_H_
+#define _MNTN_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_DCTS_PER_NODE_TN 2
+#define MAX_CHANNELS_PER_DCT_TN 1
+#define MAX_NODES_SUPPORTED_TN 1
+#define MAX_CS_PER_CHANNEL_TN 4
+
+#define DEFAULT_WR_ODT_TN 6
+#define DEFAULT_RD_ODT_TN 6
+#define DEFAULT_RD_ODT_TRNONDLY_TN 0
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemConstructNBBlockTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN MEM_FEAT_BLOCK_NB *FeatPtr,
+ IN MEM_SHARED_DATA *SharedPtr,
+ IN UINT8 NodeID
+ );
+
+VOID
+MemNInitNBDataTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNInitDefaultsTN (
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ );
+
+BOOLEAN
+MemNInitializeMctTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+BOOLEAN
+MemNAutoConfigTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+BOOLEAN
+MemNOtherTimingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNInitPhyCompTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNWritePatternTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address,
+ IN UINT8 Pattern[],
+ IN UINT16 ClCount
+ );
+
+VOID
+MemNReadPatternTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ );
+
+VOID
+MemNInitNBRegTableTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT TSEFO NBRegTable[]
+ );
+
+BOOLEAN
+MemNIsIdSupportedTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ );
+
+UINT32
+MemNCmnGetSetFieldTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ );
+
+BOOLEAN
+memNEnableTrainSequenceTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNTechBlockSwitchTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNAfterDQSTrainingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNCapSpeedBatteryLifeTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNGetMaxLatParamsTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 MaxRcvEnDly,
+ IN OUT UINT16 *MinDlyPtr,
+ IN OUT UINT16 *MaxDlyPtr,
+ IN OUT UINT16 *DlyBiasPtr
+ );
+
+VOID
+MemNSetMaxLatencyTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 MaxRcvEnDly
+ );
+
+BOOLEAN
+MemNExitPhyAssistedTrainingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ );
+
+BOOLEAN
+MemNOverrideRcvEnSeedTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *SeedPtr
+ );
+
+VOID
+MemNBeforeDQSTrainingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNProgramNbPstateDependentRegistersTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+BOOLEAN
+MemNAdjustPllLockTimeTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *PllLockTime
+ );
+
+BOOLEAN
+MemNOverrideWLSeedTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *SeedPtr
+ );
+
+BOOLEAN
+MemNFinalizeMctTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+BOOLEAN
+MemNHtMemMapInitTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+UINT32
+MemNGetUmaSizeTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNBeforeDramInitTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+BOOLEAN
+MemNCSIntLvLowAddrAdjTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *LowBit
+ );
+
+VOID
+MemNAllocateC6StorageTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNPFenceAdjustTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT INT16 *Value16
+ );
+
+BOOLEAN
+MemNReleaseNbPstateTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ );
+
+BOOLEAN
+MemNMemPstateStageChangeTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ );
+
+BOOLEAN
+MemNProgramFence2RxDllTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *Fence2Data
+ );
+
+VOID
+MemNAdjustNBPstateVolTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+BOOLEAN
+MemNRdDqsDlyRestartChkTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *Center
+ );
+
+BOOLEAN
+MemNHookBfWrDatTrnTN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *ChipSel
+ );
+
+VOID
+MemNSetOtherTimingTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNPowerDownCtlTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNBeforePlatformSpecTN (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+BOOLEAN
+MemNWLMR1TN (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *Value
+ );
+#endif /* _MNTN_H_ */
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mn.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mn.c
new file mode 100644
index 0000000000..e203fd0388
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mn.c
@@ -0,0 +1,530 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mn.c
+ *
+ * Common Northbridge functions
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mport.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "mu.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_MEM_NB_MN_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern OPTION_MEM_FEATURE_NB* memNTrainFlowControl[];
+
+extern BUILD_OPT_CFG UserOptions;
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes member functions and variables of NB block.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNInitNBDataNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ INT32 i;
+ UINT8 *BytePtr;
+
+ NBPtr->DctCachePtr = NBPtr->DctCache;
+ NBPtr->PsPtr = NBPtr->PSBlock;
+
+ BytePtr = (UINT8 *) (NBPtr->DctCache);
+ for (i = 0; i < sizeof (NBPtr->DctCache); i++) {
+ *BytePtr++ = 0;
+ }
+
+ for (i = 0; i < EnumSize; i++) {
+ NBPtr->IsSupported[i] = FALSE;
+ }
+
+ for (i = 0; i < NumberOfHooks; i++) {
+ NBPtr->FamilySpecificHook[i] = MemNDefaultFamilyHookNb;
+ }
+
+ for (i = 0; i < NBPtr->DctCount; i++) {
+ NBPtr->PSBlock[i].MemPGetPass1Seeds = (BOOLEAN (*) (MEM_NB_BLOCK *)) memDefTrue;
+ }
+
+ NBPtr->SwitchDCT = MemNSwitchDCTNb;
+ NBPtr->SwitchChannel = MemNSwitchChannelNb;
+ NBPtr->GetBitField = MemNGetBitFieldNb;
+ NBPtr->SetBitField = MemNSetBitFieldNb;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * Get System address of Chipselect RJ 16 bits (Addr[47:16])
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Receiver - Chipselect to be targeted [0-7]
+ * @param[out] AddrPtr - Pointer to System Address [47:16]
+ *
+ * @return TRUE - Address is valid
+ * @return FALSE - Address is not valid
+ */
+
+BOOLEAN
+MemNGetMCTSysAddrNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Receiver,
+ OUT UINT32 *AddrPtr
+ )
+{
+ S_UINT64 SMsr;
+ UINT32 CSBase;
+ UINT32 HoleBase;
+ UINT32 DctSelBaseAddr;
+ UINT32 BottomUma;
+ DIE_STRUCT *MCTPtr;
+ MEM_DATA_STRUCT *MemPtr;
+
+ MCTPtr = NBPtr->MCTPtr;
+ MemPtr = NBPtr->MemPtr;
+
+ ASSERT (Receiver < 8);
+
+ CSBase = MemNGetBitFieldNb (NBPtr, BFCSBaseAddr0Reg + Receiver);
+ if (CSBase & 1) {
+ ASSERT ((CSBase & 0xE0) == 0); // Should not enable CS interleaving before DQS training.
+
+ // Scale base address from [39:8] to [47:16]
+ CSBase >>= 8;
+
+ HoleBase = MCTPtr->NodeHoleBase ? MCTPtr->NodeHoleBase : 0x7FFFFFFF;
+
+ if ((MemNGetBitFieldNb (NBPtr, BFDctSelHiRngEn) == 1) && (NBPtr->Dct == MemNGetBitFieldNb (NBPtr, BFDctSelHi))) {
+ DctSelBaseAddr = MemNGetBitFieldNb (NBPtr, BFDctSelBaseAddr) << (27 - 16);
+ if (DctSelBaseAddr > HoleBase) {
+ DctSelBaseAddr -= _4GB_RJ16 - HoleBase;
+ }
+ CSBase += DctSelBaseAddr;
+ } else {
+ CSBase += MCTPtr->NodeSysBase;
+ }
+
+ if (CSBase >= HoleBase) {
+ CSBase += _4GB_RJ16 - HoleBase;
+ }
+
+ CSBase += (UINT32)1 << (21 - 16); // Add 2MB offset to avoid compat area.
+ if ((CSBase >= (MCT_TRNG_KEEPOUT_START >> 8)) && (CSBase <= (MCT_TRNG_KEEPOUT_END >> 8))) {
+ CSBase += (((MCT_TRNG_KEEPOUT_END >> 8) - CSBase) + 0x0F) & 0xFFFFFFF0;
+ }
+
+ if (MCTPtr->Status[SbHWHole]) {
+ if (MCTPtr->Status[SbSWNodeHole]) {
+ LibAmdMsrRead (TOP_MEM, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ if ((CSBase >= (SMsr.lo >> 16)) && (CSBase < _4GB_RJ16)) {
+ return FALSE;
+ }
+ }
+ }
+
+ BottomUma = NBPtr->RefPtr->Sub4GCacheTop >> 16;
+ if (BottomUma && (CSBase >= BottomUma) && (CSBase < _4GB_RJ16)) {
+ return FALSE;
+ }
+ *AddrPtr = CSBase;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function determines if a Rank is enabled.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Receiver - Receiver to check
+ * @return - FALSE
+ *
+ */
+
+BOOLEAN
+MemNRankEnabledNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Receiver
+ )
+{
+ UINT32 CSBase;
+ CSBase = MemNGetBitFieldNb (NBPtr, BFCSBaseAddr0Reg + Receiver);
+ if (CSBase & 1) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the EccSymbolSize bit depending upon configurations
+ * and system override.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNSetEccSymbolSizeNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT16 X4DimmsOnly;
+ BOOLEAN Size;
+ DIE_STRUCT *MCTPtr;
+ DCT_STRUCT *DCTPtr;
+
+ ASSERT (NBPtr != NULL);
+
+ MCTPtr = NBPtr->MCTPtr;
+ DCTPtr = NBPtr->DCTPtr;
+
+ // Determine if this node has only x4 DRAM parts
+ X4DimmsOnly = (UINT16) ((!(DCTPtr->Timings.Dimmx8Present | DCTPtr->Timings.Dimmx16Present)) && DCTPtr->Timings.Dimmx4Present);
+ //
+ // Check if EccSymbolSize BKDG value is overridden
+ //
+ if (UserOptions.CfgEccSymbolSize != ECCSYMBOLSIZE_USE_BKDG) {
+ Size = (UserOptions.CfgEccSymbolSize == ECCSYMBOLSIZE_FORCE_X4) ? FALSE : TRUE;
+ } else {
+ if (X4DimmsOnly && MCTPtr->GangedMode) {
+ Size = FALSE;
+ } else {
+ Size = TRUE;
+ }
+ }
+ IDS_OPTION_HOOK (IDS_ECCSYMBOLSIZE, &Size, &(NBPtr->MemPtr->StdHeader));
+ MemNSetBitFieldNb (NBPtr, BFEccSymbolSize, (UINT32) Size);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets the training control flow
+ * The DDR3 mode bit must be set prior to calling this function
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ */
+BOOLEAN
+MemNTrainingFlowNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ if (MemNGetBitFieldNb (NBPtr, BFDdr3Mode)!= 0) {
+ memNTrainFlowControl[DDR3_TRAIN_FLOW] (NBPtr);
+ } else {
+ memNTrainFlowControl[DDR2_TRAIN_FLOW] (NBPtr);
+ }
+ return TRUE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * This function flushes the training pattern
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Address - System Address [47:16]
+ * @param[in] ClCount - Number of cache lines
+ *
+ */
+
+VOID
+MemNFlushPatternNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ )
+{
+ // Due to speculative execution during MemUReadCachelines, we must
+ // flush one more cache line than we read.
+ MemUProcIOClFlush (Address, ClCount + 1, NBPtr->MemPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function compares test pattern with data in buffer and
+ * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
+ * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
+ * @param[in] ByteCount - Byte count
+ *
+ * @return PASS - Bitmap of results of comparison
+ */
+
+UINT16
+MemNCompareTestPatternNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN UINT16 ByteCount
+ )
+{
+ UINT16 i;
+ UINT16 Pass;
+ UINT8 ColumnCount;
+ UINT8 FailingBitMask[8];
+
+ ASSERT ((ByteCount == 18 * 64) || (ByteCount == 9 * 64) || (ByteCount == 64 * 64) || (ByteCount == 32 * 64) || (ByteCount == 3 * 64));
+
+ ColumnCount = NBPtr->ChannelPtr->ColumnCount;
+ Pass = 0xFFFF;
+ //
+ // Clear Failing Bit Mask
+ //
+ for (i = 0; i < sizeof (FailingBitMask); i++) {
+ FailingBitMask[i] = 0;
+ }
+
+ if (NBPtr->Ganged && (NBPtr->Dct != 0)) {
+ i = 8; // DCT 1 in ganged mode
+ } else {
+ i = 0;
+ }
+
+ for (; i < ByteCount; i++) {
+ if (Buffer[i] != Pattern[i]) {
+ // if bytelane n fails
+ Pass &= ~((UINT16)1 << (i % 8)); // clear bit n
+ FailingBitMask[i % NBPtr->TechPtr->MaxByteLanes ()] |= (Buffer[i] ^ Pattern[i]);
+ }
+
+ if (NBPtr->Ganged && ((i & 7) == 7)) {
+ i += 8; // if ganged, skip over other Channel's Data
+ }
+ }
+ //
+ // Accumulate Failing bit data
+ //
+ for (i = 0; i < sizeof (FailingBitMask); i++) {
+ NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel) + i] &=
+ FailingBitMask[i];
+ }
+
+ return Pass;
+}
+
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function compares test pattern with data in buffer and
+ * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
+ * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
+ * @param[in] ByteCount - Byte count
+ *
+ * @retval PASS - Bitmap of results of comparison
+ * ----------------------------------------------------------------------------
+ */
+UINT16
+MemNInsDlyCompareTestPatternNb (
+ IN MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN UINT16 ByteCount
+ )
+{
+ UINT16 i;
+ UINT16 Pass;
+ UINT16 BeatOffset;
+ UINT16 BeatCnt;
+ UINT8 ColumnCount;
+ UINT8 FailingBitMask[8];
+
+ ASSERT ((ByteCount == 18 * 64) || (ByteCount == 9 * 64) || (ByteCount == 64 * 64) || (ByteCount == 32 * 64) || (ByteCount == 3 * 64));
+
+ ColumnCount = NBPtr->ChannelPtr->ColumnCount;
+ Pass = 0xFFFF;
+ //
+ // Clear Failing Bit Mask
+ //
+ for (i = 0; i < sizeof (FailingBitMask); i++) {
+ FailingBitMask[i] = 0;
+ }
+
+ if (NBPtr->Ganged && (NBPtr->Dct != 0)) {
+ i = 8; // DCT 1 in ganged mode
+ } else {
+ i = 0;
+ }
+
+ if (NBPtr->Ganged) {
+ BeatOffset = 16;
+ } else {
+ BeatOffset = 8;
+ }
+
+ BeatCnt = 0;
+ for (; i < ByteCount; i++) {
+
+ if (Buffer[i] != Pattern[i + BeatOffset]) {
+ // if bytelane n fails
+ Pass &= ~((UINT16)1 << (i % 8)); // clear bit n
+ FailingBitMask[i % NBPtr->TechPtr->MaxByteLanes ()] |= (Buffer[i] ^ Pattern[i + BeatOffset]);
+ }
+
+ if ((i & 7) == 7) {
+ if (NBPtr->Ganged) {
+ i += 8; // if ganged, skip over other Channel's Data
+ }
+ BeatCnt++;
+ }
+
+ if ((BeatCnt & 3) == 3) {
+ // Skip last data beat of a 4-beat burst.
+ BeatCnt++;
+ i = i + BeatOffset;
+ }
+ }
+ //
+ // Accumulate Failing bit data
+ //
+ for (i = 0; i < sizeof (FailingBitMask); i++) {
+ NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel) + i] &=
+ FailingBitMask[i];
+ }
+
+ return Pass;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets the training control flow for UNB
+ * The DDR3 mode bit must be set prior to calling this function
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ */
+BOOLEAN
+MemNTrainingFlowUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ memNTrainFlowControl[DDR3_TRAIN_FLOW] (NBPtr);
+ return TRUE;
+}
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnS3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnS3.c
new file mode 100644
index 0000000000..97ac25fa0b
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnS3.c
@@ -0,0 +1,1493 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnS3.c
+ *
+ * Common Northbridge S3
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "S3.h"
+#include "mfs3.h"
+#include "cpuFamilyTranslation.h"
+#include "heapManager.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_MEM_NB_MNS3_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+VOID
+STATIC
+MemNS3GetSetBitField (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN BOOLEAN IsSet,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ );
+
+BOOLEAN
+STATIC
+MemNS3GetDummyReadAddr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ OUT UINT64 *TestAddr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function executes the S3 resume for a node
+ *
+ * @param[in,out] *S3NBPtr - Pointer to the S3_MEM_NB_BLOCK
+ * @param[in] NodeID - The Node id of the target die
+ *
+ * @return BOOLEAN
+ * TRUE - This is the correct constructor for the targeted node.
+ * FALSE - This isn't the correct constructor for the targeted node.
+ */
+
+BOOLEAN
+MemNS3ResumeNb (
+ IN OUT S3_MEM_NB_BLOCK *S3NBPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 DCT;
+ BOOLEAN GangedEn;
+ UINT64 TestAddr;
+ MEM_NB_BLOCK *NBPtr;
+ MEM_DATA_STRUCT *MemPtr;
+
+ NBPtr = S3NBPtr->NBPtr;
+ MemPtr = NBPtr->MemPtr;
+ GangedEn = (MemNGetBitFieldNb (NBPtr, BFDctGangEn) == 1) ? TRUE : FALSE;
+
+ // Errata before S3 resume sequence
+
+ // Resume Sequence
+ // 1. Program F2x[1,0]9C_x08[DisAutoComp]=1
+ MemNSwitchDCTNb (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 1);
+
+ // Program F2x[1, 0]94[MemClkFreqVal] = 1.
+ // 2. Wait for F2x[1,0]94[FreqChgInPrg]=0
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ MemNSwitchDCTNb (NBPtr, DCT);
+ if ((MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) && !((DCT == 1) && GangedEn)) {
+ MemNSetBitFieldNb (NBPtr, BFMemClkFreqVal, 1);
+ while (MemNGetBitFieldNb (NBPtr, BFFreqChgInProg) != 0) {}
+ }
+ }
+
+ // Program F2x9C_x08[DisAutoComp]=0
+ MemNSwitchDCTNb (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 0);
+ // BIOS must wait 750 us for the phy compensation engine
+ // to reinitialize.
+ MemFS3Wait10ns (75000, NBPtr->MemPtr);
+
+ // 3. Restore F2x[1,0]90_x00, F2x9C_x0A, and F2x[1,0]9C_x0C
+ // 4. Restore F2x[1,0]9C_x04
+ // Get the register value from the heap.
+ S3NBPtr->MemS3ExitSelfRefReg (NBPtr, &MemPtr->StdHeader);
+
+ // Add a hook here
+ AGESA_TESTPOINT (TpProcMemBeforeAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
+ if (AgesaHookBeforeExitSelfRefresh (0, MemPtr) == AGESA_SUCCESS) {
+ }
+ AGESA_TESTPOINT (TpProcMemAfterAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
+
+ // 5. Set F2x[1,0]90[ExitSelfRef]
+ // 6. Wait for F2x[1,0]90[ExitSelfRef]=0
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ MemNSwitchDCTNb (NBPtr, DCT);
+ if ((MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) && !((DCT == 1) && GangedEn)) {
+ MemNSetBitFieldNb (NBPtr, BFExitSelfRef, 1);
+ while (MemNGetBitFieldNb (NBPtr, BFExitSelfRef) != 0) {}
+ }
+ if ((MemNGetBitFieldNb (NBPtr, BFMemClkFreq) == DDR1333_FREQUENCY) && (NBPtr->IsSupported[CheckDllSpeedUp])) {
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D080F11, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D080F11) | 0x2000));
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D080F10, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D080F10) | 0x2000));
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D088F30, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D088F30) | 0x2000));
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D08C030, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D08C030) | 0x2000));
+ if (DCT == 0) {
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D082F30, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D082F30) | 0x2000));
+ }
+ // NOTE: wait 512 clocks for DLL-relock
+ MemFS3Wait10ns (50000, NBPtr->MemPtr); // wait 500us
+ }
+ }
+
+ // Errata After S3 resume sequence
+ // Errata 350
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ MemNSwitchDCTNb (NBPtr, DCT);
+ if (MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) {
+ if (!((DCT == 1) && GangedEn)) {
+ if (MemNS3GetDummyReadAddr (NBPtr, &TestAddr)) {
+ // Do dummy read
+ Read64Mem8 (TestAddr);
+ // Flush the cache line
+ LibAmdCLFlush (TestAddr, 1);
+ }
+ }
+ MemNSetBitFieldNb (NBPtr, BFErr350, 0x8000);
+ MemFS3Wait10ns (60, NBPtr->MemPtr); // Wait 300ns
+ MemNSetBitFieldNb (NBPtr, BFErr350, 0x0000);
+ MemFS3Wait10ns (400, NBPtr->MemPtr); // Wait 2us
+ }
+ }
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function executes the S3 resume for a node on a client NB
+ *
+ * @param[in,out] *S3NBPtr - Pointer to the S3_MEM_NB_BLOCK
+ * @param[in] NodeID - The Node id of the target die
+ *
+ * @return BOOLEAN
+ * TRUE - This is the correct constructor for the targeted node.
+ * FALSE - This isn't the correct constructor for the targeted node.
+ */
+BOOLEAN
+MemNS3ResumeClientNb (
+ IN OUT S3_MEM_NB_BLOCK *S3NBPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 DCT;
+ MEM_NB_BLOCK *NBPtr;
+ MEM_DATA_STRUCT *MemPtr;
+
+ NBPtr = S3NBPtr->NBPtr;
+ MemPtr = NBPtr->MemPtr;
+
+ // Errata before S3 resume sequence
+
+ // Add a hook here
+ AGESA_TESTPOINT (TpProcMemBeforeAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
+ if (AgesaHookBeforeExitSelfRefresh (0, MemPtr) == AGESA_SUCCESS) {
+ }
+ AGESA_TESTPOINT (TpProcMemAfterAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
+
+ NBPtr->ChangeNbFrequencyWrap (NBPtr, 0);
+ //Override the NB Pstate if needed
+ IDS_OPTION_HOOK (IDS_NB_PSTATE_DIDVID, S3NBPtr->NBPtr, &MemPtr->StdHeader);
+ // Set F2x[1,0]90[ExitSelfRef]
+ // Wait for F2x[1,0]90[ExitSelfRef]=0
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ MemNSwitchDCTNb (NBPtr, DCT);
+ if (MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) {
+ MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 1);
+ MemNSetBitFieldNb (NBPtr, BFExitSelfRef, 1);
+ while (MemNGetBitFieldNb (NBPtr, BFExitSelfRef) != 0) {}
+ MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 0);
+ }
+ }
+
+ // Errata After S3 resume sequence
+ return TRUE;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function executes the S3 resume for a node on a UNB
+ *
+ * @param[in,out] *S3NBPtr - Pointer to the S3_MEM_NB_BLOCK
+ * @param[in] NodeID - The Node id of the target die
+ *
+ * @return BOOLEAN
+ * TRUE - This is the correct constructor for the targeted node.
+ * FALSE - This isn't the correct constructor for the targeted node.
+ */
+BOOLEAN
+MemNS3ResumeUNb (
+ IN OUT S3_MEM_NB_BLOCK *S3NBPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 DCT;
+ MEM_NB_BLOCK *NBPtr;
+ MEM_DATA_STRUCT *MemPtr;
+
+ NBPtr = S3NBPtr->NBPtr;
+ MemPtr = NBPtr->MemPtr;
+
+ // Errata before S3 resume sequence
+
+ // Add a hook here
+ AGESA_TESTPOINT (TpProcMemBeforeAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
+ if (AgesaHookBeforeExitSelfRefresh (0, MemPtr) == AGESA_SUCCESS) {
+ }
+ AGESA_TESTPOINT (TpProcMemAfterAgesaHookBeforeExitSelfRef, &MemPtr->StdHeader);
+
+ //Override the NB Pstate if needed
+ IDS_OPTION_HOOK (IDS_NB_PSTATE_DIDVID, S3NBPtr->NBPtr, &MemPtr->StdHeader);
+ // Set F2x[1,0]90[ExitSelfRef]
+ // Wait for F2x[1,0]90[ExitSelfRef]=0
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ MemNSwitchDCTNb (NBPtr, DCT);
+ if (MemNGetBitFieldNb (NBPtr, BFDisDramInterface) == 0) {
+ MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 1);
+ MemNSetBitFieldNb (NBPtr, BFExitSelfRef, 1);
+ while (MemNGetBitFieldNb (NBPtr, BFExitSelfRef) != 0) {}
+ if (NBPtr->IsSupported[SetDllShutDown]) {
+ MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 0);
+ }
+ }
+ }
+
+ // Errata After S3 resume sequence
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns the conditional PCI device mask
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in, out] *DescriptPtr - Pointer to DESCRIPTOR_GROUP
+ * @return none
+ */
+VOID
+MemNS3GetConPCIMaskNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT DESCRIPTOR_GROUP *DescriptPtr
+ )
+{
+ BIT_FIELD_NAME bitfield;
+ UINT32 RegVal;
+ UINT8 DCT;
+ UINT8 DimmMask;
+ UINT8 BadDimmMask;
+ UINT8 DctGangEn;
+ BOOLEAN IsDDR3;
+
+ IsDDR3 = FALSE;
+ DimmMask = 0;
+ BadDimmMask = 0;
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ NBPtr->SwitchDCT (NBPtr, DCT);
+ if (MemNGetBitFieldNb (NBPtr, BFMemClkFreqVal)) {
+ if (MemNGetBitFieldNb (NBPtr, BFDdr3Mode) == 1) {
+ IsDDR3 = TRUE;
+ }
+ for (bitfield = BFCSBaseAddr0Reg; bitfield <= BFCSBaseAddr7Reg; bitfield ++) {
+ RegVal = MemNGetBitFieldNb (NBPtr, bitfield);
+ if (RegVal & 0x3) {
+ DimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) >> 1) << 1) + DCT));
+ } else if (RegVal & 0x4) {
+ BadDimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) >> 1) << 1) + DCT));
+ }
+ }
+ }
+ }
+
+ NBPtr->SwitchDCT (NBPtr, 0);
+ DctGangEn = (UINT8) MemNGetBitFieldNb (NBPtr, BFDctGangEn);
+ // Set channel mask
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 = 0;
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 = 0;
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ if (DimmMask & (0x55 << DCT)) {
+ // Set mask before exit self refresh
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= 1 << DCT;
+ // Set mask after exit self refresh
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= 1 << DCT;
+ // Set DDR3 mask if Dimms present are DDR3
+ if (IsDDR3) {
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= (DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 << 4);
+ }
+ } else if (BadDimmMask & (0x55 << DCT)) {
+ // Need to save function 2 registers for bad dimm
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= 1 << DCT;
+ }
+ }
+
+ // Set dimm mask
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask2 = DimmMask;
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 = DimmMask;
+ if (DctGangEn) {
+ // Need to set channel mask bit to 1 on DCT1 in ganged mode as some registers
+ // need to be restored on both channels in ganged mode
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= 2;
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= 2;
+ if (IsDDR3) {
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= (2 << 4);
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= (2 << 4);
+ }
+ // Before exit self refresh, do not copy dimm mask to DCT1 as registers restored
+ // in that time frame don't care about individual dimm population. We want to
+ // skip registers that are not needed to be restored for DCT1 in ganged mode.
+ //
+ // After exit self refresh, training registers will be restored and will only be
+ // restored for slots which have dimms on it. So dimm mask needs to be copied to DCT1.
+ //
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 |= DimmMask << 1;
+ }
+
+ // Adjust the mask if there is no dimm on the node
+ if ((DescriptPtr->CPCIDevice[PRESELFREF].Mask2 == 0) &&
+ (DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 == 0)) {
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 = DescriptPtr->CPCIDevice[PRESELFREF].Mask2 = NODE_WITHOUT_DIMM_MASK;
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 = DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 = NODE_WITHOUT_DIMM_MASK;
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns the conditional PCI device mask
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in, out] *DescriptPtr - Pointer to DESCRIPTOR_GROUP
+ * @return none
+ */
+VOID
+MemNS3GetConPCIMaskUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT DESCRIPTOR_GROUP *DescriptPtr
+ )
+{
+ BIT_FIELD_NAME bitfield;
+ UINT32 RegVal;
+ UINT8 DCT;
+ UINT8 DimmMask;
+ UINT8 BadDimmMask;
+ UINT8 NbPsCap;
+
+ DimmMask = 0;
+ BadDimmMask = 0;
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ MemNSwitchDCTNb (NBPtr, DCT);
+ if (MemNGetBitFieldNb (NBPtr, BFMemClkFreqVal)) {
+ for (bitfield = BFCSBaseAddr0Reg; bitfield <= BFCSBaseAddr7Reg; bitfield ++) {
+ RegVal = MemNGetBitFieldNb (NBPtr, bitfield);
+ if (RegVal & 0x1) {
+ DimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) >> 1) << 1) + DCT));
+ } else if (RegVal & 0x4) {
+ BadDimmMask |= (UINT8) (1 << ((((bitfield - BFCSBaseAddr0Reg) >> 1) << 1) + DCT));
+ }
+ }
+ }
+ }
+ // Check if the system is capable of doing NB Pstate change
+ NbPsCap = (UINT8) MemNGetBitFieldNb (NBPtr, BFNbPstateDis);
+
+ MemNSwitchDCTNb (NBPtr, 0);
+ // Set channel mask
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 = 0;
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 = 0;
+ for (DCT = 0; DCT < NBPtr->DctCount; DCT ++) {
+ if (DimmMask & (0x55 << DCT)) {
+ // Set mask before exit self refresh
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= ((NbPsCap == 0) ? 5 : 1) << DCT;
+ // Set mask after exit self refresh
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= 1 << DCT;
+ // Set DDR3 mask if Dimms present are DDR3
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 |= (DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 << 4);
+ } else if (BadDimmMask & (0x55 << DCT)) {
+ // Need to save function 2 registers for bad dimm
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 |= 1 << DCT;
+ }
+ }
+
+ // Set dimm mask
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask2 = DimmMask;
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 = DimmMask;
+
+ // Adjust the mask if there is no dimm on the node
+ if ((DescriptPtr->CPCIDevice[PRESELFREF].Mask2 == 0) &&
+ (DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 == 0)) {
+ DescriptPtr->CPCIDevice[PRESELFREF].Mask1 = DescriptPtr->CPCIDevice[PRESELFREF].Mask2 = NODE_WITHOUT_DIMM_MASK;
+ DescriptPtr->CPCIDevice[POSTSELFREF].Mask1 = DescriptPtr->CPCIDevice[POSTSELFREF].Mask2 = NODE_WITHOUT_DIMM_MASK;
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function read the value of CSR register.
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in] *Value - Pointer to the value be read.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3GetCSRNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT32 ExtendOffset;
+ UINT32 ValueRead;
+ UINT8 DataPort;
+
+ ValueRead = 0;
+ ExtendOffset = Address.Address.Register;
+ if (ExtendOffset & 0x800) {
+ Address.Address.Register = 0xF0;
+ DataPort = 0xF4;
+ } else {
+ Address.Address.Register = 0x98;
+ DataPort = 0x9C;
+ }
+ if (ExtendOffset & 0x400) {
+ Address.Address.Register |= 0x100;
+ }
+ ExtendOffset &= 0x3FF;
+ LibAmdPciWrite (AccessS3SaveWidth32, Address, &ExtendOffset, ConfigPtr);
+ while (((ValueRead >> 31) & 1) == 0) {
+ LibAmdPciRead (AccessS3SaveWidth32, Address, &ValueRead, ConfigPtr);
+ }
+ Address.Address.Register = (Address.Address.Register & 0xF00) | DataPort;
+ LibAmdPciRead (AccessWidth, Address, Value, ConfigPtr);
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function write to a CSR register
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value be read.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3SetCSRNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT32 ExtendOffset;
+ UINT32 ValueRead;
+ UINT32 ValueWrite;
+ UINT8 DataOffset;
+
+ ValueRead = 0;
+ ExtendOffset = Address.Address.Register;
+ // Check the flag and see the type of the access
+ if (ExtendOffset & 0x800) {
+ Address.Address.Register = 0xF4;
+ DataOffset = 0xF0;
+ } else {
+ Address.Address.Register = 0x9C;
+ DataOffset = 0x98;
+ }
+ if (ExtendOffset & 0x400) {
+ Address.Address.Register |= 0x100;
+ }
+ ExtendOffset &= 0x3FF;
+ ExtendOffset |= 0x40000000;
+ switch (AccessWidth) {
+ case AccessS3SaveWidth8:
+ ValueWrite = *(UINT8 *) Value;
+ break;
+ case AccessS3SaveWidth16:
+ ValueWrite = *(UINT16 *) Value;
+ break;
+ case AccessS3SaveWidth32:
+ ValueWrite = *(UINT32 *) Value;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ LibAmdPciWrite (AccessS3SaveWidth32, Address, &ValueWrite, ConfigPtr);
+ Address.Address.Register = (Address.Address.Register & 0xF00) | DataOffset;
+ LibAmdPciWrite (AccessS3SaveWidth32, Address, &ExtendOffset, ConfigPtr);
+ while (((ValueRead >> 31) & 1) == 0) {
+ LibAmdPciRead (AccessS3SaveWidth32, Address, &ValueRead, ConfigPtr);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function reads register bitfield
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value be read.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3GetBitFieldNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ MemNS3GetSetBitField (AccessWidth, Address, FALSE, Value, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function writes register bitfield
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3SetBitFieldNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ MemNS3GetSetBitField (AccessWidth, Address, TRUE, Value, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function restores scrubber base register
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Node - The Node id of the target die
+ *
+ */
+VOID
+MemNS3RestoreScrubNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Node
+ )
+{
+ UINT32 ScrubAddrRJ16;
+
+ ScrubAddrRJ16 = (MemNGetBitFieldNb (NBPtr, BFDramBaseReg0 + Node) & 0xFFFF0000) >> 8;
+ ScrubAddrRJ16 |= MemNGetBitFieldNb (NBPtr, BFDramBaseHiReg0 + Node) << 24;
+ MemNSetBitFieldNb (NBPtr, BFScrubAddrLoReg, ScrubAddrRJ16 << 16);
+ MemNSetBitFieldNb (NBPtr, BFScrubAddrHiReg, ScrubAddrRJ16 >> 16);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function disable NB Pstate Debug.
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3DisNbPsDbgNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT32 RegValue;
+
+ LibAmdPciRead (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
+ // Clear NbPsDbgEn and NbPsCsrAccSel
+ if ((RegValue & 0xC0000000) != 0) {
+ RegValue &= 0x3FFFFFFF;
+ LibAmdPciWrite (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function that enable NB Pstate debug register to allow access to NB Pstate
+ * 1 registers without actually changing NB Pstate.
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3EnNbPsDbg1Nb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT32 RegValue;
+
+ LibAmdPciRead (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
+ // Set NbPsDbgEn to 1 and NbPsCsrAccSel to 1
+ if ((RegValue & 0xC0000000) != 0xC0000000) {
+ RegValue = (*(UINT32 *)Value & 0x3FFFFFFF) | 0xC0000000;
+ LibAmdPciWrite (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets bit 31 [DynModeChange] of F2x9C_xB
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3SetDynModeChangeNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT32 RegValue;
+
+ RegValue = 0x80000000;
+ IDS_SKIP_HOOK (IDS_BEFORE_S3_SPECIAL, &Address, ConfigPtr) {
+ MemNS3SetCSRNb (AccessS3SaveWidth32, Address, &RegValue, ConfigPtr);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function does the channel disable sequence
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3DisableChannelNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ LOCATE_HEAP_PTR LocateBufferPtr;
+ S3_MEM_NB_BLOCK *S3NBPtr;
+ UINT32 RegValue;
+ UINT8 Die;
+
+ // See which Node should be accessed
+ Die = (UINT8) (Address.Address.Device - 24);
+
+ LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
+ if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
+ S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
+ NBPtr = S3NBPtr[Die].NBPtr;
+
+ // Function field contains the DCT number
+ NBPtr->SwitchDCT (NBPtr, (UINT8) Address.Address.Function);
+ RegValue = MemNGetBitFieldNb (NBPtr, BFCKETri);
+ // if CKETri is 0b11, this channel is disabled
+ if (RegValue == 3) {
+ //Wait for 24 MEMCLKs, which is 60ns under 400MHz
+ MemFS3Wait10ns (6, NBPtr->MemPtr);
+ MemNSetBitFieldNb (NBPtr, BFMemClkDis, 0xFF);
+ MemNSetBitFieldNb (NBPtr, BFDisDramInterface, 1);
+ MemNSetBitFieldNb (NBPtr, BFDramPhyStatusReg, 0x80800000);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function disables auto compensation.
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3SetDisAutoCompUnb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT16 RegValue;
+
+ MemNS3GetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
+ RegValue = 0x6000 | RegValue;
+ MemNS3SetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function retores Pre Driver Calibration with pre driver calibration code
+ * code valid bit set.
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3SetPreDriverCalUnb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT16 RegValue;
+
+ RegValue = 0x8000 | *(UINT16 *) Value;
+ MemNS3SetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function is used by families that use a separate DctCfgSel bit to
+ * select the current DCT which will be accessed by function 2.
+ * NOTE: This function must be called BEFORE the NBPtr->Dct variable is
+ * updated.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *Dct - Pointer to ID of the target DCT
+ *
+ */
+
+BOOLEAN
+MemNS3DctCfgSelectUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN VOID *Dct
+ )
+{
+ // Set the DctCfgSel to new DCT
+ //
+ MemNSetBitFieldNb (NBPtr, BFDctCfgSel, *(UINT8*)Dct);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function write to a register that has one copy for each NB Pstate
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value be read.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3GetNBPStateDepRegUnb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT8 NBPstate;
+ UINT8 TempValue;
+ UINT8 Dct;
+ UINT32 Temp;
+
+ Temp = Address.Address.Register;
+ NBPstate = (UINT8) (Temp >> 10);
+ Dct = (UINT8) Address.Address.Function;
+ Temp &= 0x3FF;
+
+ // Switch Dct
+ // Function field contains DCT value
+ Address.Address.Function = FUNC_1;
+ Address.Address.Register = 0x10C;
+ LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+ TempValue = (TempValue & 0xC8) | ((NBPstate << 4) | Dct);
+ LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+
+ Address.Address.Function = FUNC_2;
+ Address.Address.Register = Temp;
+ LibAmdPciRead (AccessWidth, Address, Value, ConfigPtr);
+
+ Address.Address.Function = FUNC_1;
+ Address.Address.Register = 0x10C;
+ TempValue = 0;
+ LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function write to a register that has one copy for each NB Pstate
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value be read.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3SetNBPStateDepRegUnb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT8 NBPstate;
+ UINT8 TempValue;
+ UINT8 Dct;
+ UINT32 Temp;
+
+ Temp = Address.Address.Register;
+ NBPstate = (UINT8) (Temp >> 10);
+ Dct = (UINT8) Address.Address.Function;
+ Temp &= 0x3FF;
+
+ // Switch Dct
+ // Function field contains DCT value
+ Address.Address.Function = FUNC_1;
+ Address.Address.Register = 0x10C;
+ LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+ TempValue = (TempValue & 0xCE) | ((NBPstate << 4) | Dct);
+ LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+
+ Address.Address.Function = FUNC_2;
+ Address.Address.Register = Temp;
+ LibAmdPciWrite (AccessWidth, Address, Value, ConfigPtr);
+
+ Address.Address.Function = FUNC_1;
+ Address.Address.Register = 0x10C;
+ TempValue = 0;
+ LibAmdPciWrite (AccessS3SaveWidth32, Address, &TempValue, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function read the value of Function 2 PCI register.
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the NB register in PCI_ADDR format.
+ * @param[in] *Value - Pointer to the value be read.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3SaveNBRegiserUnb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT8 TempValue;
+ UINT8 Dct;
+ UINT32 Temp;
+
+ Temp = Address.Address.Register;
+ Dct = (UINT8) Address.Address.Function;
+
+ // Switch Dct
+ // Function field contains DCT value
+ Address.Address.Function = FUNC_1;
+ Address.Address.Register = 0x10C;
+ LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+ TempValue = (TempValue & 0xFE) | Dct;
+ LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+
+ Address.Address.Register = Temp;
+ Address.Address.Function = FUNC_2;
+ LibAmdPciRead (AccessWidth, Address, Value, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function set the value of Function 2 PCI register.
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the NB register in PCI_ADDR format.
+ * @param[in] *Value - Pointer to the value be write.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3RestoreNBRegiserUnb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT8 TempValue;
+ UINT8 Dct;
+ UINT32 Temp;
+
+ Temp = Address.Address.Register;
+ Dct = (UINT8) Address.Address.Function;
+
+ // Switch Dct
+ // Function field contains DCT value
+ Address.Address.Function = FUNC_1;
+ Address.Address.Register = 0x10C;
+ LibAmdPciRead (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+ TempValue = (TempValue & 0xFE) | Dct;
+ LibAmdPciWrite (AccessS3SaveWidth8, Address, &TempValue, ConfigPtr);
+
+ Address.Address.Register = Temp;
+ Address.Address.Function = FUNC_2;
+ LibAmdPciWrite (AccessWidth, Address, Value, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets MemClkFreqVal bit.
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3SetMemClkFreqValUnb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT32 TempValue;
+
+ // 1. Program MemClkFreqVal = 1
+ MemNS3SaveNBRegiserUnb (AccessWidth, Address, &TempValue, ConfigPtr);
+ TempValue |= 0x80;
+ MemNS3RestoreNBRegiserUnb (AccessWidth, Address, &TempValue, ConfigPtr);
+
+ // 2. Wait for FreqChgInPrg = 0
+ MemNS3SaveNBRegiserUnb (AccessWidth, Address, &TempValue, ConfigPtr);
+ while ((TempValue & 0x200000) != 0) {
+ MemNS3SaveNBRegiserUnb (AccessWidth, Address, &TempValue, ConfigPtr);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function changes memory Pstate context
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format. Target MemPState is in
+ * Address.Address.Register.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+VOID
+MemNS3ChangeMemPStateContextNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ LOCATE_HEAP_PTR LocateBufferPtr;
+ S3_MEM_NB_BLOCK *S3NBPtr;
+ UINT8 Die;
+
+ IDS_SKIP_HOOK (IDS_BEFORE_S3_SPECIAL, &Address, ConfigPtr) {
+ // See which Node should be accessed
+ Die = (UINT8) (Address.Address.Device - 24);
+
+ LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
+ if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
+ S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
+ NBPtr = S3NBPtr[Die].NBPtr;
+ MemNChangeMemPStateContextNb (NBPtr, Address.Address.Register);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function retores Phy Clk DLL fine delay
+ *
+ * @param[in] AccessWidth - Access width of the register.
+ * @param[in] Address - address in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value to be written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3SetPhyClkDllFineClientNb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT16 RegValue;
+
+ RegValue = 0x4000 | *(UINT16 *) Value;
+ MemNS3SetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
+ RegValue = 0xBFFF & *(UINT16 *) Value;
+ MemNS3SetBitFieldNb (AccessS3SaveWidth16, Address, &RegValue, ConfigPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function forces NBPstate to NBP0
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value be read or written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3ForceNBP0Unb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ UINT8 NbPstateMaxVal;
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+ MEM_NB_BLOCK *NBPtr;
+ LOCATE_HEAP_PTR LocateBufferPtr;
+ S3_MEM_NB_BLOCK *S3NBPtr;
+
+ IDS_SKIP_HOOK (IDS_BEFORE_S3_SPECIAL, &Address, ConfigPtr) {
+ LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
+ if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
+ S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
+ NBPtr = S3NBPtr[0].NBPtr;
+
+ if (MemNGetBitFieldNb (NBPtr, BFCurNbPstate) != 0) {
+
+ NBPtr->NbPsCtlReg = MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg);
+
+ // If current NBPstate is already in NBPstateLo, do not do transition to NBPstateLo.
+ if (MemNGetBitFieldNb (NBPtr, BFNbPstateLo) != MemNGetBitFieldNb (NBPtr, BFCurNbPstate)) {
+ // 2.Program D18F5x170 to transition the NB P-state:
+ // NbPstateLo = NbPstateMaxVal. (HW requires an intermediate transition to low)
+ // SwNbPstateLoDis = NbPstateDisOnP0 = NbPstateThreshold = 0.
+ NbPstateMaxVal = (UINT8) MemNGetBitFieldNb (NBPtr, BFNbPstateMaxVal);
+ MemNSetBitFieldNb (NBPtr, BFNbPstateLo, NbPstateMaxVal);
+ MemNSetBitFieldNb (NBPtr, BFNbPstateCtlReg, MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg) & 0xFFFF91FF);
+ // 3.Wait for D18F5x174[CurNbPstate] to equal NbPstateLo.
+ while (MemNGetBitFieldNb (NBPtr, BFCurNbPstate) != NbPstateMaxVal) {}
+ }
+ // 4.Program D18F5x170 to force the NB P-state:
+ // NbPstateHi = target NB P-state.
+ // SwNbPstateLoDis = 1 (triggers the transition)
+ MemNSetBitFieldNb (NBPtr, BFNbPstateHi, 0);
+ MemNSetBitFieldNb (NBPtr, BFSwNbPstateLoDis, 1);
+ // 5.Wait for D18F5x174[CurNbPstate] to equal the target NB P-state.
+ while (MemNGetBitFieldNb (NBPtr, BFCurNbPstate) != 0) {}
+
+ // Update TSC rate
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &NBPtr->MemPtr->StdHeader);
+ FamilySpecificServices->GetTscRate (FamilySpecificServices, &NBPtr->MemPtr->TscRate, &NBPtr->MemPtr->StdHeader);
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function releases NBPState force
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in, out] *Value - Pointer to the value be read or written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+MemNS3ReleaseNBPSUnb (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ LOCATE_HEAP_PTR LocateBufferPtr;
+ S3_MEM_NB_BLOCK *S3NBPtr;
+
+ IDS_SKIP_HOOK (IDS_BEFORE_S3_SPECIAL, &Address, ConfigPtr) {
+ LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
+ if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
+ S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
+ NBPtr = S3NBPtr[0].NBPtr;
+
+ if (NBPtr->NbPsCtlReg != 0) {
+ // 6. Restore the initial D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0] values.
+ MemNSetBitFieldNb (NBPtr, BFNbPstateCtlReg, (MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg) & 0xFFFF9FFF) | (NBPtr->NbPsCtlReg & 0x6000));
+ // 7. Restore the initial D18F5x170[NbPstateThreshold, NbPstateHi] values.
+ MemNSetBitFieldNb (NBPtr, BFNbPstateCtlReg, (MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg) & 0xFFFFF13F) | (NBPtr->NbPsCtlReg & 0x0EC0));
+ // 8. Restore the initial D18F5x170[NbPstateLo] values.
+ MemNSetBitFieldNb (NBPtr, BFNbPstateLo, (NBPtr->NbPsCtlReg >> 3) & 3);
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+}
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------*/
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function reads and writes register bitfield
+ *
+ * @param[in] AccessWidth - Access width of the register
+ * @param[in] Address - address of the CSR register in PCI_ADDR format.
+ * @param[in] IsSet - if this is a register read or write
+ * @param[in, out] *Value - Pointer to the value be read or written.
+ * @param[in, out] *ConfigPtr - Pointer to Config handle.
+ * @return none
+ */
+VOID
+STATIC
+MemNS3GetSetBitField (
+ IN ACCESS_WIDTH AccessWidth,
+ IN PCI_ADDR Address,
+ IN BOOLEAN IsSet,
+ IN OUT VOID *Value,
+ IN OUT VOID *ConfigPtr
+ )
+{
+ BIT_FIELD_NAME BitField;
+ MEM_NB_BLOCK *NBPtr;
+ LOCATE_HEAP_PTR LocateBufferPtr;
+ S3_MEM_NB_BLOCK *S3NBPtr;
+ UINT32 RegValue;
+ UINT8 Die;
+
+ RegValue = 0;
+ // See which Node should be accessed
+ Die = (UINT8) (Address.Address.Device - 24);
+
+ LocateBufferPtr.BufferHandle = AMD_MEM_S3_NB_HANDLE;
+ if (HeapLocateBuffer (&LocateBufferPtr, ConfigPtr) == AGESA_SUCCESS) {
+ S3NBPtr = (S3_MEM_NB_BLOCK *) LocateBufferPtr.BufferPtr;
+ NBPtr = S3NBPtr[Die].NBPtr;
+
+ // Function field contains the DCT number
+ NBPtr->SwitchDCT (NBPtr, (UINT8) Address.Address.Function);
+
+ // Get the bitfield name to be accessed
+ // Register field contains the bitfield name
+ BitField = (BIT_FIELD_NAME) Address.Address.Register;
+
+ if (IsSet) {
+ switch (AccessWidth) {
+ case AccessS3SaveWidth8:
+ RegValue = *(UINT8 *) Value;
+ break;
+ case AccessS3SaveWidth16:
+ RegValue = *(UINT16 *) Value;
+ break;
+ case AccessS3SaveWidth32:
+ RegValue = *(UINT32 *) Value;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ MemNSetBitFieldNb (NBPtr, BitField, RegValue);
+ } else {
+ RegValue = MemNGetBitFieldNb (NBPtr, BitField);
+
+ switch (AccessWidth) {
+ case AccessS3SaveWidth8:
+ *(UINT8 *) Value = (UINT8) RegValue;
+ break;
+ case AccessS3SaveWidth16:
+ *(UINT16 *) Value = (UINT16) RegValue;
+ break;
+ case AccessS3SaveWidth32:
+ *(UINT32 *) Value = RegValue;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the dummy read address for a channel of a node.
+ *
+ * @param[in, out] *NBPtr - Pointer to northbridge block
+ * @param[out] *TestAddr - Pointer to the test address
+ *
+ * @retval TRUE - Dummy read address can be found
+ * @retval FALSE - Dummy read address cannot be found
+ *
+ */
+BOOLEAN
+STATIC
+MemNS3GetDummyReadAddr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ OUT UINT64 *TestAddr
+ )
+{
+ BOOLEAN DctSelIntlvEn;
+ UINT8 DramIntlvEn;
+ UINT8 DctSelIntlvAddr;
+ UINT8 IntLvRgnBaseAddr;
+ UINT8 IntLvRgnLmtAddr;
+ UINT8 IntLvRgnSize;
+ UINT32 DctSelBaseAddr;
+ UINT64 TOM;
+ BOOLEAN AddrFound;
+
+ AddrFound = TRUE;
+ // Check if Node interleaving is enabled
+ DramIntlvEn = (UINT8) MemNGetBitFieldNb (NBPtr, BFDramIntlvEn);
+ if (DramIntlvEn != 0) {
+ // Set the address bits that identify the node
+ *TestAddr = (UINT64) MemNGetBitFieldNb (NBPtr, BFDramIntlvSel) << 12;
+ } else {
+ *TestAddr = (UINT64) MemNGetBitFieldNb (NBPtr, BFDramBaseAddr) << 27;
+ }
+
+ // Check if channel interleaving is enabled
+ DctSelIntlvEn = (BOOLEAN) MemNGetBitFieldNb (NBPtr, BFDctSelIntLvEn);
+ DctSelBaseAddr = MemNGetBitFieldNb (NBPtr, BFDctSelBaseAddr);
+ if (!DctSelIntlvEn) {
+ if ((NBPtr->Dct == 1) && ((UINT8) MemNGetBitFieldNb (NBPtr, BFDctSelHi) == 1)) {
+ *TestAddr = ((UINT64) DctSelBaseAddr << 27) | (*TestAddr & 0xFFFFFFF);
+ }
+ } else {
+ DctSelIntlvAddr = (UINT8) MemNGetBitFieldNb (NBPtr, BFDctSelIntLvAddr);
+ // Set the address bits that identify the channel
+ if ((DctSelIntlvAddr == 0) || (DctSelIntlvAddr == 2)) {
+ *TestAddr |= (UINT64) NBPtr->Dct << 6;
+ } else if (DctSelIntlvAddr == 1) {
+ *TestAddr |= (UINT64) NBPtr->Dct << (12 + LibAmdBitScanReverse (DramIntlvEn + 1));
+ } else if (DctSelIntlvAddr == 3) {
+ *TestAddr |= (UINT64) NBPtr->Dct << 9;
+ }
+ }
+ // Adding 2M to avoid conflict
+ *TestAddr += 0x200000;
+
+ // If memory hoisting is disabled, the address can fall into MMIO area
+ // Need to find an address out of MMIO area but belongs to the channel
+ // If the whole channel is in MMIO, then do not do dummy read.
+ //
+ LibAmdMsrRead (TOP_MEM, &TOM, &NBPtr->MemPtr->StdHeader);
+ if ((*TestAddr >= TOM) && (*TestAddr < ((UINT64) _4GB_RJ16 << 16))) {
+ if ((NBPtr->Dct == 1) && ((UINT8) MemNGetBitFieldNb (NBPtr, BFDctSelHi) == 1)) {
+ // This is the DCT that goes to high address range
+ if (DctSelBaseAddr >= (_4GB_RJ16 >> (27 - 16))) {
+ // When DctSelBaseAddr is higher than 4G, choose DctSelBaseAddr as the dummy read addr
+ if (DctSelIntlvEn) {
+ *TestAddr = ((UINT64) DctSelBaseAddr << 27) | (*TestAddr & 0xFFFFFFF);
+ }
+ } else if (MemNGetBitFieldNb (NBPtr, BFDramLimitAddr) > (UINT32) (_4GB_RJ16 >> (27 - 16))) {
+ // if DctSelBase is smaller than 4G, but Dram limit is larger than 4G, then choose 4G as
+ // dummy read address
+ *TestAddr = ((UINT64) _4GB_RJ16 << 16) | (*TestAddr & 0xFFFFFF);
+ } else {
+ AddrFound = FALSE;
+ }
+ } else {
+ // This is the DCT that only goes to low address range
+ if (DctSelBaseAddr > (_4GB_RJ16 >> (27 - 16))) {
+ // When DctSelBaseAddr is larger than 4G, choose 4G as the dummy read address
+ // Keep the lower bits for node and channel selection
+ *TestAddr = ((UINT64) _4GB_RJ16 << 16) | (*TestAddr & 0xFFFFFF);
+ } else {
+ AddrFound = FALSE;
+ }
+ }
+ }
+
+ // Interleaved Swap Region handling
+ if ((BOOLEAN) MemNGetBitFieldNb (NBPtr, BFIntLvRgnSwapEn)) {
+ IntLvRgnBaseAddr = (UINT8) MemNGetBitFieldNb (NBPtr, BFIntLvRgnBaseAddr);
+ IntLvRgnLmtAddr = (UINT8) MemNGetBitFieldNb (NBPtr, BFIntLvRgnLmtAddr);
+ IntLvRgnSize = (UINT8) MemNGetBitFieldNb (NBPtr, BFIntLvRgnSize);
+ ASSERT (IntLvRgnSize == (IntLvRgnLmtAddr - IntLvRgnBaseAddr + 1));
+ if (((*TestAddr >> 34) == 0) &&
+ ((((*TestAddr >> 27) >= IntLvRgnBaseAddr) && ((*TestAddr >> 27) <= IntLvRgnLmtAddr))
+ || ((*TestAddr >> 27) < IntLvRgnSize))) {
+ *TestAddr ^= (UINT64) IntLvRgnBaseAddr << 27;
+ }
+ }
+
+ return AddrFound;
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mndct.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mndct.c
new file mode 100644
index 0000000000..48020c4aaa
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mndct.c
@@ -0,0 +1,3613 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mndct.c
+ *
+ * Common Northbridge DCT support
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB)
+ * @e \$Revision: 64574 $ @e \$Date: 2012-01-25 01:01:51 -0600 (Wed, 25 Jan 2012) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mu.h"
+#include "mftds.h"
+#include "merrhdl.h"
+#include "cpuFamilyTranslation.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_MEM_NB_MNDCT_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define UNUSED_CLK 4
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemNAfterStitchMemNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+UINT8
+MemNGet1KTFawTkNb (
+ IN UINT8 k
+ );
+
+UINT8
+MemNGet2KTFawTkNb (
+ IN UINT8 k
+ );
+
+VOID
+STATIC
+MemNQuarterMemClk2NClkNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT UINT16 *SubTotalPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+extern BUILD_OPT_CFG UserOptions;
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function combines all the memory into a contiguous map.
+ * Requires that Mask values for each bank be programmed first and that
+ * the chip-select population indicator is correctly set.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - An Error value lower than AGESA_FATAL may have occurred
+ * @return FALSE - An Error value greater than or equal to AGESA_FATAL may have occurred
+ */
+
+BOOLEAN
+MemNStitchMemoryNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ BOOLEAN DSpareEn;
+ UINT32 NxtCSBase;
+ UINT32 CurCSBase;
+ UINT32 CsSize;
+ UINT32 BiggestBank;
+ UINT8 p;
+ UINT8 q;
+ UINT8 BiggestDimm;
+ MEM_PARAMETER_STRUCT *RefPtr;
+ DIE_STRUCT *MCTPtr;
+ DCT_STRUCT *DCTPtr;
+ RefPtr = NBPtr->RefPtr;
+ MCTPtr = NBPtr->MCTPtr;
+ DCTPtr = NBPtr->DCTPtr;
+ DSpareEn = FALSE;
+ if (NBPtr->IsSupported[SetSpareEn]) {
+ DSpareEn = FALSE;
+ if (RefPtr->GStatus[GsbEnDIMMSpareNW]) {
+ DSpareEn = TRUE;
+ }
+ }
+
+ DCTPtr->Timings.CsEnabled = 0;
+ NxtCSBase = 0;
+ for (p = 0; p < MAX_CS_PER_CHANNEL; p++) {
+ BiggestBank = 0;
+ BiggestDimm = 0;
+ for (q = 0; q < MAX_CS_PER_CHANNEL; q++) {
+ if (((DCTPtr->Timings.CsPresent & ~DCTPtr->Timings.CsTestFail) & ((UINT16)1 << q)) != 0) {
+ if ((MemNGetBitFieldNb (NBPtr, BFCSBaseAddr0Reg + q) & 7) == 0) {
+ // (CSEnable|Spare==1)bank is not enabled yet
+ CsSize = MemNGetBitFieldNb (NBPtr, BFCSMask0Reg + (q >> 1));
+ if (CsSize != 0) {
+ CsSize += ((UINT32)1 << 19);
+ CsSize &= 0xFFF80000;
+ }
+ if (CsSize > BiggestBank) {
+ BiggestBank = CsSize;
+ BiggestDimm = q;
+ }
+ }
+ }
+ }
+
+ if (BiggestBank != 0) {
+ CurCSBase = NxtCSBase;
+ if (NBPtr->IsSupported[CheckSpareEn]) {
+ if (DSpareEn) {
+ CurCSBase = ((UINT32)1 << BFSpare);
+ DSpareEn = FALSE;
+ } else {
+ CurCSBase |= ((UINT32)1 << BFCSEnable);
+ NxtCSBase += BiggestBank;
+ }
+ } else {
+ CurCSBase |= ((UINT32)1 << BFCSEnable);
+ NxtCSBase += BiggestBank;
+ }
+ if ((BiggestDimm & 1) != 0) {
+ if (!(MCTPtr->Status[SbLrdimms])) {
+ // For LRDIMMS, On Dimm Mirroring is enabled after SDI
+ if ((DCTPtr->Timings.DimmMirrorPresent & (1 << (BiggestDimm >> 1))) != 0) {
+ CurCSBase |= ((UINT32)1 << BFOnDimmMirror);
+ }
+ }
+ }
+ MemNSetBitFieldNb (NBPtr, BFCSBaseAddr0Reg + BiggestDimm, CurCSBase);
+ DCTPtr->Timings.CsEnabled |= (1 << BiggestDimm);
+ }
+ if ((DCTPtr->Timings.CsTestFail & ((UINT16)1 << p)) != 0) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "Node %d Dct %d exclude CS %d\n", NBPtr->Node, NBPtr->Dct, p);
+ MemNSetBitFieldNb (NBPtr, (BFCSBaseAddr0Reg + p), (UINT32)1 << BFTestFail);
+ }
+ }
+
+ if (NxtCSBase != 0) {
+ DCTPtr->Timings.DctMemSize = NxtCSBase >> 8; // Scale base address from [39:8] to [47:16]
+ MemNAfterStitchMemNb (NBPtr);
+ }
+
+ return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * 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_FATAL may have occurred
+ * @return FALSE - An Error value greater than or equal to AGESA_FATAL may have occurred
+ */
+
+BOOLEAN
+MemNPlatformSpecNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST BIT_FIELD_NAME ChipletPDRegs[] = {
+ BFPhyClkConfig0,
+ BFPhyClkConfig3,
+ BFPhyClkConfig1,
+ BFPhyClkConfig2
+ };
+ CONST UINT8 ChipletPDClkDisMap[][2] = {
+ //F2[1, 0]x9C_x0D0F2030 -> F2x[1, 0]88[MemClkDis[1:0]]
+ {0, 1},
+ //F2[1, 0]x9C_x0D0F2330 -> F2x[1, 0]88[MemClkDis[7:6]]
+ {6, 7},
+ //F2x09C_x0D0F2130 -> F2x88[MemClkDis[5:4]]
+ {4, 5},
+ //F2x09C_x0D0F2230 -> F2x88[MemClkDis[3:2]]
+ {2, 3},
+ //F2x19C_x0D0F2130 -> F2x188[MemClkDis[5:2]]
+ {2, 5},
+ //F2x19C_x0D0F2230 -> F2x188[MemClkDis[4:3]]
+ {3, 4}
+ };
+
+ UINT8 MemClkDis;
+ UINT8 i;
+ UINT8 MemoryAllClocks;
+ UINT8 *MemClkDisMap;
+ UINT16 CsPresent;
+ UINT8 RegIndex;
+ UINT8 Cs1;
+ UINT8 Cs2;
+
+ if (!MemNGetPlatformCfgNb (NBPtr)) {
+ IDS_ERROR_TRAP;
+ }
+
+ if (!NBPtr->PsPtr->MemPDoPs (NBPtr)) {
+ IDS_ERROR_TRAP;
+ }
+ MemNProgramPlatformSpecNb (NBPtr);
+
+ MemProcessConditionalOverrides (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr, PSO_ACTION_ODT, ALL_DIMMS);
+
+ if (NBPtr->MCTPtr->GangedMode) {
+ MemNSwitchDCTNb (NBPtr, 1);
+ if (!MemNGetPlatformCfgNb (NBPtr)) {
+ IDS_ERROR_TRAP;
+ }
+ MemNProgramPlatformSpecNb (NBPtr);
+ MemNSwitchDCTNb (NBPtr, 0);
+ }
+
+ //======================================================================
+ // Disable unused MemClk to save power
+ //======================================================================
+ //
+ MemClkDis = 0;
+ MemoryAllClocks = UserOptions.CfgMemoryAllClocksOn;
+ IDS_OPTION_HOOK (IDS_ALL_MEMORY_CLOCK, &MemoryAllClocks, &(NBPtr->MemPtr->StdHeader));
+ if (!MemoryAllClocks) {
+ // Special Jedec SPD diagnostic bit - "enable all clocks"
+ if (!NBPtr->MCTPtr->Status[SbDiagClks]) {
+ MemClkDisMap = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MEMCLK_DIS, NBPtr->MCTPtr->SocketId, MemNGetSocketRelativeChannelNb (NBPtr, NBPtr->Dct, 0), 0,
+ &(NBPtr->MCTPtr->LogicalCpuid), &(NBPtr->MemPtr->StdHeader));
+ if (MemClkDisMap == NULL) {
+ MemClkDisMap = NBPtr->ChannelPtr->MemClkDisMap;
+ }
+
+ // Turn off the unused CS clocks
+ CsPresent = NBPtr->DCTPtr->Timings.CsPresent;
+
+ if (NBPtr->IsSupported[CheckMemClkCSPresent]) {
+ if (NBPtr->ChannelPtr->RegDimmPresent != 0) {
+ // All DDR3 RDIMM use only one MEMCLOCK from edge finger to the register
+ // regardless of how many Ranks are on the DIMM (Single, Dual or Quad)
+ CsPresent = (CsPresent | (CsPresent >> 1)) & 0x5555;
+ }
+ }
+ for (i = 0; i < 8; i++) {
+ if ((CsPresent & MemClkDisMap[i]) == 0) {
+ MemClkDis |= (UINT8) (1 << i);
+ }
+ }
+ //Chiplet power down
+ for (RegIndex = 0; RegIndex < GET_SIZE_OF (ChipletPDRegs); RegIndex++) {
+ if ((NBPtr->Dct == 1) && (RegIndex >= 2)) {
+ Cs1 = MemClkDisMap[ChipletPDClkDisMap[RegIndex + 2][0]];
+ Cs2 = MemClkDisMap[ChipletPDClkDisMap[RegIndex + 2][1]];
+ } else {
+ Cs1 = MemClkDisMap[ChipletPDClkDisMap[RegIndex][0]];
+ Cs2 = MemClkDisMap[ChipletPDClkDisMap[RegIndex][1]];
+ }
+ if ((CsPresent & (UINT16) (Cs1 | Cs2)) == 0) {
+ MemNSetBitFieldNb (NBPtr, ChipletPDRegs[RegIndex], (MemNGetBitFieldNb (NBPtr, ChipletPDRegs[RegIndex]) | 0x10));
+ }
+ }
+ }
+ }
+ MemNSetBitFieldNb (NBPtr, BFMemClkDis, MemClkDis);
+
+ AGESA_TESTPOINT (TPProcMemPhyCompensation, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->MemNInitPhyComp (NBPtr);
+
+ MemProcessConditionalOverrides (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr, PSO_ACTION_SLEWRATE, ALL_DIMMS);
+
+ // Program DramTerm for DDR2
+ if ((MemNGetBitFieldNb (NBPtr, BFDdr3Mode)) == 0) {
+ MemNSetBitFieldNb (NBPtr, BFDramTerm, NBPtr->PsPtr->DramTerm);
+ } else {
+ // Dynamic Dynamic DramTerm for DDR3
+ // Dram Term for DDR3 may vary based on chip selects
+ MemNSetBitFieldNb (NBPtr, BFDramTermDyn, NBPtr->PsPtr->DynamicDramTerm);
+ }
+
+ MemFInitTableDrive (NBPtr, MTAfterPlatformSpec);
+
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * 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_FATAL may have occurred
+ * @return FALSE - An Error value greater than or equal to AGESA_FATAL may have occurred
+ */
+
+BOOLEAN
+MemNPlatformSpecUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 MemClkDis;
+ UINT8 i;
+ UINT8 MemoryAllClocks;
+ UINT8 *MemClkDisMap;
+ UINT16 CsPresent;
+
+ if (!MemNGetPlatformCfgNb (NBPtr)) {
+ IDS_ERROR_TRAP;
+ }
+
+ if (!NBPtr->PsPtr->MemPDoPs (NBPtr)) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tDisable DCT%d due to unsupported DIMM configuration\n", NBPtr->Dct);
+ if (!NBPtr->MemPtr->ErrorHandling (NBPtr->MCTPtr, NBPtr->Dct, EXCLUDE_ALL_CHIPSEL, &NBPtr->MemPtr->StdHeader)) {
+ ASSERT (FALSE);
+ }
+ NBPtr->DisableDCT (NBPtr);
+ } else {
+
+ MemNProgramPlatformSpecNb (NBPtr);
+ MemProcessConditionalOverrides (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr, PSO_ACTION_ODT, ALL_DIMMS);
+
+ //======================================================================
+ // Disable unused MemClk to save power
+ //======================================================================
+ //
+ MemClkDis = 0;
+ MemoryAllClocks = UserOptions.CfgMemoryAllClocksOn;
+ IDS_OPTION_HOOK (IDS_ALL_MEMORY_CLOCK, &MemoryAllClocks, &(NBPtr->MemPtr->StdHeader));
+ if (!MemoryAllClocks) {
+ // Special Jedec SPD diagnostic bit - "enable all clocks"
+ if (!NBPtr->MCTPtr->Status[SbDiagClks]) {
+ MemClkDisMap = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MEMCLK_DIS, NBPtr->MCTPtr->SocketId, NBPtr->Dct, 0,
+ &(NBPtr->MCTPtr->LogicalCpuid), &(NBPtr->MemPtr->StdHeader));
+ if (MemClkDisMap == NULL) {
+ MemClkDisMap = NBPtr->ChannelPtr->MemClkDisMap;
+ }
+
+ // Turn off unused clocks
+ CsPresent = NBPtr->DCTPtr->Timings.CsPresent;
+
+ for (i = 0; i < 8; i++) {
+ if ((CsPresent & MemClkDisMap[i]) == 0) {
+ MemClkDis |= (UINT8) (1 << i);
+ }
+ }
+
+ // Turn off unused chiplets
+ for (i = 0; i < 3; i++) {
+ if (((MemClkDis >> (i * 2)) & 0x3) == 0x3) {
+ MemNSetBitFieldNb (NBPtr, BFPhyClkConfig0 + i, 0x0010);
+ }
+ }
+ }
+ }
+ MemNSetBitFieldNb (NBPtr, BFMemClkDis, MemClkDis);
+ MemFInitTableDrive (NBPtr, MTAfterPlatformSpec);
+ }
+
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function disables the DCT and mem clock
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNDisableDCTNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MemNSetBitFieldNb (NBPtr, BFCKETri, 0x03);
+ MemNSetBitFieldNb (NBPtr, BFODTTri, 0x0F);
+ MemNSetBitFieldNb (NBPtr, BFChipSelTri, 0xFF);
+
+ // To maximize power savings when DisDramInterface=1b,
+ // all of the MemClkDis bits should also be set.
+ //
+ MemNSetBitFieldNb (NBPtr, BFMemClkDis, 0xFF);
+ MemNSetBitFieldNb (NBPtr, BFDisDramInterface, 1);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function disables the DCT and mem clock for client NB
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNDisableDCTClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MemNSetBitFieldNb (NBPtr, BFCKETri, 0x03);
+ MemNSetBitFieldNb (NBPtr, BFODTTri, 0x0F);
+ MemNSetBitFieldNb (NBPtr, BFChipSelTri, 0xFF);
+
+ //Wait for 24 MEMCLKs
+ MemNWaitXMemClksNb (NBPtr, 24);
+
+ // To maximize power savings when DisDramInterface=1b,
+ // all of the MemClkDis bits should also be set.
+ //
+ MemNSetBitFieldNb (NBPtr, BFMemClkDis, 0xFF);
+
+ MemNSetBitFieldNb (NBPtr, BFDramPhyStatusReg, 0x80800000);
+
+ MemNSetBitFieldNb (NBPtr, BFDisDramInterface, 1);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function disables the DCT and mem clock for UNB
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNDisableDCTUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MemNSetBitFieldNb (NBPtr, BFExtendedParityEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFParEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFCKETri, 0x0F);
+
+ //Wait for 24 MEMCLKs
+ MemNWaitXMemClksNb (NBPtr, 24);
+
+ // To maximize power savings when DisDramInterface=1b,
+ // all of the MemClkDis bits should also be set.
+ //
+ MemNSetBitFieldNb (NBPtr, BFMemClkDis, 0xFF);
+
+ MemNSetBitFieldNb (NBPtr, BFDisDramInterface, 1);
+
+ if (NBPtr->Dct == 0) {
+ MemNSetBitFieldNb (NBPtr, BFPhyPSMasterChannel, 0x100);
+ }
+
+ // If channel is disabled after dram init, set DisDllShutdownSR
+ if (MemNGetBitFieldNb (NBPtr, BFDramEnabled) == 1) {
+ MemNSetBitFieldNb (NBPtr, BFDisDllShutdownSR, 1);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the DRAM devices on all DCTs at the same time
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNStartupDCTNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ // 1. Ensure F2x[1, 0]9C_x08[DisAutoComp] = 1.
+ // 2. BIOS waits 5 us for the disabling of the compensation engine to complete.
+ // DisAutoComp is still being set since InitPhyComp
+
+ if (NBPtr->MCTPtr->NodeMemSize != 0) {
+ // Init MemClk frequency
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreqVal, 1);
+
+
+ AGESA_TESTPOINT (TpProcMemBeforeDramInit, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->MemNBeforeDramInitNb (NBPtr);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nMemClkFreq: %d MHz\n", NBPtr->DCTPtr->Timings.Speed);
+ AGESA_TESTPOINT (TpProcMemDramInit, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->FeatPtr->DramInit (NBPtr->TechPtr);
+ }
+
+ // 7. Program F2x[1, 0]9C_x08[DisAutoComp] = 0.
+ // 8. BIOS must wait 750 us for the phy compensation engine
+ // to reinitialize.
+ // DisAutoComp will be cleared after DramEnabled turns to 1
+
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the DRAM devices on all DCTs at the same time
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNStartupDCTUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dct;
+ UINT16 FinalPllLockTime;
+
+ if (NBPtr->MCTPtr->NodeMemSize != 0) {
+ // Update NB frequency for startup DDR speed
+ NBPtr->ChangeNbFrequency (NBPtr);
+
+ if (!NBPtr->IsSupported[ForcePhyToM0]) {
+ MemNBrdcstSetNb (NBPtr, BFDramPhyStatusReg, 0x80000000);
+
+ MemNBrdcstSetNb (NBPtr, BFPllRegWaitTime, 0x118);
+ }
+
+ // Phy Voltage Level Programming
+ MemNPhyVoltageLevelNb (NBPtr);
+
+ // Run frequency change sequence
+ MemNBrdcstSetNb (NBPtr, BFPllLockTime, NBPtr->FreqChangeParam->PllLockTimeDefault);
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreq, NBPtr->GetMemClkFreqId (NBPtr, NBPtr->DCTPtr->Timings.Speed));
+ NBPtr->FamilySpecificHook[SetSkewMemClk] (NBPtr, NULL);
+ NBPtr->ProgramNbPsDependentRegs (NBPtr);
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if ((NBPtr->DCTPtr->Timings.DctMemSize != 0)) {
+ MemNSetBitFieldNb (NBPtr, BFMemClkFreqVal, 1);
+ MemNPollBitFieldNb (NBPtr, BFFreqChgInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ }
+ }
+ FinalPllLockTime = 0xF;
+ NBPtr->FamilySpecificHook[AfterMemClkFreqVal] (NBPtr, &FinalPllLockTime);
+ if (!NBPtr->IsSupported[CsrPhyPllPdEn]) {
+ // IF (D18F2x[1,0]9C_x0D0F_E00A[CsrPhySrPllPdMode]==0) THEN program
+ // D18F2x[1,0]9C_x0D0F_E006[PllLockTime] = 0Fh
+ MemNBrdcstSetNb (NBPtr, BFPllLockTime, FinalPllLockTime);
+ }
+
+ NBPtr->FamilySpecificHook[BeforePhyFenceTraining] (NBPtr, NBPtr);
+
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
+
+ // Phy fence programming
+ AGESA_TESTPOINT (TpProcMemPhyFenceTraining, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->PhyFenceTraining (NBPtr);
+
+ // Phy compensation initialization
+ AGESA_TESTPOINT (TPProcMemPhyCompensation, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->MemNInitPhyComp (NBPtr);
+ MemProcessConditionalOverrides (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr, PSO_ACTION_SLEWRATE, ALL_DIMMS);
+ }
+ }
+
+ AGESA_TESTPOINT (TpProcMemBeforeDramInit, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->MemNBeforeDramInitNb (NBPtr);
+
+ AGESA_TESTPOINT (TpProcMemDramInit, &(NBPtr->MemPtr->StdHeader));
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nMemClkFreq: %d MHz\n", NBPtr->DCTPtr->Timings.Speed);
+ NBPtr->FeatPtr->DramInit (NBPtr->TechPtr);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * MemNChangeFrequencyHy:
+ *
+ * This function change MemClk frequency to the value that is specified by DCTPtr->Timings.Speed
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNChangeFrequencyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ UINT8 Dct;
+ UINT8 ChipSel;
+
+ TechPtr = NBPtr->TechPtr;
+ if (NBPtr->IsSupported[CheckDisDllShutdownSR] && !(NBPtr->IsSupported[SetDllShutDown])) {
+ // #107421
+ MemNBrdcstSetNb (NBPtr, BFDisDllShutdownSR, 1);
+ }
+
+ //Program F2x[1,0]90[EnterSelfRefresh]=1.
+ //Wait until the hardware resets F2x[1,0]90[EnterSelfRefresh]=0.
+ MemNBrdcstSetNb (NBPtr, BFEnterSelfRef, 1);
+ MemNPollBitFieldNb (NBPtr, BFEnterSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE);
+
+ //Program F2x9C_x08[DisAutoComp]=1
+ MemNSwitchDCTNb (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 1);
+
+ //Program F2x[1, 0]94[MemClkFreqVal] = 0.
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreqVal, 0);
+
+ //Program F2x[1, 0]94[MemClkFreq] to specify the target MEMCLK frequency.
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreq, NBPtr->GetMemClkFreqId (NBPtr, NBPtr->DCTPtr->Timings.Speed));
+
+ IDS_OPTION_HOOK (IDS_BEFORE_MEM_FREQ_CHG, NBPtr, &(NBPtr->MemPtr->StdHeader));
+ //Program F2x[1, 0]94[MemClkFreqVal] = 1.
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreqVal, 1);
+
+ //Wait until F2x[1, 0]94[FreqChgInProg]=0.
+ MemNPollBitFieldNb (NBPtr, BFFreqChgInProg, 0, PCI_ACCESS_TIMEOUT, TRUE);
+
+ if (NBPtr->IsSupported[CheckPhyFenceTraining]) {
+ //Perform Phy Fence retraining after frequency changed
+ AGESA_TESTPOINT (TpProcMemPhyFenceTraining, &(NBPtr->MemPtr->StdHeader));
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
+ AGESA_TESTPOINT (TpProcMemPhyFenceTraining, &(NBPtr->MemPtr->StdHeader));
+ MemNPhyFenceTrainingNb (NBPtr);
+ }
+ }
+ }
+
+ //Program F2x9C_x08[DisAutoComp]=0
+ MemNSwitchDCTNb (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 0);
+
+ //Program F2x[1,0]90[ExitSelfRef]=1 for both DCTs.
+ //Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0.
+ MemNBrdcstSetNb (NBPtr, BFExitSelfRef, 1);
+ MemNPollBitFieldNb (NBPtr, BFExitSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE);
+
+ if (NBPtr->MCTPtr->Status[SbRegistered]) {
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ TechPtr->FreqChgCtrlWrd (TechPtr);
+ }
+ }
+ }
+
+ //wait for 500 MCLKs after ExitSelfRef, 500*2.5ns=1250ns
+ MemNWaitXMemClksNb (NBPtr, 500);
+
+ if (NBPtr->IsSupported[CheckDisDllShutdownSR] && !(NBPtr->IsSupported[SetDllShutDown])) {
+ // #107421
+ MemNBrdcstSetNb (NBPtr, BFDisDllShutdownSR, 0);
+ }
+
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+
+ //9.Configure the DCT to send initialization MR commands:
+ // BIOS must reprogram Twr, Tcwl, and Tcl based on the new MEMCLK frequency.
+ // Program F2x[1, 0]7C similar to step #2 in Pass 1 above for the new Dimm values.
+ TechPtr->AutoCycTiming (TechPtr);
+ if (!MemNPlatformSpecNb (NBPtr)) {
+ IDS_ERROR_TRAP;
+ }
+
+ for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel++) {
+ if (NBPtr->IsSupported[CheckGetMCTSysAddr]) {
+ if ((NBPtr->DCTPtr->Timings.CsPresent & ((UINT16)1 << ChipSel)) != 0) {
+ // if chip select present
+ TechPtr->SendAllMRCmds (TechPtr, ChipSel);
+ // NOTE: wait 512 clocks for DLL-relock
+ MemUWait10ns (50000, NBPtr->MemPtr); // wait 500us
+ }
+ }
+ if (NBPtr->IsSupported[CheckSendAllMRCmds]) {
+ if ((NBPtr->DCTPtr->Timings.CsPresent & ((UINT16)1 << ChipSel)) != 0) {
+
+ // if chip select present
+ TechPtr->SendAllMRCmds (TechPtr, ChipSel);
+ }
+ }
+ }
+ if ((NBPtr->DCTPtr->Timings.Speed == DDR1600_FREQUENCY) && (NBPtr->IsSupported[CheckDllSpeedUp])) {
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D080F11, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D080F11) | 0x2000));
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D080F10, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D080F10) | 0x2000));
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D088F30, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D088F30) | 0x2000));
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D08C030, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D08C030) | 0x2000));
+ if (Dct == 0) {
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D082F30, (MemNGetBitFieldNb (NBPtr, BFPhy0x0D082F30) | 0x2000));
+ }
+ // NOTE: wait 512 clocks for DLL-relock
+ MemUWait10ns (50000, NBPtr->MemPtr); // wait 500us
+ }
+ }
+ }
+ // Re-enable phy compensation since it had been disabled during InitPhyComp
+ MemNSwitchDCTNb (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 0);
+
+ MemFInitTableDrive (NBPtr, MTAfterFreqChg);
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function ramp up frequency the next level if it have not reached
+ * its TargetSpeed yet.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - No fatal error occurs.
+ * @return FALSE - Fatal error occurs.
+ */
+
+BOOLEAN
+MemNRampUpFrequencyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST UINT16 FreqList[] = {
+ DDR400_FREQUENCY,
+ DDR533_FREQUENCY,
+ DDR667_FREQUENCY,
+ DDR800_FREQUENCY,
+ DDR1066_FREQUENCY,
+ DDR1333_FREQUENCY,
+ DDR1600_FREQUENCY,
+ DDR1866_FREQUENCY,
+ DDR2133_FREQUENCY
+ };
+ UINT8 Dct;
+ UINT8 i;
+ UINT16 NewSpeed;
+ DIE_STRUCT *MCTPtr;
+
+ MCTPtr = NBPtr->MCTPtr;
+
+ // Do not change frequency when it is already at TargetSpeed
+ if (NBPtr->DCTPtr->Timings.Speed == NBPtr->DCTPtr->Timings.TargetSpeed) {
+ return TRUE;
+ }
+
+ // Find the next supported frequency level
+ NewSpeed = NBPtr->DCTPtr->Timings.TargetSpeed;
+ for (i = 0; i < (GET_SIZE_OF (FreqList) - 1); i++) {
+ if (NBPtr->DCTPtr->Timings.Speed == FreqList[i]) {
+ NewSpeed = FreqList[i + 1];
+ break;
+ }
+ }
+ ASSERT (i < (GET_SIZE_OF (FreqList) - 1));
+ ASSERT (NewSpeed <= NBPtr->DCTPtr->Timings.TargetSpeed);
+
+ // BIOS must program both DCTs to the same frequency.
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nMemClkFreq changed: %d MHz", NBPtr->DCTPtr->Timings.Speed);
+ for (Dct = 0; Dct < MCTPtr->DctCount; Dct++) {
+ NBPtr->SwitchDCT (NBPtr, Dct);
+ NBPtr->DCTPtr->Timings.Speed = NewSpeed;
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, " -> %d MHz", NewSpeed);
+
+ NBPtr->ChangeFrequency (NBPtr);
+
+ return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function ramp up frequency to target frequency
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - No fatal error occurs.
+ * @return FALSE - Fatal error occurs.
+ */
+
+BOOLEAN
+MemNRampUpFrequencyUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dct;
+ DIE_STRUCT *MCTPtr;
+
+ MCTPtr = NBPtr->MCTPtr;
+
+ // Do not change frequency when it is already at TargetSpeed
+ if (NBPtr->DCTPtr->Timings.Speed == NBPtr->DCTPtr->Timings.TargetSpeed) {
+ return TRUE;
+ }
+
+ // BIOS must program both DCTs to the same frequency.
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nMemClkFreq changed: %d MHz", NBPtr->DCTPtr->Timings.Speed);
+ for (Dct = 0; Dct < MCTPtr->DctCount; Dct++) {
+ NBPtr->SwitchDCT (NBPtr, Dct);
+ NBPtr->DCTPtr->Timings.Speed = NBPtr->DCTPtr->Timings.TargetSpeed;
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, " -> %d MHz", NBPtr->DCTPtr->Timings.TargetSpeed);
+
+ NBPtr->ChangeFrequency (NBPtr);
+
+ return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function uses calculated values from DCT.Timings structure to
+ * program its registers.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNProgramCycTimingsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST CTENTRY TmgAdjTab[] = {
+ // BitField, Min, Max, Bias, Ratio_x2
+ {BFTcl, 4, 12, 4, 2},
+ {BFTrcd, 5, 12, 5, 2},
+ {BFTrp, 5, 12, 5, 2},
+ {BFTrtp, 4, 7, 4, 2},
+ {BFTras, 15, 30, 15, 2},
+ {BFTrc, 11, 42, 11, 2},
+ {BFTwrDDR3, 5, 12, 4, 2},
+ {BFTrrd, 4, 7, 4, 2},
+ {BFTwtr, 4, 7, 4, 2},
+ {BFFourActWindow, 16, 32, 14, 1}
+ };
+
+ DCT_STRUCT *DCTPtr;
+ UINT8 *MiniMaxTmg;
+ UINT8 *MiniMaxTrfc;
+ UINT8 Value8;
+ UINT8 j;
+ BIT_FIELD_NAME BitField;
+
+ DCTPtr = NBPtr->DCTPtr;
+
+ //======================================================================
+ // Program turnaround timings to their max during DRAM init and training
+ //======================================================================
+ //
+ MemNSetBitFieldNb (NBPtr, BFNonSPD, 0x28FF);
+
+ MemNSetBitFieldNb (NBPtr, BFNonSPDHi, 0x2A);
+
+ //======================================================================
+ // Program DRAM Timing values
+ //======================================================================
+ //
+ MiniMaxTmg = &DCTPtr->Timings.CasL;
+ for (j = 0; j < GET_SIZE_OF (TmgAdjTab); j++) {
+ BitField = TmgAdjTab[j].BitField;
+
+ if (MiniMaxTmg[j] < TmgAdjTab[j].Min) {
+ MiniMaxTmg[j] = TmgAdjTab[j].Min;
+ } else if (MiniMaxTmg[j] > TmgAdjTab[j].Max) {
+ MiniMaxTmg[j] = TmgAdjTab[j].Max;
+ }
+
+ Value8 = (UINT8) MiniMaxTmg[j];
+
+ if (BitField == BFTwrDDR3) {
+ Value8 = (Value8 == 10) ? 9 : (Value8 >= 11) ? 10 : Value8;
+ } else if (BitField == BFTrtp) {
+ Value8 = (DCTPtr->Timings.Speed <= DDR1066_FREQUENCY) ? 4 : (DCTPtr->Timings.Speed == DDR1333_FREQUENCY) ? 5 : 6;
+ }
+
+ Value8 = Value8 - TmgAdjTab[j].Bias;
+ Value8 = (Value8 * TmgAdjTab[j].Ratio_x2) >> 1;
+
+ ASSERT ((BitField == BFTcl ) ? (Value8 <= 8) :
+ (BitField == BFTrcd) ? (Value8 <= 7) :
+ (BitField == BFTrp ) ? (Value8 <= 7) :
+ (BitField == BFTrtp) ? (Value8 <= 3) :
+ (BitField == BFTras) ? (Value8 <= 15) :
+ (BitField == BFTrc ) ? (Value8 <= 31) :
+ (BitField == BFTrrd) ? (Value8 <= 3) :
+ (BitField == BFTwtr) ? (Value8 <= 3) :
+ (BitField == BFTwrDDR3) ? ((Value8 >= 1) && (Value8 <= 6)) :
+ (BitField == BFFourActWindow) ? ((Value8 >= 1) && (Value8 <= 9)) : FALSE);
+ MemNSetBitFieldNb (NBPtr, BitField, Value8);
+ }
+
+ MiniMaxTrfc = &DCTPtr->Timings.Trfc0;
+ for (j = 0; j < 4; j++) {
+ ASSERT (MiniMaxTrfc[j] <= 4);
+ MemNSetBitFieldNb (NBPtr, BFTrfc0 + j, MiniMaxTrfc[j]);
+ }
+
+ MemNSetBitFieldNb (NBPtr, BFTcwl, ((DCTPtr->Timings.Speed >= DDR800_FREQUENCY) ?
+ (NBPtr->GetMemClkFreqId (NBPtr, DCTPtr->Timings.Speed) - 3) : 0));
+
+ MemNSetBitFieldNb (NBPtr, BFTref, 2); // 7.8 us
+
+ //======================================================================
+ // DRAM MRS Register, set ODT
+ //======================================================================
+ //
+ // DrvImpCtrl: drive impedance control.01b(34 ohm driver; Ron34 = Rzq/7)
+ MemNSetBitFieldNb (NBPtr, BFDrvImpCtrl, 1);
+
+ // burst length control
+ if (NBPtr->MCTPtr->Status[Sb128bitmode]) {
+ MemNSetBitFieldNb (NBPtr, BFBurstCtrl, 2);
+ }
+
+ // ASR=1, auto self refresh; SRT=0
+ MemNSetBitFieldNb (NBPtr, BFASR, 1);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function uses calculated values from DCT.Timings structure to
+ * program its registers.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNProgramCycTimingsClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST CTENTRY TmgAdjTab[] = {
+ // BitField, Min, Max, Bias, Ratio_x2
+ {BFTcl, 5, 14, 4, 2},
+ {BFTrcd, 5, 14, 5, 2},
+ {BFTrp, 5, 14, 5, 2},
+ {BFTrtp, 4, 8, 4, 2},
+ {BFTras, 15, 36, 15, 2},
+ {BFTrc, 20, 49, 11, 2},
+ {BFTwrDDR3, 5, 16, 4, 2},
+ {BFTrrd, 4, 8, 4, 2},
+ {BFTwtr, 4, 8, 4, 2},
+ {BFFourActWindow, 16, 40, 14, 1}
+ };
+
+ DCT_STRUCT *DCTPtr;
+ UINT8 *MiniMaxTmg;
+ UINT8 *MiniMaxTrfc;
+ UINT8 Value8;
+ UINT8 j;
+ UINT8 Tcwl;
+ UINT8 Trcd;
+ INT32 TCK_ps;
+ BIT_FIELD_NAME BitField;
+
+ DCTPtr = NBPtr->DCTPtr;
+
+ //======================================================================
+ // Program DRAM Timing values
+ //======================================================================
+ //
+ MiniMaxTmg = &DCTPtr->Timings.CasL;
+ for (j = 0; j < GET_SIZE_OF (TmgAdjTab); j++) {
+ BitField = TmgAdjTab[j].BitField;
+
+ if (MiniMaxTmg[j] < TmgAdjTab[j].Min) {
+ MiniMaxTmg[j] = TmgAdjTab[j].Min;
+ } else if (MiniMaxTmg[j] > TmgAdjTab[j].Max) {
+ MiniMaxTmg[j] = TmgAdjTab[j].Max;
+ }
+
+ Value8 = (UINT8) MiniMaxTmg[j];
+
+ if (BitField == BFTwrDDR3) {
+ if (NBPtr->IsSupported[AdjustTwr]) {
+ Value8 ++;
+ }
+ Value8 = (Value8 >= 10) ? (((Value8 + 1) / 2) + 4) : Value8;
+ }
+
+ if ((BitField == BFTrc) && NBPtr->IsSupported[AdjustTrc]) {
+ Value8 -= 5;
+ }
+
+ Value8 = Value8 - TmgAdjTab[j].Bias;
+ Value8 = (Value8 * TmgAdjTab[j].Ratio_x2) >> 1;
+
+ ASSERT ((BitField == BFTcl ) ? ((Value8 >= 1) && (Value8 <= 10)) :
+ (BitField == BFTrcd) ? (Value8 <= 9) :
+ (BitField == BFTrp ) ? (Value8 <= 9) :
+ (BitField == BFTrtp) ? (Value8 <= 4) :
+ (BitField == BFTras) ? (Value8 <= 21) :
+ (BitField == BFTrc ) ? (NBPtr->IsSupported[AdjustTrc] ? ((Value8 >= 4) && (Value8 <= 38)) : ((Value8 >= 9) && (Value8 <= 38))) :
+ (BitField == BFTrrd) ? (Value8 <= 4) :
+ (BitField == BFTwtr) ? (Value8 <= 4) :
+ (BitField == BFTwrDDR3) ? (Value8 <= 7) :
+ (BitField == BFFourActWindow) ? ((Value8 >= 1) && (Value8 <= 13)) : FALSE);
+ MemNSetBitFieldNb (NBPtr, BitField, Value8);
+ }
+
+ MiniMaxTrfc = &DCTPtr->Timings.Trfc0;
+ for (j = 0; j < 4; j++) {
+ ASSERT (MiniMaxTrfc[j] <= 5);
+ MemNSetBitFieldNb (NBPtr, BFTrfc0 + j, MiniMaxTrfc[j]);
+ }
+
+ Tcwl = (UINT8) (DCTPtr->Timings.Speed / 133) + 2;
+ MemNSetBitFieldNb (NBPtr, BFTcwl, ((Tcwl > 5) ? (Tcwl - 5) : 0));
+
+ MemNSetBitFieldNb (NBPtr, BFTref, 2); // Tref = 7.8 us
+
+ // Skid buffer can only be programmed once before Dram init
+ if (NBPtr->DCTPtr->Timings.Speed == DDR800_FREQUENCY) {
+ TCK_ps = 1000500 / DCTPtr->Timings.TargetSpeed;
+ Trcd = (UINT8) ((((1000 / 40) * (UINT32)DCTPtr->Timings.DIMMTrcd) + TCK_ps - 1) / TCK_ps);
+ MemNSetBitFieldNb (NBPtr, BFDbeSkidBufDis, (Trcd > 10) ? 0 : 1);
+ }
+
+ MemNSetBitFieldNb (NBPtr, BFRdOdtTrnOnDly, (DCTPtr->Timings.CasL > Tcwl) ? (DCTPtr->Timings.CasL - Tcwl) : 0);
+
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function uses calculated values from DCT.Timings structure to
+ * program its registers for UNB
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNProgramCycTimingsUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST CTENTRY TmgAdjTab[] = {
+ // BitField, Min, Max, Bias, Ratio_x2
+ {BFTcl, 5, 14, 0, 2},
+ {BFTrcd, 2, 19, 0, 2},
+ {BFTrp, 2, 19, 0, 2},
+ {BFTrtp, 4, 10, 0, 2},
+ {BFTras, 8, 40, 0, 2},
+ {BFTrc, 10, 56, 0, 2},
+ {BFTwrDDR3, 5, 16, 0, 2},
+ {BFTrrd, 4, 9, 0, 2},
+ {BFTwtr, 4, 9, 0, 2},
+ {BFFourActWindow, 6, 42, 0, 2}
+ };
+
+ DCT_STRUCT *DCTPtr;
+ UINT8 *MiniMaxTmg;
+ UINT8 *MiniMaxTrfc;
+ UINT8 Value8;
+ UINT8 j;
+ UINT8 Tcwl;
+ UINT8 RdOdtTrnOnDly;
+ BIT_FIELD_NAME BitField;
+
+ DCTPtr = NBPtr->DCTPtr;
+
+ //======================================================================
+ // Program DRAM Timing values
+ //======================================================================
+ //
+ MiniMaxTmg = &DCTPtr->Timings.CasL;
+ for (j = 0; j < GET_SIZE_OF (TmgAdjTab); j++) {
+ BitField = TmgAdjTab[j].BitField;
+
+ if (BitField == BFTrp) {
+ if (NBPtr->IsSupported[AdjustTrp]) {
+ MiniMaxTmg[j] ++;
+ if (MiniMaxTmg[j] < 5) {
+ MiniMaxTmg[j] = 5;
+ }
+ }
+ }
+
+ if (MiniMaxTmg[j] < TmgAdjTab[j].Min) {
+ MiniMaxTmg[j] = TmgAdjTab[j].Min;
+ } else if (MiniMaxTmg[j] > TmgAdjTab[j].Max) {
+ MiniMaxTmg[j] = TmgAdjTab[j].Max;
+ }
+
+ Value8 = (UINT8) MiniMaxTmg[j];
+
+ if (BitField == BFTwrDDR3) {
+ if ((Value8 > 8) && ((Value8 & 1) != 0)) {
+ ASSERT (FALSE);
+ }
+ }
+
+ MemNSetBitFieldNb (NBPtr, BitField, Value8);
+ }
+
+ MiniMaxTrfc = &DCTPtr->Timings.Trfc0;
+ for (j = 0; j < 4; j++) {
+ if ((NBPtr->DCTPtr->Timings.DctDimmValid & (1 << j)) != 0) {
+ ASSERT (MiniMaxTrfc[j] <= 4);
+ MemNSetBitFieldNb (NBPtr, BFTrfc0 + j, MiniMaxTrfc[j]);
+ }
+ }
+
+ Tcwl = (UINT8) (DCTPtr->Timings.Speed / 133) + 2;
+ Tcwl = (Tcwl > 5) ? Tcwl : 5;
+ MemNSetBitFieldNb (NBPtr, BFTcwl, Tcwl);
+
+ MemNSetBitFieldNb (NBPtr, BFTref, 2); // 7.8 us
+
+ RdOdtTrnOnDly = (DCTPtr->Timings.CasL > Tcwl) ? (DCTPtr->Timings.CasL - Tcwl) : 0;
+ MemNSetBitFieldNb (NBPtr, BFRdOdtTrnOnDly, RdOdtTrnOnDly);
+ NBPtr->FamilySpecificHook[ProgOdtControl] (NBPtr, NULL);
+
+ //
+ // Program Tmod
+ //
+ MemNSetBitFieldNb (NBPtr, BFTmod, (DCTPtr->Timings.Speed < DDR1866_FREQUENCY) ? 0x0C :
+ (DCTPtr->Timings.Speed > DDR1866_FREQUENCY) ? 0x10 : 0x0E);
+ //
+ // Program Tzqcs and Tzqoper
+ //
+ // Tzqcs max(64nCK, 80ns)
+ MemNSetBitFieldNb (NBPtr, BFTzqcs, MIN (6, (MAX (64, MemUnsToMemClk (NBPtr->DCTPtr->Timings.Speed, 80)) + 15) / 16));
+ // Tzqoper max(256nCK, 320ns)
+ MemNSetBitFieldNb (NBPtr, BFTzqoper, MIN (0xC, (MAX (256, MemUnsToMemClk (NBPtr->DCTPtr->Timings.Speed, 320)) + 31) / 32));
+
+ // Program power management timing
+ MemNDramPowerMngTimingNb (NBPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets platform specific settings for the current channel
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - All platform types defined have initialized successfully
+ * @return FALSE - At least one of the platform types gave not been initialized successfully
+ */
+
+BOOLEAN
+MemNGetPlatformCfgNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 p;
+
+ for (p = 0; p < MAX_PLATFORM_TYPES; p++) {
+ ASSERT (NBPtr->MemPtr->GetPlatformCfg[p] != NULL);
+ if (NBPtr->MemPtr->GetPlatformCfg[p] (NBPtr->MemPtr, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr) == AGESA_SUCCESS) {
+ break;
+ }
+ }
+ return (p < MAX_PLATFORM_TYPES);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function retrieves the Max latency parameters
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @param[in] *MinDlyPtr - Pointer to variable to store the Minimum Delay value
+ * @param[in] *MaxDlyPtr - Pointer to variable to store the Maximum Delay value
+ * @param[in] *DlyBiasPtr - Pointer to variable to store Delay Bias value
+ * @param[in] MaxRcvEnDly - Maximum receiver enable delay value
+ */
+
+VOID
+MemNGetMaxLatParamsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 MaxRcvEnDly,
+ IN OUT UINT16 *MinDlyPtr,
+ IN OUT UINT16 *MaxDlyPtr,
+ IN OUT UINT16 *DlyBiasPtr
+ )
+{
+ *MinDlyPtr = (MemNTotalSyncComponentsNb (NBPtr) + (MaxRcvEnDly >> 5)) * 2;
+ MemNQuarterMemClk2NClkNb (NBPtr, MinDlyPtr);
+
+ *MaxDlyPtr = 0x3FF;
+
+ *DlyBiasPtr = 4;
+ MemNQuarterMemClk2NClkNb (NBPtr, DlyBiasPtr); // 1 MEMCLK Margin
+
+ *DlyBiasPtr += 1; // add 1 NCLK
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * 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
+MemNSetMaxLatencyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 MaxRcvEnDly
+ )
+{
+ UINT16 SubTotal;
+
+ AGESA_TESTPOINT (TpProcMemRcvrCalcLatency, &(NBPtr->MemPtr->StdHeader));
+
+ SubTotal = 0xC8; // init value for MaxRdLat used in training
+
+
+ if (MaxRcvEnDly != 0xFFFF) {
+ // Get all sync components BKDG steps 1-5
+ SubTotal = MemNTotalSyncComponentsNb (NBPtr);
+
+ // Add the maximum (worst case) delay value of DqsRcvEnGrossDelay
+ // that exists across all DIMMs and byte lanes.
+ //
+ SubTotal += MaxRcvEnDly >> 5;
+
+
+ // Add 14.5 to the sub-total. 14.5 represents part of the processor
+ // specific constant delay value in the DRAM clock domain.
+ //
+ SubTotal <<= 1; // scale 1/2 MemClk to 1/4 MemClk
+ SubTotal += 29; // add 14.5 1/2 MemClk
+
+ // Convert the sub-total (in 1/2 MEMCLKs) to northbridge clocks (NCLKs)
+ // as follows (assuming DDR400 and assuming that no P-state or link speed
+ // changes have occurred).
+ //
+ MemNQuarterMemClk2NClkNb (NBPtr, &SubTotal);
+
+ // Add 2 NCLKs to the sub-total. 2 represents part of the processor
+ // specific constant value in the northbridge clock domain.
+ //
+ SubTotal += 2;
+ }
+
+ NBPtr->DCTPtr->Timings.MaxRdLat = SubTotal;
+ // Program the F2x[1, 0]78[MaxRdLatency] register with the total delay value
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMaxRdLat: %03x\n", SubTotal);
+ MemNSetBitFieldNb (NBPtr, BFMaxLatency, SubTotal);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sends the ZQCL command
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNSendZQCmdNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ // 1.Program MrsAddress[10]=1
+ MemNSetBitFieldNb (NBPtr, BFMrsAddress, (UINT32)1 << 10);
+
+ // 2.Set SendZQCmd=1
+ MemNSetBitFieldNb (NBPtr, BFSendZQCmd, 1);
+
+ // 3.Wait for SendZQCmd=0
+ MemNPollBitFieldNb (NBPtr, BFSendZQCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
+
+ // 4.Wait 512 MEMCLKs
+ MemNWaitXMemClksNb (NBPtr, 512);
+}
+
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function is used to create the DRAM map
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ */
+
+VOID
+STATIC
+MemNAfterStitchMemNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ if (NBPtr->MCTPtr->GangedMode) {
+ NBPtr->MCTPtr->NodeMemSize = NBPtr->DCTPtr->Timings.DctMemSize;
+ NBPtr->MCTPtr->NodeSysLimit = NBPtr->MCTPtr->NodeMemSize - 1;
+ NBPtr->MCTPtr->DctData[1].Timings.CsPresent = NBPtr->DCTPtr->Timings.CsPresent;
+ NBPtr->MCTPtr->DctData[1].Timings.CsEnabled = NBPtr->DCTPtr->Timings.CsEnabled;
+ NBPtr->MCTPtr->DctData[1].Timings.DctMemSize = NBPtr->DCTPtr->Timings.DctMemSize;
+ } else {
+ // In unganged mode, add DCT0 and DCT1 to NodeMemSize
+ NBPtr->MCTPtr->NodeMemSize += NBPtr->DCTPtr->Timings.DctMemSize;
+ NBPtr->MCTPtr->NodeSysLimit = NBPtr->MCTPtr->NodeMemSize - 1;
+ }
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function Return the binary value of tfaw associated with
+ * the index k
+ *
+ * @param[in] k value
+ *
+ * @return F[k], in Binary MHz.
+ */
+
+UINT8
+MemNGet1KTFawTkNb (
+ IN UINT8 k
+ )
+{
+ CONST UINT8 Tab1KTfawTK[] = {0, 8, 10, 13, 14, 19};
+ ASSERT (k <= 5);
+ return Tab1KTfawTK[k];
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function Return the binary value of the 2KTFaw associated with
+ * the index k
+ *
+ * @param[in] k value
+ *
+ * @return 2KTFaw converted based on k.
+ */
+
+UINT8
+MemNGet2KTFawTkNb (
+ IN UINT8 k
+ )
+{
+ CONST UINT8 Tab2KTfawTK[] = {0, 10, 14, 17, 18, 24};
+ ASSERT (k <= 5);
+ return Tab2KTfawTK[k];
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function converts the sub-total (in 1/4 MEMCLKs) to northbridge clocks (NCLKs)
+ * (assuming DDR400 and assuming that no P-state or link speed
+ * changes have occurred).
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *SubTotalPtr - pointer to Sub-Total
+ */
+
+VOID
+STATIC
+MemNQuarterMemClk2NClkNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT UINT16 *SubTotalPtr
+ )
+{
+ UINT32 NBFreq;
+ UINT32 MemFreq;
+
+ // Multiply SubTotal by NB COF
+ NBFreq = (MemNGetBitFieldNb (NBPtr, BFNbFid) + 4) * 200;
+ // Divide SubTotal by 4 times current MemClk frequency
+ MemFreq = NBPtr->DCTPtr->Timings.Speed * 4;
+ *SubTotalPtr = (UINT16) (((NBFreq * (*SubTotalPtr)) + MemFreq - 1) / MemFreq); // round up
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the total of sync components for Max Read Latency calculation
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return Total in 1/2 MEMCLKs
+ */
+
+UINT16
+MemNTotalSyncComponentsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT16 SubTotal;
+
+ // Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs UINTs.
+ SubTotal = (UINT16) MemNGetBitFieldNb (NBPtr, BFTcl) + 1;
+ if ((MemNGetBitFieldNb (NBPtr, BFDdr3Mode)) != 0) {
+ SubTotal += 3;
+ }
+ SubTotal *= 2;
+
+ // If registered DIMMs are being used then add 1 MEMCLK to the sub-total.
+ if ((MemNGetBitFieldNb (NBPtr, BFUnBuffDimm)) == 0) {
+ SubTotal += 2;
+ }
+
+ // If (F2x[1, 0]9C_x04[AddrCmdSetup] and F2x[1, 0]9C_x04[CsOdtSetup] and F2x[1, 0]9C_x04[Cke-Setup] = 0) then K = K + 1
+ // If (F2x[1, 0]9C_x04[AddrCmdSetup] or F2x[1, 0]9C_x04[CsOdtSetup] or F2x[1, 0]9C_x04[CkeSetup] = 1) then K = K + 2
+ if ((MemNGetBitFieldNb (NBPtr, BFAddrTmgControl) & 0x0202020) == 0) {
+ SubTotal += 1;
+ } else {
+ SubTotal += 2;
+ }
+
+ // If the F2x[1, 0]78[RdPtrInit] field is 4, 5, 6 or 7 MEMCLKs,
+ // then add 4, 3, 2, or 1 MEMCLKs, respectively to the sub-total.
+ //
+ SubTotal = SubTotal + (8 - (UINT16) MemNGetBitFieldNb (NBPtr, BFRdPtrInit));
+
+ return SubTotal;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function swaps bits for OnDimmMirror support
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNSwapBitsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 ChipSel;
+ UINT32 MRSReg;
+
+ ChipSel = (UINT8) MemNGetBitFieldNb (NBPtr, BFMrsChipSel);
+ if ((ChipSel & 1) != 0) {
+ MRSReg = MemNGetBitFieldNb (NBPtr, BFDramInitRegReg);
+ if ((NBPtr->DCTPtr->Timings.DimmMirrorPresent & (1 << (ChipSel >> 1))) != 0) {
+ MRSReg = (MRSReg & 0xFFFCFE07) | ((MRSReg&0x100A8) << 1) | ((MRSReg&0x20150) >> 1);
+ MemNSetBitFieldNb (NBPtr, BFDramInitRegReg, MRSReg);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function swaps bits for OnDimmMirror support for Unb
+ *
+ * Dimm Mirroring Requires that, during MRS command cycles, the following
+ * bits are swapped by software
+ *
+ * A3 -> A4 A7 -> A8
+ * A4 -> A3 BA0 -> BA1
+ * A5 -> A6 BA1 -> BA0
+ * A6 -> A5
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNSwapBitsUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 ChipSel;
+ UINT32 MRSBank;
+ UINT32 MRSAddr;
+
+ ChipSel = (UINT8) MemNGetBitFieldNb (NBPtr, BFMrsChipSel);
+ if ((ChipSel & 1) != 0) {
+ if ((NBPtr->DCTPtr->Timings.DimmMirrorPresent & (1 << (ChipSel >> 1))) != 0) {
+ MRSBank = MemNGetBitFieldNb (NBPtr, BFMrsBank);
+ MRSAddr = MemNGetBitFieldNb (NBPtr, BFMrsAddress);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tCS%d MR%d %05x swapped to ->",
+ (ChipSel & 0x7),
+ (MRSBank & 0x7),
+ (MRSAddr & 0x3FFFF));
+ //
+ // Swap Mrs Bank bits 0 with 1
+ MRSBank = (MRSBank & 0x0100) | ((MRSBank & 0x01) << 1) | ((MRSBank & 0x02) >> 1);
+ //
+ // Swap Mrs Address bits 3 with 4, 5 with 6, and 7 with 8
+ MRSAddr = (MRSAddr & 0x03FE07) | ((MRSAddr&0x000A8) << 1) | ((MRSAddr&0x00150) >> 1);
+ MemNSetBitFieldNb (NBPtr, BFMrsBank, MRSBank);
+ MemNSetBitFieldNb (NBPtr, BFMrsAddress, MRSAddr);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Programs Address/command timings, driver strengths, and tri-state fields.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNProgramPlatformSpecNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST UINT8 PinType[3] = {PSO_CKE_TRI, PSO_ODT_TRI, PSO_CS_TRI};
+ CONST UINT8 TabSize[3] = { 2, 4, 8};
+ CONST BIT_FIELD_NAME BitField[3] = { BFCKETri, BFODTTri, BFChipSelTri};
+ UINT8 *TabPtr;
+ UINT8 i;
+ UINT8 k;
+ UINT8 Value;
+ //===================================================================
+ // Tristate unused CKE, ODT and chip select to save power
+ //===================================================================
+ //
+ TabPtr = NULL;
+ for (k = 0; k < sizeof (PinType); k++) {
+ if (NBPtr->IsSupported[CheckFindPSOverideWithSocket]) {
+ TabPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PinType[k], NBPtr->MCTPtr->SocketId, MemNGetSocketRelativeChannelNb (NBPtr, NBPtr->Dct, 0), 0,
+ &(NBPtr->MCTPtr->LogicalCpuid), &(NBPtr->MemPtr->StdHeader));
+ }
+ if (NBPtr->IsSupported[CheckFindPSDct]) {
+ TabPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PinType[k], NBPtr->MCTPtr->SocketId, NBPtr->Dct, 0,
+ &(NBPtr->MCTPtr->LogicalCpuid), &(NBPtr->MemPtr->StdHeader));
+ }
+ if (TabPtr == NULL) {
+ switch (k) {
+ case 0:
+ TabPtr = NBPtr->ChannelPtr->CKETriMap;
+ break;
+ case 1:
+ TabPtr = NBPtr->ChannelPtr->ODTTriMap;
+ break;
+ case 2:
+ TabPtr = NBPtr->ChannelPtr->ChipSelTriMap;
+ break;
+ default:
+ IDS_ERROR_TRAP;
+ }
+ }
+ ASSERT (TabPtr != NULL);
+
+ Value = 0;
+ for (i = 0; i < TabSize[k]; i++) {
+ if ((NBPtr->DCTPtr->Timings.CsPresent & TabPtr[i]) == 0) {
+ Value |= (UINT8) (1 << i);
+ }
+ }
+
+ if (k == PSO_CS_TRI) {
+ NBPtr->FamilySpecificHook[BeforeSetCsTri] (NBPtr, &Value);
+ }
+
+ ASSERT (k < GET_SIZE_OF (BitField));
+ MemNSetBitFieldNb (NBPtr, BitField[k], Value);
+ }
+ NBPtr->MemNBeforePlatformSpecNb (NBPtr);
+
+ //===================================================================
+ // Program Address/Command timings and driver strength
+ //===================================================================
+ //
+ MemProcessConditionalOverrides (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr, PSO_ACTION_ADDRTMG, ALL_DIMMS);
+ MemProcessConditionalOverrides (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr, PSO_ACTION_ODCCONTROL, ALL_DIMMS);
+
+ MemNSetBitFieldNb (NBPtr, BFSlowAccessMode, (NBPtr->ChannelPtr->SlowMode) ? 1 : 0);
+ MemNSetBitFieldNb (NBPtr, BFODCControl, NBPtr->ChannelPtr->DctOdcCtl);
+ MemNSetBitFieldNb (NBPtr, BFAddrTmgControl, NBPtr->ChannelPtr->DctAddrTmg);
+ NBPtr->FamilySpecificHook[SetDqsODT] (NBPtr, NBPtr);
+
+ if (NBPtr->IsSupported[CheckODTControls]) {
+ MemNSetBitFieldNb (NBPtr, BFPhyRODTCSLow, NBPtr->ChannelPtr->PhyRODTCSLow);
+ MemNSetBitFieldNb (NBPtr, BFPhyRODTCSHigh, NBPtr->ChannelPtr->PhyRODTCSHigh);
+ MemNSetBitFieldNb (NBPtr, BFPhyWODTCSLow, NBPtr->ChannelPtr->PhyWODTCSLow);
+ MemNSetBitFieldNb (NBPtr, BFPhyWODTCSHigh, NBPtr->ChannelPtr->PhyWODTCSHigh);
+ }
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the Trdrd value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return Trdrd value
+ */
+
+UINT8
+MemNGetTrdrdNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ DCT_STRUCT *DCTPtr;
+ INT8 Cgdd;
+
+ DCTPtr = NBPtr->DCTPtr;
+
+ // BIOS calculates Trdrd (in MEMCLKs) = CGDD / 2 + 3 clocks and programs F2x[1, 0]8C[Trdrd] with the
+ // converted field value. BIOS rounds fractional values down.
+ // The Critical Gross Delay Difference (CGDD) for Trdrd on any given byte lane is the largest F2x[1,
+ // 0]9C_x[3:0][2B:10][DqsRcvEnGrossDelay] delay of any DIMM minus the F2x[1,
+ // 0]9C_x[3:0][2B:10][DqsRcvEnGrossDelay] delay of any other DIMM.
+
+ Cgdd = MemNGetOptimalCGDDNb (NBPtr, AccessRcvEnDly, AccessRcvEnDly);
+ DCTPtr->Timings.Trdrd = (Cgdd / 2) + 3;
+
+ // Transfer clk to reg definition, 2T is 00b, etc.
+ DCTPtr->Timings.Trdrd -= 2;
+ if (DCTPtr->Timings.Trdrd > 8) {
+ DCTPtr->Timings.Trdrd = 8;
+ }
+
+ return DCTPtr->Timings.Trdrd;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the Twrwr value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return Twrwr value
+ */
+
+UINT8
+MemNGetTwrwrNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ DCT_STRUCT *DCTPtr;
+ INT8 Cgdd;
+
+ DCTPtr = NBPtr->DCTPtr;
+
+ // Twrwr (in MEMCLKs) = CGDD / 2 + 3 clocks and programs F2x[1, 0]8C[Twrwr] with the
+ // converted field value. BIOS rounds fractional values down.
+ // On any given byte lane, the largest F2x[1, 0]9C_x[3:0][A, 7, 6, 0][2:1]:F2x[1, 0]9C_x[3:0][A, 7, 6,
+ // 0]3[WrDatGrossDlyByte] delay of any DIMM minus the F2x[1, 0]9C_x[3:0][A, 7, 6, 0][2:1]:F2x[1,
+ // 0]9C_x[3:0][A, 7, 6, 0]3[WrDatGrossDlyByte] delay of any other DIMM is equal to the Critical Gross
+ // Delay Difference (CGDD) for Twrwr.
+
+ Cgdd = MemNGetOptimalCGDDNb (NBPtr, AccessWrDatDly, AccessWrDatDly);
+ DCTPtr->Timings.Twrwr = (Cgdd / 2) + 3;
+ NBPtr->TechPtr->AdjustTwrwr (NBPtr->TechPtr);
+
+ return DCTPtr->Timings.Twrwr;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the Twrrd value. BIOS calculates Twrrd (in MEMCLKs) = CGDD / 2 - LD + 3 clocks and programs
+ * F2x[1, 0]8C[Twrrd] with the converted field value. BIOS rounds fractional
+ * values down.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return Value to be programmed to Twrrd field
+ * pDCT->Timings.Twrrd updated
+ */
+
+UINT8
+MemNGetTwrrdNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ INT8 Cgdd;
+ INT8 Ld;
+ INT8 Twrrd;
+ DCT_STRUCT *DCTPtr;
+
+ DCTPtr = NBPtr->DCTPtr;
+
+ //
+ // For DDR3, BIOS calculates the latency difference (Ld) as equal to read CAS latency minus write CAS
+ // latency, in MEMCLKs (see F2x[1, 0]88[Tcl] and F2x[1, 0]84[Tcwl]) which can be a negative or positive
+ // value.
+ // For DDR2, LD is always one clock (For DDR2, Tcwl is always Tcl minus 1).
+ //
+ Ld = NBPtr->TechPtr->GetLD (NBPtr->TechPtr);
+
+ // On any given byte lane, the largest WrDatGrossDlyByte delay of any DIMM
+ // minus the DqsRcvEnGrossDelay delay of any other DIMM is
+ // equal to the Critical Gross Delay Difference (CGDD) for Twrrd.
+ Cgdd = MemNGetOptimalCGDDNb (NBPtr, AccessWrDatDly, AccessRcvEnDly);
+ Twrrd = (Cgdd / 2) - Ld + 3;
+ DCTPtr->Timings.Twrrd = (UINT8) ((Twrrd >= 0) ? Twrrd : 0);
+ NBPtr->TechPtr->AdjustTwrrd (NBPtr->TechPtr);
+
+ return DCTPtr->Timings.Twrrd;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the TrwtTO value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return pDCT->Timings.TrwtTO updated
+ */
+
+UINT8
+MemNGetTrwtTONb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ INT8 Cgdd;
+ INT8 Ld;
+ INT8 TrwtTO;
+ DCT_STRUCT *DCTPtr;
+
+ DCTPtr = NBPtr->DCTPtr;
+ //
+ // For DDR3, BIOS calculates the latency difference (Ld) as equal to read CAS latency minus write CAS
+ // latency, in MEMCLKs (see F2x[1, 0]88[Tcl] and F2x[1, 0]84[Tcwl]) which can be a negative or positive
+ // value.
+ // For DDR2, LD is always one clock (For DDR2, Tcwl is always Tcl minus 1).
+ //
+ Ld = NBPtr->TechPtr->GetLD (NBPtr->TechPtr);
+
+ // On any byte lane, the largest DqsRcvEnGrossDelay delay of any DIMM minus
+ // the WrDatGrossDlyByte delay of any other DIMM is equal to the Critical Gross
+ // Delay Difference (CGDD) for TrwtTO.
+ Cgdd = MemNGetOptimalCGDDNb (NBPtr, AccessRcvEnDly, AccessWrDatDly);
+ TrwtTO = (Cgdd / 2) + Ld + 3;
+ TrwtTO -= 2;
+ DCTPtr->Timings.TrwtTO = (UINT8) ((TrwtTO > 1) ? TrwtTO : 1);
+
+ return DCTPtr->Timings.TrwtTO;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the TrwtWB value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TrwtWB value
+ */
+UINT8
+MemNGetTrwtWBNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ DCT_STRUCT *DCTPtr;
+
+ DCTPtr = NBPtr->DCTPtr;
+
+ // TrwtWB ensures read-to-write data-bus turnaround.
+ // This value should be one more than the programmed TrwtTO.
+ return DCTPtr->Timings.TrwtWB = DCTPtr->Timings.TrwtTO;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function converts MemClk frequency in MHz to MemClkFreq value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Speed - MemClk frequency in MHz
+ *
+ * @return MemClkFreq value
+ */
+UINT8
+MemNGetMemClkFreqIdNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 Speed
+ )
+{
+ return (UINT8) ((Speed < DDR800_FREQUENCY) ? ((Speed / 66) - 3) : (Speed / 133));
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function enables swapping interleaved region feature.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Base - Swap interleaved region base [47:27]
+ * @param[in] Limit - Swap interleaved region limit [47:27]
+ *
+ */
+VOID
+MemNEnableSwapIntlvRgnNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Base,
+ IN UINT32 Limit
+ )
+{
+ UINT32 Size;
+ UINT32 SizeOfAlign;
+
+ // Swapped interleaving region must be below 16G
+ if (Limit < (1 << (34 - 27))) {
+ // Adjust Base and Size to meet :
+ // 1. The size of the swapped region must be less than or equal to the alignment of F2x10C[IntLvRegionBase].
+ // 2. Entire UMA region is swapped with interleaving region.
+ Size = Limit - Base;
+ SizeOfAlign = (UINT32) 1 << LibAmdBitScanForward (Base);
+ while (SizeOfAlign <= Size) {
+ // In case of SizeOfAlign <= Size, UmaBase -= 128MB, SizeOfIntlvrgn += 128MB.
+ Base -= 1;
+ Size += 1;
+ SizeOfAlign = (UINT32) 1 << LibAmdBitScanForward (Base);
+ }
+ MemNSetBitFieldNb (NBPtr, BFIntLvRgnBaseAddr, Base);
+ MemNSetBitFieldNb (NBPtr, BFIntLvRgnLmtAddr, (Limit - 1));
+ MemNSetBitFieldNb (NBPtr, BFIntLvRgnSize, Size);
+ MemNSetBitFieldNb (NBPtr, BFIntLvRgnSwapEn, 1);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function converts MemClk frequency in MHz to MemClkFreq value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Speed - MemClk frequency in MHz
+ *
+ * @return MemClkFreq value
+ */
+UINT8
+MemNGetMemClkFreqIdClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 Speed
+ )
+{
+ return (UINT8) ((Speed > DDR400_FREQUENCY) ? ((Speed / 33) - 6) : ((Speed == DDR400_FREQUENCY) ? 2 : (Speed / 55)));
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function converts MemClk frequency in MHz to MemClkFreq value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Speed - MemClk frequency in MHz
+ *
+ * @return MemClkFreq value
+ */
+UINT8
+MemNGetMemClkFreqIdUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 Speed
+ )
+{
+ return (UINT8) ((Speed > DDR400_FREQUENCY) ? ((Speed / 33) - 6) : ((Speed == DDR400_FREQUENCY) ? 2 : (Speed / 55)));
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function converts MemClkFreq Id value to MemClk frequency in MHz
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] FreqId - FreqId from Register
+ *
+ * @return MemClk frequency in MHz
+ */
+UINT16
+MemNGetMemClkFreqUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 FreqId
+ )
+{
+ UINT16 MemClkFreq;
+ if (FreqId > 2) {
+ MemClkFreq = (FreqId == 14) ? 667 : (300 + ((FreqId - 3) * 33) + (FreqId - 3) / 3);
+ } else if (FreqId == 2) {
+ MemClkFreq = 200;
+ } else {
+ MemClkFreq = 50 + (50 * FreqId);
+ }
+ return MemClkFreq;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function change MemClk frequency to the value that is specified by DCTPtr->Timings.Speed
+ * for client NB.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNChangeFrequencyClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ UINT8 Dct;
+ UINT8 ChipSel;
+ UINT16 FinalPllLockTime;
+ BOOLEAN FrequencyChangeSuccess;
+ UINT64 OrgMMIOCfgBase;
+ UINT64 NewMMIOCfgBase;
+
+ TechPtr = NBPtr->TechPtr;
+
+ // Disable MMIO to prevent speculative DRAM reads during self refresh
+ LibAmdMsrRead (MSR_MMIO_Cfg_Base, &OrgMMIOCfgBase, &(NBPtr->MemPtr->StdHeader));
+ NewMMIOCfgBase = OrgMMIOCfgBase & (~(BIT0));
+ LibAmdMsrWrite (MSR_MMIO_Cfg_Base, &NewMMIOCfgBase, &(NBPtr->MemPtr->StdHeader));
+
+ MemNBrdcstSetNb (NBPtr, BFDisDllShutdownSR, 1);
+
+ //Program F2x[1,0]90[EnterSelfRefresh]=1.
+ //Wait until the hardware resets F2x[1,0]90[EnterSelfRefresh]=0.
+ MemNBrdcstSetNb (NBPtr, BFEnterSelfRef, 1);
+ MemNPollBitFieldNb (NBPtr, BFEnterSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE);
+
+ if (NBPtr->ChangeNbFrequency (NBPtr)) {
+ // Reprogram Twr, Tcwl, and Tcl based on the new MEMCLK frequency.
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ TechPtr->AutoCycTiming (TechPtr);
+ if (!MemNPlatformSpecUnb (NBPtr)) {
+ IDS_ERROR_TRAP;
+ }
+ }
+ }
+
+ // 1. Program PllLockTime to Family-specific value
+ MemNBrdcstSetNb (NBPtr, BFPllLockTime, NBPtr->FreqChangeParam->PllLockTimeDefault);
+
+ // 2. Program D18F2x[1,0]94[MemClkFreqVal] = 0.
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreqVal, 0);
+
+ // 3. Program D18F2x[1,0]94[MemClkFreq] to the desired DRAM frequency.
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreq, NBPtr->GetMemClkFreqId (NBPtr, NBPtr->DCTPtr->Timings.Speed));
+
+ // 4. Program D18F2x[1,0]F4_x30[DbeGskFifoNumerator] and D18F2x[1,0]F4_x31[DbeGskFifoDenominator].
+ // 5. Program D18F2x[1,0]F4_x32[DataTxFifoSchedDlyNegSlot1, DataTxFifoSchedDlySlot1,
+ // DataTxFifoSchedDlyNegSlot0, DataTxFifoSchedDlySlot0]. See 2.10.3.2.2.1 [DCT Transmit Fifo Schedule
+ // Delay Programming].
+ // 6. D18F2x[1,0]78[RdPtrInit] = IF (D18F2x[1,0]94[MemClkFreq] >= 667 MHz) THEN 7 ELSE 8 ENDIF (Llano)
+ // THEN 2 ELSE 3 ENDIF (Ontario)
+ NBPtr->ProgramNbPsDependentRegs (NBPtr);
+
+ NBPtr->FamilySpecificHook[BeforeMemClkFreqVal] (NBPtr, NBPtr);
+ IDS_OPTION_HOOK (IDS_BEFORE_MEM_FREQ_CHG, NBPtr, &(NBPtr->MemPtr->StdHeader));
+ // 7. Program D18F2x[1,0]94[MemClkFreqVal] = 1.
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreqVal, 1);
+ MemNPollBitFieldNb (NBPtr, BFFreqChgInProg, 0, PCI_ACCESS_TIMEOUT, TRUE);
+ FinalPllLockTime = 0xF;
+ NBPtr->FamilySpecificHook[AfterMemClkFreqVal] (NBPtr, &FinalPllLockTime);
+
+ // 8. IF (D18F2x[1,0]9C_x0D0F_E00A[CsrPhySrPllPdMode]==0) THEN program
+ // D18F2x[1,0]9C_x0D0F_E006[PllLockTime] = 0Fh.
+ if (!NBPtr->IsSupported[CsrPhyPllPdEn]) {
+ MemNBrdcstSetNb (NBPtr, BFPllLockTime, FinalPllLockTime);
+ }
+
+ FrequencyChangeSuccess = TRUE;
+ } else {
+ // If NB frequency cannot be updated, use the current speed as the target speed
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ NBPtr->DCTPtr->Timings.Speed = NBPtr->TechPtr->PrevSpeed;
+ NBPtr->DCTPtr->Timings.TargetSpeed = NBPtr->TechPtr->PrevSpeed;
+ }
+ FrequencyChangeSuccess = FALSE;
+ }
+
+ //Program F2x[1,0]90[ExitSelfRef]=1 for both DCTs.
+ //Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0.
+ MemNBrdcstSetNb (NBPtr, BFExitSelfRef, 1);
+ MemNPollBitFieldNb (NBPtr, BFExitSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE);
+ MemNBrdcstSetNb (NBPtr, BFDisDllShutdownSR, 0);
+
+ if (FrequencyChangeSuccess) {
+ NBPtr->FamilySpecificHook[AfterMemClkFreqChg] (NBPtr, NULL);
+
+ // Perform Phy Fence training and Phy comp init after frequency change
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
+
+ // Phy fence programming
+ AGESA_TESTPOINT (TpProcMemPhyFenceTraining, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->PhyFenceTraining (NBPtr);
+
+ // Phy compensation initialization
+ AGESA_TESTPOINT (TPProcMemPhyCompensation, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->MemNInitPhyComp (NBPtr);
+ MemProcessConditionalOverrides (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr, PSO_ACTION_SLEWRATE, ALL_DIMMS);
+ }
+ }
+
+ //======================================================================
+ // Calculate and program DRAM Timings at new frequency
+ //======================================================================
+ //
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel++) {
+ if ((NBPtr->DCTPtr->Timings.CsPresent & ((UINT16)1 << ChipSel)) != 0) {
+ // if chip select present
+ if (!(TechPtr->TechnologySpecificHook[LrdimmSendAllMRCmds] (TechPtr, &ChipSel))) {
+ TechPtr->SendAllMRCmds (TechPtr, ChipSel);
+ }
+ }
+ }
+ // Wait 512 clocks for DLL-relock
+ MemNWaitXMemClksNb (NBPtr, 512);
+ }
+ }
+ }
+
+ // Restore MMIO setting
+ LibAmdMsrWrite (MSR_MMIO_Cfg_Base, &OrgMMIOCfgBase, &(NBPtr->MemPtr->StdHeader));
+
+ MemFInitTableDrive (NBPtr, MTAfterFreqChg);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function change MemClk frequency to the value that is specified by DCTPtr->Timings.Speed
+ * for UNB.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNChangeFrequencyUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ UINT8 Dct;
+ UINT8 ChipSel;
+ UINT16 FinalPllLockTime;
+ BOOLEAN FrequencyChangeSuccess;
+ UINT64 OrgMMIOCfgBase;
+ UINT64 NewMMIOCfgBase;
+
+ TechPtr = NBPtr->TechPtr;
+
+ // Disable MMIO to prevent speculative DRAM reads during self refresh
+ LibAmdMsrRead (MSR_MMIO_Cfg_Base, &OrgMMIOCfgBase, &(NBPtr->MemPtr->StdHeader));
+ NewMMIOCfgBase = OrgMMIOCfgBase & (~(BIT0));
+ LibAmdMsrWrite (MSR_MMIO_Cfg_Base, &NewMMIOCfgBase, &(NBPtr->MemPtr->StdHeader));
+
+ MemNBrdcstSetNb (NBPtr, BFDisDllShutdownSR, 1);
+
+ //Program F2x[1,0]90[EnterSelfRefresh]=1.
+ //Wait until the hardware resets F2x[1,0]90[EnterSelfRefresh]=0.
+ MemNBrdcstSetNb (NBPtr, BFEnterSelfRef, 1);
+ MemNPollBitFieldNb (NBPtr, BFEnterSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE);
+
+ if (NBPtr->ChangeNbFrequency (NBPtr)) {
+ // Reprogram Twr, Tcwl, and Tcl based on the new MEMCLK frequency.
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ TechPtr->AutoCycTiming (TechPtr);
+ if (!MemNPlatformSpecUnb (NBPtr)) {
+ IDS_ERROR_TRAP;
+ }
+ }
+ }
+
+ // 1. Program PllLockTime to Family-specific value
+ MemNBrdcstSetNb (NBPtr, BFPllLockTime, NBPtr->FreqChangeParam->PllLockTimeDefault);
+
+ // 2. Program D18F2x[1,0]94[MemClkFreqVal] = 0.
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreqVal, 0);
+
+ // 3. Program D18F2x[1,0]94[MemClkFreq] to the desired DRAM frequency.
+ MemNBrdcstSetNb (NBPtr, BFMemClkFreq, NBPtr->GetMemClkFreqId (NBPtr, NBPtr->DCTPtr->Timings.Speed));
+
+ // 4. Program D18F2x[1,0]F4_x30[DbeGskFifoNumerator] and D18F2x[1,0]F4_x31[DbeGskFifoDenominator].
+ // 5. Program D18F2x[1,0]F4_x32[DataTxFifoSchedDlyNegSlot1, DataTxFifoSchedDlySlot1,
+ // DataTxFifoSchedDlyNegSlot0, DataTxFifoSchedDlySlot0]. See 2.10.3.2.2.1 [DCT Transmit Fifo Schedule
+ // Delay Programming].
+ // 6. D18F2x[1,0]78[RdPtrInit] = IF (D18F2x[1,0]94[MemClkFreq] >= 667 MHz) THEN 7 ELSE 8 ENDIF (Llano)
+ // THEN 2 ELSE 3 ENDIF (Ontario)
+ NBPtr->ProgramNbPsDependentRegs (NBPtr);
+
+ IDS_OPTION_HOOK (IDS_BEFORE_MEM_FREQ_CHG, NBPtr, &(NBPtr->MemPtr->StdHeader));
+ // 7. Program D18F2x[1,0]94[MemClkFreqVal] = 1.
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if ((NBPtr->DCTPtr->Timings.DctMemSize != 0)) {
+ MemNSetBitFieldNb (NBPtr, BFMemClkFreqVal, 1);
+ MemNPollBitFieldNb (NBPtr, BFFreqChgInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ }
+ }
+ FinalPllLockTime = 0xF;
+ NBPtr->FamilySpecificHook[AfterMemClkFreqVal] (NBPtr, &FinalPllLockTime);
+
+ // 8. IF (D18F2x[1,0]9C_x0D0F_E00A[CsrPhySrPllPdMode]==0) THEN program
+ // D18F2x[1,0]9C_x0D0F_E006[PllLockTime] = 0Fh.
+ if (!NBPtr->IsSupported[CsrPhyPllPdEn]) {
+ MemNBrdcstSetNb (NBPtr, BFPllLockTime, FinalPllLockTime);
+ }
+
+ FrequencyChangeSuccess = TRUE;
+ } else {
+ // If NB frequency cannot be updated, use the current speed as the target speed
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ NBPtr->DCTPtr->Timings.Speed = NBPtr->TechPtr->PrevSpeed;
+ NBPtr->DCTPtr->Timings.TargetSpeed = NBPtr->TechPtr->PrevSpeed;
+ }
+ FrequencyChangeSuccess = FALSE;
+ }
+
+ if (FrequencyChangeSuccess) {
+ // Perform Phy Fence training and Phy comp init after frequency change
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
+
+ // Phy fence programming
+ AGESA_TESTPOINT (TpProcMemPhyFenceTraining, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->PhyFenceTraining (NBPtr);
+
+ // Phy compensation initialization
+ AGESA_TESTPOINT (TPProcMemPhyCompensation, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->MemNInitPhyComp (NBPtr);
+ MemProcessConditionalOverrides (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr, PSO_ACTION_SLEWRATE, ALL_DIMMS);
+ }
+ }
+ }
+
+ //Program F2x[1,0]90[ExitSelfRef]=1 for both DCTs.
+ //Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0.
+ MemNBrdcstSetNb (NBPtr, BFExitSelfRef, 1);
+ MemNPollBitFieldNb (NBPtr, BFExitSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE);
+ if (NBPtr->IsSupported[SetDllShutDown]) {
+ MemNBrdcstSetNb (NBPtr, BFDisDllShutdownSR, 0);
+ }
+
+ if (FrequencyChangeSuccess) {
+ NBPtr->FamilySpecificHook[AfterMemClkFreqChg] (NBPtr, NULL);
+
+ //======================================================================
+ // Calculate and program DRAM Timings at new frequency
+ //======================================================================
+ //
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", Dct);
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel++) {
+ if ((NBPtr->DCTPtr->Timings.CsPresent & ((UINT16)1 << ChipSel)) != 0) {
+ // if chip select present
+ if (!(TechPtr->TechnologySpecificHook[LrdimmSendAllMRCmds] (TechPtr, &ChipSel))) {
+ TechPtr->SendAllMRCmds (TechPtr, ChipSel);
+ }
+ }
+ }
+ // Wait 512 clocks for DLL-relock
+ MemNWaitXMemClksNb (NBPtr, 512);
+ }
+ }
+ }
+
+ // Restore MMIO setting
+ LibAmdMsrWrite (MSR_MMIO_Cfg_Base, &OrgMMIOCfgBase, &(NBPtr->MemPtr->StdHeader));
+
+ MemFInitTableDrive (NBPtr, MTAfterFreqChg);
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates and programs NB P-state dependent registers
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNProgramNbPstateDependentRegistersUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 RdPtrInit;
+
+ RdPtrInit = (NBPtr->DCTPtr->Timings.Speed <= DDR1600_FREQUENCY) ? 6 : 4;
+ MemNBrdcstSetNb (NBPtr, BFRdPtrInit, RdPtrInit);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tRdPtr: %d\n", RdPtrInit);
+
+ MemFInitTableDrive (NBPtr, MTAfterNbPstateChange);
+
+ IDS_HDT_CONSOLE_DEBUG_CODE (
+ RdPtrInit = (UINT8) MemNGetBitFieldNb (NBPtr, BFRdPtrInit);
+ );
+
+ switch (RdPtrInit) {
+ case 4:
+ if (MemNGetBitFieldNb (NBPtr, BFNbPsSel) == 0) {
+ MemNBrdcstSetNb (NBPtr, BFDataTxFifoWrDly, 2);
+ } else {
+ MemNBrdcstSetNb (NBPtr, BFDataTxFifoWrDly, 1);
+ }
+ break;
+ case 5:
+ MemNBrdcstSetNb (NBPtr, BFDataTxFifoWrDly, 1);
+ break;
+ case 6:
+ MemNBrdcstSetNb (NBPtr, BFDataTxFifoWrDly, 0);
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ NBPtr->FamilySpecificHook[OverrideDataTxFifoWrDly] (NBPtr, NBPtr);
+ IDS_OPTION_HOOK (IDS_NBPS_REG_OVERRIDE, NBPtr, &NBPtr->MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+CONST UINT8 PllDivTab[] = {0, 0, 0, 2, 3, 3, 2, 3};
+CONST UINT8 PllMultTab[] = {0, 0, 0, 16, 32, 40, 32, 56};
+
+/**
+ *
+ * This function calculates and programs NB P-state dependent registers
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNProgramNbPstateDependentRegistersClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 i;
+ UINT8 Dct;
+ UINT8 NclkFid;
+ UINT16 MemClkDid;
+ UINT8 PllMult;
+ UINT8 NclkDiv;
+ UINT8 RdPtrInitMin;
+ UINT8 RdPtrInit;
+ UINT32 NclkPeriod;
+ UINT32 MemClkPeriod;
+ INT32 PartialSum2x;
+ INT32 PartialSumSlotI2x;
+ INT32 RdPtrInitRmdr2x;
+ INT32 TDataProp;
+ UINT8 NbPstate;
+ UINT8 SlowMode;
+ UINT32 CalcNclkDiv;
+ UINT32 DbeGskFifoNumeratorVal;
+ UINT32 DbeGskFifoDenominatorVal;
+
+ CalcNclkDiv = 0;
+ NclkFid = (UINT8) (MemNGetBitFieldNb (NBPtr, BFMainPllOpFreqId) + 0x10); // NclkFid is in 100MHz
+
+ MemClkDid = PllDivTab[NBPtr->DCTPtr->Timings.Speed / 133];
+ NBPtr->FamilySpecificHook[OverridePllDiv] (NBPtr, &MemClkDid);
+ PllMult = PllMultTab[NBPtr->DCTPtr->Timings.Speed / 133];
+ NBPtr->FamilySpecificHook[OverridePllMult] (NBPtr, &PllMult);
+
+ if (NBPtr->NbFreqChgState == 2) {
+ MemNSetBitFieldNb (NBPtr, BFNbPsCsrAccSel, 1);
+ MemNSetBitFieldNb (NBPtr, BFNbPsDbgEn, 1);
+ NclkDiv = (UINT8) MemNGetBitFieldNb (NBPtr, BFNbPs1NclkDiv);
+ // Divisors less than 8 are undefined. Maybe the CPU does not support NB P-states.
+ if (NclkDiv < 8) {
+ // Set a dummy divisor to prevent divide by zero exception below.
+ NclkDiv = 8;
+ }
+ NbPstate = 1;
+ } else {
+ NclkDiv = (UINT8) MemNGetBitFieldNb (NBPtr, BFNbPs0NclkDiv);
+ NbPstate = 0;
+ }
+
+ if (NclkDiv >= 0x60) {
+ CalcNclkDiv = (NclkDiv - 0x40) * 10000;
+ } else if (NclkDiv >= 0x40) {
+ CalcNclkDiv = ((NclkDiv - 0x40) * 5000) + 160000;
+ } else {
+ CalcNclkDiv = 2500 * NclkDiv;
+ }
+
+ NclkPeriod = CalcNclkDiv / NclkFid; // (1,000,000 * 0.25 * NclkDiv) / (NclkFid * 100MHz) = ps
+ MemClkPeriod = 1000000 / NBPtr->DCTPtr->Timings.Speed;
+ NBPtr->NBClkFreq = ((UINT32) NclkFid * 1000000) / CalcNclkDiv;
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\tNB P%d Freq: %dMHz\n", NbPstate, NBPtr->NBClkFreq);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClk Freq: %dMHz\n", NBPtr->DCTPtr->Timings.Speed);
+ // D18F2x[1,0]78[RdPtrInit] = IF (D18F2x[1,0]94[MemClkFreq] >= 667 MHz) THEN 7 ELSE 8 ENDIF (Llano)
+ // THEN 2 ELSE 3 ENDIF (Ontario)
+ RdPtrInit = RdPtrInitMin = (NBPtr->DCTPtr->Timings.Speed >= DDR1333_FREQUENCY) ? NBPtr->FreqChangeParam->RdPtrInit667orHigher : NBPtr->FreqChangeParam->RdPtrInitLower667;
+ NBPtr->FamilySpecificHook[AdjustRdPtrInit] (NBPtr, &RdPtrInit);
+ MemNBrdcstSetNb (NBPtr, BFRdPtrInit, RdPtrInit);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tRdPtr: %d\n", RdPtrInit);
+
+ // Program D18F2x[1,0]F4_x30[DbeGskFifoNumerator] and D18F2x[1,0]F4_x31[DbeGskFifoDenominator].
+ DbeGskFifoNumeratorVal = NclkFid * MemClkDid * 16;
+ DbeGskFifoDenominatorVal = NclkDiv * PllMult;
+ if (NclkDiv >= 0x40) {
+ DbeGskFifoNumeratorVal = NclkFid * MemClkDid * 4;
+ DbeGskFifoDenominatorVal = CalcNclkDiv * PllMult / 10000;
+ }
+ MemNBrdcstSetNb (NBPtr, BFDbeGskFifoNumerator, DbeGskFifoNumeratorVal);
+ MemNBrdcstSetNb (NBPtr, BFDbeGskFifoDenominator, DbeGskFifoDenominatorVal);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDbeGskFifoNumerator: %d\n", DbeGskFifoNumeratorVal);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDbeGskFifoDenominator: %d\n", DbeGskFifoDenominatorVal);
+
+ // Program D18F2x[1,0]F4_x32[DataTxFifoSchedDlyNegSlot1, DataTxFifoSchedDlySlot1,
+ // DataTxFifoSchedDlyNegSlot0, DataTxFifoSchedDlySlot0].
+ // PartialSum = ((7 * NclkPeriod) + (1.5 * MemClkPeriod) + 520ps)*MemClkFrequency - tCWL -
+ // CmdSetup - PtrSeparation - 1. (Llano)
+ // PartialSum = ((5 * NclkPeriod) + MemClkPeriod) + 520ps)*MemClkFrequency - tCWL -
+ // CmdSetup - PtrSeparation - 1. (Ontario)
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ PartialSum2x = NBPtr->FreqChangeParam->NclkPeriodMul2x * NclkPeriod;
+ PartialSum2x += NBPtr->FreqChangeParam->MemClkPeriodMul2x * MemClkPeriod;
+ PartialSum2x += 520 * 2;
+
+ // PtrSeparation = ((16 + RdPtrInitMin - D18F2x[1,0]78[RdPtrInit]) MOD 16)/2 + RdPtrInitRmdr
+ // If (D18F2x[1,0]94[MemClkFreq] >= 800 MHz)
+ // then RdPtrInitRmdr = (((4.5 * MemClkPeriod) - 990ps) MOD MemClkPeriod)/MemClkPeriod
+ // else RdPtrInitRmdr = (((4.5 * MemClkPeriod) - 1466ps) MOD MemClkPeriod)/MemClkPeriod
+ TDataProp = (NBPtr->DCTPtr->Timings.Speed >= DDR1600_FREQUENCY) ?
+ NBPtr->FreqChangeParam->TDataProp800orHigher : NBPtr->FreqChangeParam->TDataPropLower800;
+ RdPtrInitRmdr2x = ((NBPtr->FreqChangeParam->SyncTimeMul4x * MemClkPeriod) / 2) - 2 * (TDataProp + 520);
+ RdPtrInitRmdr2x %= MemClkPeriod;
+ PartialSum2x -= ((16 + RdPtrInitMin - RdPtrInit) % 16) * MemClkPeriod + RdPtrInitRmdr2x;
+
+ // Convert PartialSum2x to PCLK
+ PartialSum2x = (PartialSum2x + MemClkPeriod - 1) / MemClkPeriod; // round-up here
+ PartialSum2x -= 2 * (MemNGetBitFieldNb (NBPtr, BFTcwl) + 5);
+ if ((MemNGetBitFieldNb (NBPtr, BFAddrTmgControl) & 0x0202020) == 0) {
+ PartialSum2x -= 1;
+ } else {
+ PartialSum2x -= 2;
+ }
+ PartialSum2x -= 2;
+
+ // If PartialSumSlotN is positive:
+ // DataTxFifoSchedDlySlotN=CEIL(PartialSumSlotN).
+ // DataTxFifoSchedDlyNegSlotN=0.
+ // Else if PartialSumSlotN is negative:
+ // DataTxFifoSchedDlySlotN=ABS(CEIL(PartialSumSlotN*MemClkPeriod/NclkPeriod)).
+ // DataTxFifoSchedDlyNegSlotN=1.
+ for (i = 0; i < 2; i++) {
+ PartialSumSlotI2x = PartialSum2x;
+ SlowMode = (UINT8) MemNGetBitFieldNb (NBPtr, BFSlowAccessMode);
+ if ((i == 0) && (SlowMode == 0)) {
+ PartialSumSlotI2x += 2;
+ }
+ if (NBPtr->IsSupported[SchedDlySlot1Extra] && (i == 1) && (SlowMode != 0)) {
+ PartialSumSlotI2x -= 2;
+ }
+ if (PartialSumSlotI2x > 0) {
+ MemNSetBitFieldNb (NBPtr, BFDataTxFifoSchedDlyNegSlot0 + i, 0);
+ MemNSetBitFieldNb (NBPtr, BFDataTxFifoSchedDlySlot0 + i, (PartialSumSlotI2x + 1) / 2);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDataTxFifoSchedDlySlot%d: %d\n", i, (PartialSumSlotI2x + 1) / 2);
+ } else {
+ MemNSetBitFieldNb (NBPtr, BFDataTxFifoSchedDlyNegSlot0 + i, 1);
+ PartialSumSlotI2x = ((-PartialSumSlotI2x) * MemClkPeriod) / (2 * NclkPeriod);
+ MemNSetBitFieldNb (NBPtr, BFDataTxFifoSchedDlySlot0 + i, PartialSumSlotI2x);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDataTxFifoSchedDlySlot%d: -%d\n", i, PartialSumSlotI2x);
+ }
+ }
+
+ // Set ProcOdtAdv
+ if ((NBPtr->DCTPtr->Timings.Speed <= DDR1333_FREQUENCY) &&
+ ((!(NBPtr->IsSupported[EnProcOdtAdvForUDIMM])) || (NBPtr->ChannelPtr->SODimmPresent != 0))) {
+ MemNSetBitFieldNb (NBPtr, BFProcOdtAdv, 0);
+ } else {
+ MemNSetBitFieldNb (NBPtr, BFProcOdtAdv, 0x4000);
+ }
+ }
+ }
+
+ MemFInitTableDrive (NBPtr, MTAfterNbPstateChange);
+ if (NBPtr->NbFreqChgState == 2) {
+ MemNSetBitFieldNb (NBPtr, BFNbPsDbgEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFNbPsCsrAccSel, 0);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the total of sync components for Max Read Latency calculation
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return Total in ps
+ */
+
+UINT32
+MemNTotalSyncComponentsClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 P;
+ UINT32 T;
+ UINT8 RdPtrInitMin;
+ UINT8 RdPtrInit;
+ UINT32 AddrTmgCtl;
+ UINT8 DbeGskMemClkAlignMode;
+ UINT32 MemClkPeriod;
+
+ // P = P + ((16 + RdPtrInitMin - D18F2x[1,0]78[RdPtrInit]) MOD 16)
+ RdPtrInitMin = (NBPtr->DCTPtr->Timings.Speed >= DDR1333_FREQUENCY) ? NBPtr->FreqChangeParam->RdPtrInit667orHigher : NBPtr->FreqChangeParam->RdPtrInitLower667;
+ RdPtrInit = (UINT8) MemNGetBitFieldNb (NBPtr, BFRdPtrInit);
+ P = (16 + RdPtrInitMin - RdPtrInit) % 16;
+
+ // IF (AddrCmdSetup != CkeSetup) THEN P = P + 1
+ AddrTmgCtl = MemNGetBitFieldNb (NBPtr, BFAddrTmgControl);
+ if (((AddrTmgCtl >> 16) & 0x20) != (AddrTmgCtl & 0x20)) {
+ P += 1;
+ }
+
+ // IF (DbeGskMemClkAlignMode==01b || (DbeGskMemClkAlignMode==00b && !(AddrCmdSetup==CsOdtSetup==CkeSetup)))
+ // THEN P = P + 1
+ DbeGskMemClkAlignMode = (UINT8) MemNGetBitFieldNb (NBPtr, BFDbeGskMemClkAlignMode);
+ if ((DbeGskMemClkAlignMode == 1) || ((DbeGskMemClkAlignMode == 0) &&
+ !((((AddrTmgCtl >> 16) & 0x20) == (AddrTmgCtl & 0x20)) && (((AddrTmgCtl >> 8) & 0x20) == (AddrTmgCtl & 0x20))))) {
+ P += 1;
+ }
+
+ // IF (SlowAccessMode==1) THEN P = P + 2
+ if (MemNGetBitFieldNb (NBPtr, BFSlowAccessMode) == 1) {
+ P += 2;
+ }
+
+ // P = P + 2
+ P += 2;
+ T = 0;
+
+ // If (AddrCmdSetup==0 && CsOdtSetup==0 && CkeSetup==0)
+ // then P = P + 1
+ // else P = P + 2
+ if ((AddrTmgCtl & 0x0202020) == 0) {
+ P += 1;
+ } else {
+ P += 2;
+ }
+
+ // P = P + (2 * (D18F2x[1,0]88[Tcl] clocks - 1))
+ P += 2 * (NBPtr->DCTPtr->Timings.CasL - 1);
+
+ // If (DisCutThroughMode==0)
+ // then P = P + 3
+ // else P = P + 7
+ if (MemNGetBitFieldNb (NBPtr, BFDisCutThroughMode) == 0) {
+ P += 3;
+ } else {
+ P += 7;
+ }
+
+ MemClkPeriod = 1000000 / NBPtr->DCTPtr->Timings.Speed;
+ return (((P * MemClkPeriod + 1) / 2) + T);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets up phy power saving for client NB
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNPhyPowerSavingClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ // 4. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]13[DllDisEarlyU] = 1b.
+ // 5. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]13[DllDisEarlyL] = 1b.
+ // 6. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]13[7:4] = 1010b.
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D0F0F13Bit0to7, 0xA3);
+ // 7. Program D18F2x[1,0]9C_x0D0F_812F[7, 5, 0] = {1b, 1b, 1b} to disable unused PAR and A[17:16] pins.
+ MemNSetBitFieldNb (NBPtr, BFAddrCmdTri, MemNGetBitFieldNb (NBPtr, BFAddrCmdTri) | 0xA1);
+ // 8. Program D18F2x[1,0]9C_x0D0F_C000[LowPowerDrvStrengthEn] = 1.
+ if (!NBPtr->FamilySpecificHook[DisLowPwrDrvStr] (NBPtr, NULL)) {
+ MemNSetBitFieldNb (NBPtr, BFLowPowerDrvStrengthEn, 0x100);
+ }
+ // 9. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]10[EnRxPadStandby]= IF (D18F2x[1,0]94[MemClkFreq] <=
+ // 800 MHz) THEN 1 ELSE 0 ENDIF.
+ MemNSetBitFieldNb (NBPtr, BFEnRxPadStandby, (NBPtr->DCTPtr->Timings.Speed <= DDR1600_FREQUENCY) ? 0x1000 : 0);
+ // 10. Program D18F2x[1,0]9C_x0000_000D as follows:
+ // TxMaxDurDllNoLock/RxMaxDurDllNoLock = 7h.
+ MemNSetBitFieldNb (NBPtr, BFRxMaxDurDllNoLock, 7);
+ MemNSetBitFieldNb (NBPtr, BFTxMaxDurDllNoLock, 7);
+ // TxCPUpdPeriod/RxCPUpdPeriod = 011b.
+ MemNSetBitFieldNb (NBPtr, BFTxCPUpdPeriod, 3);
+ MemNSetBitFieldNb (NBPtr, BFRxCPUpdPeriod, 3);
+ // TxDLLWakeupTime/RxDLLWakeupTime = 11b.
+ MemNSetBitFieldNb (NBPtr, BFTxDLLWakeupTime, 3);
+ MemNSetBitFieldNb (NBPtr, BFRxDLLWakeupTime, 3);
+
+ IDS_OPTION_HOOK (IDS_PHY_DLL_STANDBY_CTRL, NBPtr, &NBPtr->MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets up phy power saving for UNB
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNPhyPowerSavingUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT16 MixedX4AndX8Dimms;
+
+ // 4. Program D18F2x9C_x0D0F_0[F,8:0]13_dct[1:0][DllDisEarlyU] = 1b.
+ // 5. Program D18F2x9C_x0D0F_0[F,8:0]13_dct[1:0][DllDisEarlyL] = 1b.
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D0F0F13, MemNGetBitFieldNb (NBPtr, BFPhy0x0D0F0F13) | 3);
+ // 6. D18F2x9C_x0D0F_0[F,8:0]13_dct[1:0][RxDqsUDllPowerDown] = (D18F2x90_dct[1:0][X4Dimm]!=0).
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D0F0F13, MemNGetBitFieldNb (NBPtr, BFX4Dimm) == 0 ? (MemNGetBitFieldNb (NBPtr, BFPhy0x0D0F0F13) | 0x80) : (MemNGetBitFieldNb (NBPtr, BFPhy0x0D0F0F13) & 0xFF7F));
+ // 7. D18F2x9C_x0D0F_812F_dct[1:0][PARTri] = ~D18F2x90_dct[1:0][ParEn].
+ MemNSetBitFieldNb (NBPtr, BFAddrCmdTri, MemNGetBitFieldNb (NBPtr, BFParEn) == 0 ? (MemNGetBitFieldNb (NBPtr, BFAddrCmdTri) | 1) : (MemNGetBitFieldNb (NBPtr, BFAddrCmdTri) & 0xFFFE));
+ // 8. D18F2x9C_x0D0F_812F_dct[1:0][Add17Tri, Add16Tri] = {1b, 1b}
+ MemNSetBitFieldNb (NBPtr, BFAddrCmdTri, MemNGetBitFieldNb (NBPtr, BFAddrCmdTri) | 0xA0);
+ // 9. IF (D18F2x94_dct[1:0][MemClkFreq] <= 800 MHz && ~(mixed channel of x4 and x8 DIMMs)) THEN
+ // Program D18F2x9C_x0D0F_0[F,8:0]10_dct[1:0][EnRxPadStandby] = 1.
+ // ELSE
+ // Program D18F2x9C_x0D0F_0[F,8:0]10_dct[1:0][EnRxPadStandby] = 0.
+ // ENDIF.
+ MixedX4AndX8Dimms = NBPtr->DCTPtr->Timings.Dimmx4Present != 0 && NBPtr->DCTPtr->Timings.Dimmx8Present != 0;
+ MemNSetBitFieldNb (NBPtr, BFEnRxPadStandby, (NBPtr->DCTPtr->Timings.Speed <= DDR1600_FREQUENCY) && !MixedX4AndX8Dimms ? 0x1000 : 0);
+ // 10. IF (~(mixed channel of x4 and x8 DIMMs)) THEN
+ if (MixedX4AndX8Dimms == FALSE) {
+ // Program D18F2x9C_x0000_000D_dct[1:0] as follows:
+ // TxMaxDurDllNoLock = RxMaxDurDllNoLock = 7h.
+ MemNSetBitFieldNb (NBPtr, BFTxMaxDurDllNoLock, 7);
+ MemNSetBitFieldNb (NBPtr, BFRxMaxDurDllNoLock, 7);
+ // TxCPUpdPeriod = RxCPUpdPeriod = 011b.
+ MemNSetBitFieldNb (NBPtr, BFTxCPUpdPeriod, 3);
+ MemNSetBitFieldNb (NBPtr, BFRxCPUpdPeriod, 3);
+ // TxDLLWakeupTime = RxDLLWakeupTime = 11b.
+ MemNSetBitFieldNb (NBPtr, BFTxDLLWakeupTime, 3);
+ MemNSetBitFieldNb (NBPtr, BFRxDLLWakeupTime, 3);
+ } else {
+ // ELSE
+ // Program D18F2x9C_x0000_000D_dct[1:0][TxMaxDurDllNoLock, RxMaxDurDllNoLock, TxCPUpdPeriod,
+ // RxCPUpdPeriod, TxDLLWakeupTime, RxDLLWakeupTime] = {0, 0, 0, 0, 0, 0}.
+ MemNSetBitFieldNb (NBPtr, BFTxMaxDurDllNoLock, 0);
+ MemNSetBitFieldNb (NBPtr, BFRxMaxDurDllNoLock, 0);
+ MemNSetBitFieldNb (NBPtr, BFTxCPUpdPeriod, 0);
+ MemNSetBitFieldNb (NBPtr, BFRxCPUpdPeriod, 0);
+ MemNSetBitFieldNb (NBPtr, BFTxDLLWakeupTime, 0);
+ MemNSetBitFieldNb (NBPtr, BFRxDLLWakeupTime, 0);
+ }
+ // 11. Program D18F2x9C_x0D0F_0[F,8:0]30_dct[1:0][PwrDn] to disable unused ECC byte lane.
+ if (NBPtr->IsSupported[CheckEccDLLPwrDnConfig]) {
+ if (!NBPtr->MCTPtr->Status[SbEccDimms]) {
+ MemNSetBitFieldNb (NBPtr, BFEccDLLPwrDnConf, 0x0010);
+ }
+ }
+
+ // 12. Program D18F2x9C_x0D0F_0[F,8:0]04_dct[1:0][TriDM] = IF (LRDIMM & (D18F2x90_dct[1:0][X4Dimm] == 0)) THEN 1 ELSE 0.
+ if (NBPtr->MCTPtr->Status[SbLrdimms]) {
+ MemNSetBitFieldNb (NBPtr, BFDataByteDMConf, (MemNGetBitFieldNb (NBPtr, BFX4Dimm) == 0) ? 0x2000 : 0);
+ }
+
+ IDS_OPTION_HOOK (IDS_PHY_DLL_STANDBY_CTRL, NBPtr, &NBPtr->MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function overrides the ASR and SRT value in MRS command
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNSetASRSRTNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 MrsAddress;
+ UINT8 Dimm;
+ UINT8 *SpdBufferPtr;
+ BOOLEAN ASREn;
+ BOOLEAN SRTEn;
+
+ // Look for MR2
+ if (NBPtr->GetBitField (NBPtr, BFMrsBank) == 2) {
+ MrsAddress = NBPtr->GetBitField (NBPtr, BFMrsAddress);
+ // Clear A6(ASR) and A7(SRT)
+ MrsAddress &= (UINT32) ~0xC0;
+ if ((NBPtr->ChannelPtr->RegDimmPresent) || (NBPtr->ChannelPtr->LrDimmPresent)) {
+ // For registered dimm and LR dimm, MRS command is sent to all chipselects.
+ // So different ASR/SRT setting can be sent to each chip select.
+ Dimm = (UINT8) (NBPtr->GetBitField (NBPtr, BFMrsChipSel) >> 1);
+ // Make sure we access SPD of the second logical dimm of QR dimm correctly
+ if ((Dimm >= 2) && ((NBPtr->ChannelPtr->DimmQrPresent & (UINT8) (1 << Dimm)) != 0)) {
+ Dimm -= 2;
+ }
+ if (NBPtr->TechPtr->GetDimmSpdBuffer (NBPtr->TechPtr, &SpdBufferPtr, Dimm)) {
+ // Bit 2 is ASR
+ if (SpdBufferPtr[THERMAL_OPT] & 0x4) {
+ // when ASR is 1, set SRT to 0
+ MrsAddress |= 0x40;
+ } else {
+ // Set SRT based on bit on of thermal byte
+ MrsAddress |= ((SpdBufferPtr[THERMAL_OPT] & 1) << 7);
+ }
+ }
+ } else {
+ // Udimm and unbuffered dimm, MSR command will be broadcasted during Dram Init.
+ // ASR/SRT value needs to be leveled across the DCT. Only if all dimms on the DCT
+ // support ASR or SRT can ASR or SRT be enabled.
+ ASREn = TRUE;
+ SRTEn = TRUE;
+ for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm ++) {
+ if (NBPtr->TechPtr->GetDimmSpdBuffer (NBPtr->TechPtr, &SpdBufferPtr, Dimm)) {
+ // Bit 2 is ASR
+ if ((SpdBufferPtr[THERMAL_OPT] & 0x4) == 0) {
+ // when any dimm in the DCT does not support ASR, disable ASR for the DCT
+ ASREn = FALSE;
+ // When any dimm does not have SRT with a value of 1, set SRT to 0 for the DCT
+ if ((SpdBufferPtr[THERMAL_OPT] & 1) == 0) {
+ SRTEn = FALSE;
+ }
+ }
+ }
+ }
+ if (ASREn) {
+ MrsAddress |= 0x40;
+ } else {
+ MrsAddress |= (UINT8) SRTEn << 7;
+ }
+ }
+
+ NBPtr->SetBitField (NBPtr, BFMrsAddress, MrsAddress);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function changes NB frequency as below:
+ * NBP0-DDR800 -> NBP0-DDR1066 -> ... -> NBP0-DDRTarget -> NBP1-DDRTarget -> NBP0-DDRTarget
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+BOOLEAN
+MemNChangeNbFrequencyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ BOOLEAN Status;
+
+ Status = FALSE;
+
+ // State machine to change NB frequency and NB Pstate
+ switch (NBPtr->NbFreqChgState) {
+ case 0:
+ // Starting up by not changing NB P state, but only updating NB frequency based on current MemClk frequency
+ Status = NBPtr->ChangeNbFrequencyWrap (NBPtr, 0);
+ ASSERT (Status);
+
+ if (NBPtr->DCTPtr->Timings.Speed == NBPtr->DCTPtr->Timings.TargetSpeed) {
+ // When MemClk has been ramped up to its max, transition to next state, which changes NBPstate to P1
+ NBPtr->NbFreqChgState = 1;
+ IDS_OPTION_HOOK (IDS_NB_PSTATE_DIDVID, NBPtr, &(NBPtr->MemPtr->StdHeader));
+ }
+ break;
+
+ case 1:
+ // Clear ForceCasToSlot0 after MaxRdLatency training is completed for NB-P0
+ MemNBrdcstSetNb (NBPtr, BFForceCasToSlot0, 0);
+
+ // Next state would be to change NBPstate back to P0
+ NBPtr->NbFreqChgState = 2;
+
+ // Update NB freq dependent registers
+ NBPtr->ProgramNbPsDependentRegs (NBPtr);
+
+ // Change NB P-State to NBP1 for MaxRdLat training
+ if (NBPtr->ChangeNbFrequencyWrap (NBPtr, 1)) {
+ // Enable cut through mode for NB P1
+ MemNBrdcstSetNb (NBPtr, BFDisCutThroughMode, 0);
+
+ // Return TRUE to repeat MaxRdLat training
+ Status = TRUE;
+
+ } else {
+ // If transition to NB-P1 fails, transition to exit state machine
+ NBPtr->NbFreqChgState = 3;
+ }
+ break;
+
+ case 2:
+ // Clear ForceCasToSlot0 after MaxRdLatency training is completed for NB-P1
+ MemNBrdcstSetNb (NBPtr, BFForceCasToSlot0, 0);
+
+ // Change NB P-State back to NBP0
+ Status = NBPtr->ChangeNbFrequencyWrap (NBPtr, 0);
+ ASSERT (Status);
+
+ // Return FALSE to get out of MaxRdLat training loop
+ Status = FALSE;
+
+ // Exit state machine
+ NBPtr->NbFreqChgState = 3;
+ break;
+
+ default:
+ break;
+ }
+
+ return Status;
+}
+
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function programs registers before phy fence training for CNB
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNBeforePhyFenceTrainingClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClkAlign=0\n");
+ MemNBrdcstSetNb (NBPtr, BFDbeGskMemClkAlignMode, 0);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tEnDramInit = 1 for both DCTs\n");
+ MemNBrdcstSetNb (NBPtr, BFEnDramInit, 1);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function changes NB frequency foras below:
+ * NBP0-DDR800 -> NBP0-DDR1066 -> ... -> NBP0-DDRTarget -> NBP1-DDRTarget -> NBP2-DDRTarget -> NBP3-DDRTarget -> NBP0-DDRTarget
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+BOOLEAN
+MemNChangeNbFrequencyUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ BOOLEAN Status;
+
+ Status = FALSE;
+
+ // State machine to change NB frequency and NB Pstate
+ switch (NBPtr->NbFreqChgState) {
+ case 0:
+ // Do not change NB Pstate, just to save initial NB Pstate value
+ Status = NBPtr->ChangeNbFrequencyWrap (NBPtr, 0);
+ if (NBPtr->DCTPtr->Timings.Speed == NBPtr->DCTPtr->Timings.TargetSpeed) {
+ // When MemClk has been ramped up to its max, transition to next state, which changes NBPstate to P1
+ NBPtr->NbFreqChgState = 1;
+ IDS_OPTION_HOOK (IDS_NB_PSTATE_DIDVID, NBPtr, &(NBPtr->MemPtr->StdHeader));
+ }
+ break;
+
+ case 1:
+ case 2:
+ case 3:
+ // Change NB P-State to NBP1 for MaxRdLat training
+ if (NBPtr->ChangeNbFrequencyWrap (NBPtr, NBPtr->NbFreqChgState)) {
+ // Next state is to try all NBPstates
+ NBPtr->NbFreqChgState++;
+
+ // Return TRUE to repeat MaxRdLat training
+ Status = TRUE;
+ } else {
+ // If transition to any NBPs fails, transition to exit state machine
+ NBPtr->NbFreqChgState = 4;
+ }
+ break;
+
+ case 4:
+ // Change NB P-State back to NBP0
+ Status = NBPtr->ChangeNbFrequencyWrap (NBPtr, 0);
+ ASSERT (Status);
+
+ // Return FALSE to get out of MaxRdLat training loop
+ Status = FALSE;
+
+ // Exit state machine
+ NBPtr->NbFreqChgState = 5;
+ break;
+
+ default:
+ break;
+ }
+
+ return Status;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets "Dram Term" value from data structure
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] ChipSel - Targeted chipsel
+ *
+ * @return Dram Term value
+ */
+UINT8
+MemNGetDramTermNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 ChipSel
+ )
+{
+ UINT8 DramTerm;
+
+ if ((NBPtr->ChannelPtr->DimmQrPresent & ((UINT16) (1 << (ChipSel >> 1)))) != 0) {
+ DramTerm = NBPtr->PsPtr->QR_DramTerm;
+ } else {
+ DramTerm = NBPtr->PsPtr->DramTerm;
+ }
+
+ return DramTerm;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets "Dram Term" value from data structure for Unb
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] ChipSel - Targeted chipsel
+ *
+ * @return Dram Term value
+ */
+UINT8
+MemNGetDramTermTblDrvNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 ChipSel
+ )
+{
+ UINT8 RttNom;
+ RttNom = NBPtr->PsPtr->RttNom[ChipSel];
+ IDS_OPTION_HOOK (IDS_MEM_DRAM_TERM, &RttNom, &NBPtr->MemPtr->StdHeader);
+ return RttNom;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets "Dynamic Dram Term" value from data structure
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] ChipSel - Targeted chipsel
+ *
+ * @return Dynamic Dram Term value
+ */
+UINT8
+MemNGetDynDramTermNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 ChipSel
+ )
+{
+ return (NBPtr->PsPtr->DynamicDramTerm);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets "Dynamic Dram Term" value from data structure
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] ChipSel - Targeted chipsel
+ *
+ * @return Dynamic Dram Term value
+ */
+UINT8
+MemNGetDynDramTermTblDrvNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 ChipSel
+ )
+{
+ UINT8 RttWr;
+ RttWr = NBPtr->PsPtr->RttWr[ChipSel];
+ IDS_OPTION_HOOK (IDS_MEM_DYN_DRAM_TERM, &RttWr, &NBPtr->MemPtr->StdHeader);
+ return RttWr;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns MR0[CL] value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return MR0[CL] value
+ */
+UINT32
+MemNGetMR0CLNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Tcl;
+ UINT32 Value32;
+
+ Tcl = (UINT8) MemNGetBitFieldNb (NBPtr, BFTcl);
+ Value32 = (UINT32) ((Tcl < 8) ? (Tcl << 4) : (((Tcl - 8) << 4) | 4));
+
+ return Value32;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns MR0[WR] value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return MR0[WR] value
+ */
+UINT32
+MemNGetMR0WRNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 Value32;
+
+ Value32 = MemNGetBitFieldNb (NBPtr, BFTwrDDR3) << 9;
+
+ return Value32;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns MR0[WR] value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return MR0[WR] value
+ */
+UINT32
+MemNGetMR0WRTblDrvNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ return (UINT32) (NBPtr->PsPtr->MR0WR << 9);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns MR2[CWL] value
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return MR0[CWL] value
+ */
+UINT32
+MemNGetMR2CWLNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 Value32;
+
+ Value32 = MemNGetBitFieldNb (NBPtr, BFTcwl) << 3;
+
+ return Value32;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function returns MR2[CWL] value for UNB
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return MR0[CWL] value
+ */
+UINT32
+MemNGetMR2CWLUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 Value32;
+
+ Value32 = (MemNGetBitFieldNb (NBPtr, BFTcwl) - 5) << 3;
+
+ return Value32;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets Txp and Txpdll
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return none
+ */
+VOID
+MemNSetTxpNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST UINT8 Txp[] = {0xFF, 0xFF, 3, 3, 4, 4, 5, 6, 7};
+ CONST UINT8 Txpdll[] = {0xFF, 0xFF, 0xA, 0xA, 0xD, 0x10, 0x14, 0x17, 0x1A};
+ UINT8 i;
+ UINT8 TxpVal;
+ UINT8 TxpdllVal;
+ UINT16 Speed;
+
+ Speed = NBPtr->DCTPtr->Timings.Speed;
+ i = (UINT8) ((Speed < DDR800_FREQUENCY) ? ((Speed / 66) - 3) : (Speed / 133));
+ ASSERT (i < sizeof (Txp));
+ ASSERT (i < sizeof (Txpdll));
+
+ TxpdllVal = Txpdll[i];
+
+ if ((NBPtr->MCTPtr->Status[SbLrdimms] || NBPtr->MCTPtr->Status[SbRegistered]) &&
+ ((NBPtr->DCTPtr->Timings.Speed == DDR667_FREQUENCY) || (NBPtr->DCTPtr->Timings.Speed == DDR800_FREQUENCY)) &&
+ (NBPtr->RefPtr->DDR3Voltage == VOLT1_25)) {
+ TxpVal = 4;
+ } else {
+ TxpVal = Txp[i];
+ }
+
+ if (TxpVal != 0xFF) {
+ MemNSetBitFieldNb (NBPtr, BFTxp, TxpVal);
+ }
+ if (TxpdllVal != 0xFF) {
+ NBPtr->FamilySpecificHook[AdjustTxpdll] (NBPtr, &TxpdllVal);
+ MemNSetBitFieldNb (NBPtr, BFTxpdll, TxpdllVal);
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function adjust value of Txpdll to encoded value.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNAdjustTxpdllClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ *(UINT8 *) OptParam -= 10;
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function is a wrapper to handle or switch NB Pstate for UNB
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *NBPstate - NB Pstate
+ *
+ * @return TRUE - Succeed
+ * @return FALSE - Fail
+ */
+
+BOOLEAN
+MemNChangeNbFrequencyWrapUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 NBPstate
+ )
+{
+ UINT8 TargetNbPs;
+ UINT32 FreqNumeratorInMHz;
+ UINT32 FreqDivisor;
+ UINT32 VoltageInuV;
+ UINT8 NbPstateMaxVal;
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+
+ if (NBPtr->NbFreqChgState == 0) {
+ // While in state 0, keep NB Pstate at the highest supported
+ TargetNbPs = 0;
+ if (NBPtr->NbPsCtlReg == 0) {
+ // Save NbPsCtl register on the first run
+ NBPtr->NbPsCtlReg = MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg);
+ } else {
+ // Do not need to switch NB Pstate again if it is already at highest
+ return TRUE;
+ }
+ } else if (NBPtr->NbFreqChgState < 4) {
+ // While in other states, go to the next lower NB Pstate
+ TargetNbPs = (UINT8) MemNGetBitFieldNb (NBPtr, BFCurNbPstate) + 1;
+ if (TargetNbPs == 1) {
+ // Set up intermediate NBPstate
+ NbPstateMaxVal = (UINT8) MemNGetBitFieldNb (NBPtr, BFNbPstateMaxVal);
+ MemNSetBitFieldNb (NBPtr, BFNbPsSel, NbPstateMaxVal);
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &NBPtr->MemPtr->StdHeader);
+ if (FamilySpecificServices->GetNbPstateInfo (FamilySpecificServices,
+ NBPtr->MemPtr->PlatFormConfig,
+ &NBPtr->PciAddr,
+ (UINT32) NbPstateMaxVal,
+ &FreqNumeratorInMHz,
+ &FreqDivisor,
+ &VoltageInuV,
+ &(NBPtr->MemPtr->StdHeader))) {
+ // Get NCLK speed for intermediate NBPstate
+ NBPtr->NBClkFreq = FreqNumeratorInMHz / FreqDivisor;
+ NBPtr->ProgramNbPsDependentRegs (NBPtr);
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ } else {
+ // When done with training, release NB Pstate force by restoring NbPsCtl register
+ NBPtr->FamilySpecificHook[ReleaseNbPstate] (NBPtr, NBPtr);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tRelease NB Pstate force\n");
+ return TRUE;
+ }
+
+ // Make sure target NB Pstate is enabled, else find next enabled NB Pstate
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &NBPtr->MemPtr->StdHeader);
+ for (; TargetNbPs < 4; TargetNbPs++) {
+ if (FamilySpecificServices->GetNbPstateInfo (FamilySpecificServices,
+ NBPtr->MemPtr->PlatFormConfig,
+ &NBPtr->PciAddr,
+ (UINT32) TargetNbPs,
+ &FreqNumeratorInMHz,
+ &FreqDivisor,
+ &VoltageInuV,
+ &(NBPtr->MemPtr->StdHeader))) {
+ // Record NCLK speed
+ NBPtr->NBClkFreq = FreqNumeratorInMHz / FreqDivisor;
+ break;
+ }
+ }
+
+ if (TargetNbPs < 4) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tNB P%d: %dMHz\n", TargetNbPs, NBPtr->NBClkFreq);
+
+ // 1.Program the configuration registers which contain multiple internal copies for each NB P-state. See
+ // D18F1x10C[NbPsSel].
+ MemNSetBitFieldNb (NBPtr, BFNbPsSel, TargetNbPs);
+
+ // Check to see if NB P-states have been disabled. @todo This should only be needed for
+ // bring up, but must be included in any releases that occur before NB P-state operation
+ // has been debugged/fixed.
+ if ((NBPtr->NbPsCtlReg & 0x00000003) != 0) {
+ NbPstateMaxVal = (UINT8) MemNGetBitFieldNb (NBPtr, BFNbPstateMaxVal);
+ // Set up RdPtrInit before transit to target NBPstate
+ if ((TargetNbPs > 0) && (TargetNbPs != NbPstateMaxVal)) {
+ NBPtr->ProgramNbPsDependentRegs (NBPtr);
+ }
+
+ // If current NBPstate is already in NBPstateLo, do not do transition to NBPstateLo.
+ if ((TargetNbPs != 0) || (MemNGetBitFieldNb (NBPtr, BFNbPstateLo) != MemNGetBitFieldNb (NBPtr, BFCurNbPstate))) {
+ // 2.Program D18F5x170 to transition the NB P-state:
+ // NbPstateLo = NbPstateMaxVal. (HW requires an intermediate transition to low)
+ // SwNbPstateLoDis = NbPstateDisOnP0 = NbPstateThreshold = 0.
+ MemNSetBitFieldNb (NBPtr, BFNbPstateLo, NbPstateMaxVal);
+ MemNSetBitFieldNb (NBPtr, BFNbPstateCtlReg, MemNGetBitFieldNb (NBPtr, BFNbPstateCtlReg) & 0xFFFF91FF);
+
+ // 3.Wait for D18F5x174[CurNbPstate] to equal NbPstateLo.
+ MemNPollBitFieldNb (NBPtr, BFCurNbPstate, NbPstateMaxVal, PCI_ACCESS_TIMEOUT, FALSE);
+ }
+ // 4.Program D18F5x170 to force the NB P-state:
+ // NbPstateHi = target NB P-state.
+ // SwNbPstateLoDis = 1 (triggers the transition)
+ MemNSetBitFieldNb (NBPtr, BFNbPstateHi, TargetNbPs);
+ MemNSetBitFieldNb (NBPtr, BFSwNbPstateLoDis, 1);
+
+ // 5.Wait for D18F5x174[CurNbPstate] to equal the target NB P-state.
+ MemNPollBitFieldNb (NBPtr, BFCurNbPstate, TargetNbPs, PCI_ACCESS_TIMEOUT, FALSE);
+ }
+
+ // When NB frequency change succeeds, TSC rate may have changed.
+ // We need to update TSC rate
+ FamilySpecificServices->GetTscRate (FamilySpecificServices, &NBPtr->MemPtr->TscRate, &NBPtr->MemPtr->StdHeader);
+ // Switch MemPstate context if the current MemPstate does not sync with MemPstate context
+ if (MemNGetBitFieldNb (NBPtr, BFCurMemPstate) != MemNGetBitFieldNb (NBPtr, BFMemPsSel)) {
+ MemNChangeMemPStateContextNb (NBPtr, MemNGetBitFieldNb (NBPtr, BFCurMemPstate));
+ }
+ } else {
+ // Cannot find a supported NB Pstate to switch to
+ // Release NB Pstate force by restoring NbPsCtl register
+ NBPtr->FamilySpecificHook[ReleaseNbPstate] (NBPtr, NBPtr);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tRelease NB Pstate force\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sends an MRS command for Unb
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNSendMrsCmdUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 MrsBank;
+ UINT16 MrsBuffer;
+ UINT8 MrsChipSel;
+
+ MemNSetASRSRTNb (NBPtr);
+ MemNSwapBitsUnb (NBPtr);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tCS%d MR%d %05x\n",
+ (MemNGetBitFieldNb (NBPtr, BFMrsChipSel) & 0x7),
+ (MemNGetBitFieldNb (NBPtr, BFMrsBank) & 0x7),
+ (MemNGetBitFieldNb (NBPtr, BFMrsAddress) & 0x3FFFF));
+
+ // 1.Set SendMrsCmd=1
+ MemNSetBitFieldNb (NBPtr, BFSendMrsCmd, 1);
+
+ // 2.Wait for SendMrsCmd=0
+ MemNPollBitFieldNb (NBPtr, BFSendMrsCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
+
+ // Send MRS buffer if memory pstate is supported and enabled
+ if (NBPtr->MemPstateStage != 0) {
+ MrsChipSel = (UINT8) (MemNGetBitFieldNb (NBPtr, BFMrsChipSel) & 0x7);
+ // Only user even rank MRS to set MRS buffer
+ if ((MrsChipSel & 1) == 0) {
+ MrsBank = (UINT8) (MemNGetBitFieldNb (NBPtr, BFMrsBank) & 0x7);
+ MrsBuffer = (UINT16) (MemNGetBitFieldNb (NBPtr, BFMrsAddress) & 0xFFFF);
+ if (MrsBank == 0) {
+ MrsBuffer &= 0xFEFF;
+ MemNSetBitFieldNb (NBPtr, BFMxMr0, MrsBuffer);
+ } else if (MrsBank == 1) {
+ MemNSetBitFieldNb (NBPtr, BFMxMr1, MrsBuffer);
+ } else if (MrsBank == 2) {
+ MemNSetBitFieldNb (NBPtr, BFMxMr2, MrsBuffer);
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns MR0[CL] value with table driven support
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return MR0[CL] value
+ */
+UINT32
+MemNGetMR0CLTblDrvNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ return (UINT32) ((NBPtr->PsPtr->MR0CL31 << 4) | (NBPtr->PsPtr->MR0CL0 << 2));
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function performs MaxRdLat training for slot 1
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] TestAddrRJ16 - Test address
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNSlot1MaxRdLatTrainClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *TestAddrRJ16
+ )
+{
+ UINT8 DummyBuffer[8];
+ UINT16 MaxLatDly;
+ UINT8 i;
+
+ // Perform slot1 specific training:
+ // A.Program D18F2x[1,0]78[SlotSel]=1. Force read CAS to fifo slot1 for training.
+ // B.Program D18F2x[1,0]78[MaxRdLatency] = TrainedMaxRdLatency. Set to last slot0 value that passed.
+ // C.Read the DIMM test addresses.
+ // D.Compare the values read against the pattern written.
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tTrain Slot 1: \n");
+ MemNSetBitFieldNb (NBPtr, BFSlotSel, 1);
+
+ MaxLatDly = (UINT16) (MemNGetBitFieldNb (NBPtr, BFMaxLatency) + 1); // Add 1 to get back to the last passing value
+ MemNSetBitFieldNb (NBPtr, BFMaxLatency, MaxLatDly);
+
+ for (i = 0; i < 100; i++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tDly %3x", MaxLatDly);
+
+ NBPtr->ReadPattern (NBPtr, DummyBuffer, *(UINT32*)TestAddrRJ16, 6);
+
+ if (NBPtr->CompareTestPattern (NBPtr, DummyBuffer, DummyBuffer, 6 * 64) == 0xFFFF) {
+ IDS_HDT_CONSOLE (MEM_FLOW, " P");
+ break;
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n");
+ }
+
+ if (i < 100) {
+ MemNSetBitFieldNb (NBPtr, BFSlot1ExtraClkEn, 0);
+ } else {
+ MemNSetBitFieldNb (NBPtr, BFSlot1ExtraClkEn, 1);
+ }
+
+ MemNSetBitFieldNb (NBPtr, BFMaxSkipErrTrain, 0);
+
+ return TRUE;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function programs dram power management timing related registers
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return none
+ * ----------------------------------------------------------------------------
+ */
+VOID
+MemNDramPowerMngTimingNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ STATIC CONST UINT8 Tckesr[] = {4, 4, 4, 5, 5, 6, 7, 2, 2};
+ UINT8 Tck;
+
+ // These timings are based on DDR3 spec
+ // Tcksrx = max(5 nCK, 10 ns)
+ Tck = (UINT8) MAX (5, (MemUnsToMemClk (NBPtr->DCTPtr->Timings.Speed, 10)));
+ MemNSetBitFieldNb (NBPtr, BFTcksrx, MIN (0xE, MAX (Tck, 2)));
+
+ // Tcksre = max(5 nCK, 10 ns)
+ MemNSetBitFieldNb (NBPtr, BFTcksre, MIN (0x27, MAX (Tck, 5)));
+
+ // Tckesr = tCKE(min) + 1 nCK
+ // tCKE(min)
+ // DDR-667 7.5ns = 3nCk max(3nCK, 7.5ns) + 1 = 3nCK + 1nCK = 4nCK
+ // DDR-800 7.5ns = 3nCk max(3nCK, 7.5ns) + 1 = 3nCK + 1nCK = 4nCK
+ // DDR-1066 5.625ns = 3nCK max(3nCK, 5.625ns) + 1 = 3nCL + 1nCK = 4nCK
+ // DDR-1333 5.625ns = 4nCK max(3nCK, 4nCK) + 1 = 4nCK + 1nCK = 5nCK
+ // DDR-1600 5ns = 4nCK max(3nCK, 4nCK) + 1 = 4nCK + 1nCK = 5nCK
+ // DDR-1866 5ns = 5nCK max(3nCK, 5nCK) + 1 = 5nCK + 1nCK = 6nCK
+ // DDR-2133 5ns = 6nCK max(3nCK, 6nCK) + 1 = 6nCK + 1nCK = 7nCK
+ ASSERT (((NBPtr->DCTPtr->Timings.Speed / 133) >= 2) && ((NBPtr->DCTPtr->Timings.Speed / 133) <= 10));
+ MemNSetBitFieldNb (NBPtr, BFTckesr, Tckesr[(NBPtr->DCTPtr->Timings.Speed / 133) - 2]);
+
+ // Tpd = tCKE(min)
+ MemNSetBitFieldNb (NBPtr, BFTpd, Tckesr[(NBPtr->DCTPtr->Timings.Speed / 133) - 2] - 1);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * The function resets Rcv Fifo
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] Dummy - Dummy parameter
+ *
+ */
+
+VOID
+MemTResetRcvFifoUnb (
+ IN OUT struct _MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 Dummy
+ )
+{
+ // Program D18F2x9C_x0000_0050_dct[1:0]=00000000h
+ MemNSetBitFieldNb (TechPtr->NBPtr, BFRstRcvFifo, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the memory width
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return Memory width
+ */
+
+UINT32
+MemNGetMemoryWidthUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ DIE_STRUCT *MCTPtr;
+ MEM_SHARED_DATA *SharedPtr;
+
+ MCTPtr = NBPtr->MCTPtr;
+ SharedPtr = NBPtr->SharedPtr;
+
+ return 64 + ((SharedPtr->AllECC && MCTPtr->Status[SbEccDimms]) ? 8 : 0);
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnfeat.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnfeat.c
new file mode 100644
index 0000000000..2d9d23fac8
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnfeat.c
@@ -0,0 +1,1418 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnfeat.c
+ *
+ * Common Northbridge features
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "mu.h"
+#include "PlatformMemoryConfiguration.h"
+#include "merrhdl.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_MEM_NB_MNFEAT_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_CL_CONT_READ 32
+#define MAX_CL_CONT_WRITE 32
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemNContWritePatternNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address,
+ IN UINT8 Pattern[],
+ IN UINT16 ClCount
+ );
+
+VOID
+STATIC
+MemNContReadPatternNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ );
+
+VOID
+STATIC
+MemNGenHwRcvEnReadsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address
+ );
+
+UINT16
+STATIC
+MemNCompareTestPatternClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN UINT16 ByteCount
+ );
+
+UINT16
+STATIC
+MemNInsDlyCompareTestPatternClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN UINT16 ByteCount
+ );
+
+VOID
+STATIC
+MemNContWritePatternClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address,
+ IN UINT8 Pattern[],
+ IN UINT16 ClCount
+ );
+
+VOID
+STATIC
+MemNContReadPatternClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ );
+
+VOID
+STATIC
+MemNGenHwRcvEnReadsClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address
+ );
+
+BOOLEAN
+STATIC
+MemNBeforeMemClrClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN VOID *UnUsed
+ );
+
+VOID
+STATIC
+MemNGenHwRcvEnReadsUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address
+ );
+
+VOID
+STATIC
+MemNEnableInfiniteWritePatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+STATIC
+MemNDisableInfiniteWritePatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNInitCPGNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNInitDqsTrainRcvrEnHwNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNDisableDqsTrainRcvrEnHwNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNInitCPGClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemNInitCPGUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function assigns read/write function pointers to CPG read/write modules.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNInitCPGNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ NBPtr->WritePattern = MemNContWritePatternNb;
+ NBPtr->ReadPattern = MemNContReadPatternNb;
+ NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsNb;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes member functions of HW Rx En Training.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNInitDqsTrainRcvrEnHwNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ NBPtr->MemNPrepareRcvrEnDlySeed = MemNPrepareRcvrEnDlySeedNb;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function disables member functions of Hw Rx En Training.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNDisableDqsTrainRcvrEnHwNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ NBPtr->MemNPrepareRcvrEnDlySeed = (VOID (*) (MEM_NB_BLOCK *)) memDefRet;
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function writes 9 or 18 cache lines continuously using GH CPG engine
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Pattern - Array of bytes that will be written to DRAM
+ * @param[in] Address - System Address [47:16]
+ * @param[in] ClCount - Number of cache lines
+ *
+ */
+VOID
+STATIC
+MemNContWritePatternNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address,
+ IN UINT8 Pattern[],
+ IN UINT16 ClCount
+ )
+{
+ UINT16 ClDiff;
+ if (ClCount > MAX_CL_CONT_WRITE) {
+ ClDiff = ClCount - MAX_CL_CONT_WRITE;
+ ClCount = MAX_CL_CONT_WRITE;
+ } else {
+ ClDiff = 0;
+ }
+
+ // Set F2x11C[MctWrLimit] to desired number of cachelines in the burst.
+ MemNSetBitFieldNb (NBPtr, BFMctWrLimit, MAX_CL_CONT_WRITE - ClCount);
+
+ // Issue the stream of writes. When F2x11C[MctWrLimit] is reached (or when F2x11C[FlushWr] is set
+ // again), all the writes are written to DRAM.
+ Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
+ MemUWriteCachelines (Address, Pattern, ClCount);
+
+ // Flush out prior writes by setting F2x11C[FlushWr].
+ MemNSetBitFieldNb (NBPtr, BFFlushWr, 1);
+ // Wait for F2x11C[FlushWr] to clear, indicating prior writes have been flushed.
+ while (MemNGetBitFieldNb (NBPtr, BFFlushWr) != 0) {}
+
+ // Set F2x11C[MctWrLimit] to 1Fh to disable write bursting.
+ MemNSetBitFieldNb (NBPtr, BFMctWrLimit, 0x1F);
+
+ if (ClDiff > 0) {
+ MemNContWritePatternNb (NBPtr, Address + (MAX_CL_CONT_WRITE * 64), Pattern + (MAX_CL_CONT_WRITE * 64), ClDiff);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function reads 9 or 18 cache lines continuously using GH CPG engine
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] Buffer - Array of bytes to be filled with data read from DRAM
+ * @param[in] Address - System Address [47:16]
+ * @param[in] ClCount - Number of cache lines
+ *
+ */
+
+VOID
+STATIC
+MemNContReadPatternNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ )
+{
+ BOOLEAN DisAutoRefresh;
+ UINT16 ClDiff;
+ if (ClCount > MAX_CL_CONT_READ) {
+ ClDiff = ClCount - MAX_CL_CONT_READ;
+ ClCount = MAX_CL_CONT_READ;
+ } else {
+ ClDiff = 0;
+ }
+
+ Address = MemUSetUpperFSbase (Address, NBPtr->MemPtr);
+
+ // 1. BIOS ensures that the only accesses outstanding to the MCT are training reads.
+ // 2. If F2x[1, 0]90[BurstLength32]=1, then BIOS ensures that the DCTs and DRAMs are configured for 64
+ // byte bursts (8-beat burst length). This requires that BIOS issue MRS commands to the devices
+ // to change to an 8-beat burst length and then to restore the desired burst length after training
+ // is complete.
+
+ if (MemNGetBitFieldNb (NBPtr, BFDisAutoRefresh) == 0) {
+ DisAutoRefresh = FALSE;
+ // 3. BIOS programs F2x[1, 0]90[ForceAutoPchg] = 0 and F2x[1, 0]8C[DisAutoRefresh] = 1.
+ // 4. If necessary, BIOS programs F2x[1, 0]78[EarlyArbEn] = 1 at this time. See register description.
+ MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
+ // MemNSetBitFieldNb (NBPtr, BFForceAutoPchg, 0); // ForceAutoPchg is 0 by default.
+ MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
+ } else {
+ DisAutoRefresh = TRUE;
+ }
+
+ MemNSetBitFieldNb (NBPtr, BFPrefCpuDis, 0);
+
+ // 5. BIOS sets F2x11C[MctPrefReqLimit] to the number of training reads (Ntrain) it wishes to generate in the
+ // training sequence.
+ MemNSetBitFieldNb (NBPtr, BFMctPrefReqLimit, ClCount - 1);
+
+ // 6. BIOS sets F2x11C[PrefDramTrainMode] bit.
+ // 7. The act of setting F2x11C[PrefDramTrainMode] causes the MCT to flush out the prefetch stride predictor
+ // table (removing any existing prefetch stride patterns).
+ MemNSetBitFieldNb (NBPtr, BFPrefDramTrainMode, 1);
+
+ // 8. BIOS issues an SFENCE (or other serializing instruction) to ensure that the prior write completes.
+ // 9. For revision C and earlier processors, BIOS generates two training reads. For revision D processors BIOS
+ // generates three training reads. Three are required to detect the stride with DCQ buddy enabled. These must
+ // be to consecutive cache lines (i.e. 64 bytes apart) and must not cross a naturally aligned 4 Kbyte boundary.
+ // 10. These reads set up a stride pattern which is detected by the prefetcher. The prefetcher then continues to
+ // issue prefetches until F2x11C[MctPrefReqLimit] is reached, at which point the MCT clears
+ // F2x11C[PrefDramTrainMode].
+ MemUDummyCLRead (Address);
+ MemUDummyCLRead (Address + 0x40);
+ if (NBPtr->IsSupported[CheckDummyCLRead]) {
+ MemUDummyCLRead (Address + 0x80);
+ }
+ // 11. BIOS issues the remaining (Ntrain - 2 for revisions C and earlier or Ntrain - 3 for revision D) reads after
+ // checking that F2x11C[PrefDramTrainMode] is cleared. These reads must be to consecutive cache lines
+ // (i.e., 64 bytes apart) and must not cross a naturally aligned 4KB boundary. These reads hit the prefetches
+ // and read the data from the prefetch buffer.
+ while (MemNGetBitFieldNb (NBPtr, BFPrefDramTrainMode) != 0) {}
+ MemUReadCachelines (Buffer, Address, ClCount);
+
+ // 14. BIOS restores the target values for F2x[1, 0]90[ForceAutoPchg], F2x[1, 0]8C[DisAutoRefresh] and
+ // F2x[1, 0]90[BurstLength32].
+ if (!DisAutoRefresh) {
+ MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 0);
+ MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 2);
+ }
+
+ if (ClDiff > 0) {
+ MemNContReadPatternNb (NBPtr, Buffer + (MAX_CL_CONT_READ * 64), Address + (MAX_CL_CONT_READ * 64), ClDiff);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function generates a continuous burst of reads during HW RcvEn training.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Address - System Address [47:16]
+ *
+ */
+VOID
+STATIC
+MemNGenHwRcvEnReadsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address
+ )
+{
+ UINT8 TempBuffer[12 * 64];
+ UINT8 BurstCount;
+
+ for (BurstCount = 0; BurstCount < 10; BurstCount++) {
+ NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 12);
+ NBPtr->FlushPattern (NBPtr, Address, 12);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function writes cache lines continuously using TCB CPG engine
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Pattern - Array of bytes that will be written to DRAM
+ * @param[in] Address - System Address [47:16]
+ * @param[in] ClCount - Number of cache lines
+ *
+ */
+VOID
+STATIC
+MemNContWritePatternClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address,
+ IN UINT8 Pattern[],
+ IN UINT16 ClCount
+ )
+{
+ UINT32 PatternHash;
+ UINT32 *DwordPtr;
+ UINT16 i;
+ UINT16 j;
+ UINT16 Multiplier;
+
+ Multiplier = 1;
+
+ // 1. Program D18F2x1C0[WrDramTrainMode]=1.
+ MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 1);
+
+ PatternHash = ClCount << 24;
+ for (i = 0; i < 3; i ++) {
+ PatternHash |= (Pattern[i * ClCount * 24 + 9] << (8 * i));
+ }
+ if (NBPtr->CPGInit != PatternHash) {
+
+ if (ClCount == 3) {
+ // Double pattern length for MaxRdLat training
+ Multiplier = 2;
+ }
+
+ // If write training buffer has not been initialized, initialize it
+ // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
+ MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
+
+ // 3. Program D18F2x1D0[WrTrainBufAddr]=000h.
+ MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
+
+ // 4. Successively write each dword of the training pattern to D18F2x1D4.
+ DwordPtr = (UINT32 *) Pattern;
+ for (j = 0; j < Multiplier; j++) {
+ for (i = 0; i < (ClCount * 16); i++) {
+ MemNSetBitFieldNb (NBPtr, BFWrTrainBufDat, DwordPtr[i]);
+ }
+ }
+
+ NBPtr->CPGInit = PatternHash;
+ }
+
+ // 5. Program D18F2x1D0[WrTrainBufAddr]=000h
+ MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
+
+ // 6. Program the DRAM training address
+ MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
+ MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
+
+ // 7. Program D18F2x1C0[WrTrainGo]=1.
+ MemNSetBitFieldNb (NBPtr, BFWrTrainGo, 1);
+
+ // 8. Wait for D18F2x1C0[WrTrainGo]=0.
+ while (MemNGetBitFieldNb (NBPtr, BFWrTrainGo) != 0) {}
+
+ // 9. Program D18F2x1C0[WrDramTrainMode]=0.
+ MemNSetBitFieldNb (NBPtr, BFWrDramTrainMode, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function reads cache lines continuously using TCB CPG engine
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] Buffer - Array of bytes to be filled with data read from DRAM
+ * @param[in] Address - System Address [47:16]
+ * @param[in] ClCount - Number of cache lines
+ *
+ */
+
+VOID
+STATIC
+MemNContReadPatternClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ )
+{
+ UINT16 Multiplier;
+
+ Multiplier = 1;
+ if (ClCount == 3) {
+ // Double pattern length for MaxRdLat training
+ Multiplier = 2;
+ }
+
+ // 1. Program D18F2x1C0[RdDramTrainMode]=1.
+ MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 1);
+
+ // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
+ MemNSetBitFieldNb (NBPtr, BFTrainLength, ClCount * Multiplier);
+
+ // 3. Program the DRAM training address as follows:
+ MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, Address << (16 - 6));
+ MemNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrHi, (Address >> (38 - 16)) & 3);
+
+ // 4. Program D18F2x1D0[WrTrainBufAddr]=000h
+ MemNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
+
+ // 5. Program D18F2x1C0[RdTrainGo]=1.
+ MemNSetBitFieldNb (NBPtr, BFRdTrainGo, 1);
+
+ // 6. Wait for D18F2x1C0[RdTrainGo]=0.
+ while (MemNGetBitFieldNb (NBPtr, BFRdTrainGo) != 0) {}
+
+ // 7. Read D18F2x1E8[TrainCmpSts] and D18F2x1E8[TrainCmpSts2].
+ // This step will be accomplished in Compare routine.
+
+ // 8. Program D18F2x1C0[RdDramTrainMode]=0.
+ MemNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function generates a continuous burst of reads during HW RcvEn training.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Address - System Address [47:16]
+ *
+ */
+VOID
+STATIC
+MemNGenHwRcvEnReadsClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address
+ )
+{
+ UINT8 TempBuffer[64];
+ UINT8 Count;
+
+ for (Count = 0; Count < 3; Count++) {
+ NBPtr->ReadPattern (NBPtr, TempBuffer, Address, 64);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function assigns read/write function pointers to CPG read/write modules.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNInitCPGClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ NBPtr->WritePattern = MemNContWritePatternClientNb;
+ NBPtr->ReadPattern = MemNContReadPatternClientNb;
+ NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsClientNb;
+ NBPtr->FlushPattern = (VOID (*) (MEM_NB_BLOCK *, UINT32, UINT16)) memDefRet;
+ NBPtr->CompareTestPattern = MemNCompareTestPatternClientNb;
+ NBPtr->InsDlyCompareTestPattern = MemNInsDlyCompareTestPatternClientNb;
+ NBPtr->FamilySpecificHook[BeforeMemClr] = MemNBeforeMemClrClientNb;
+ NBPtr->CPGInit = 0;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function compares test pattern with data in buffer and
+ * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
+ * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
+ * @param[in] ByteCount - Byte count
+ *
+ * @return PASS - Bitmap of results of comparison
+ */
+
+UINT16
+STATIC
+MemNCompareTestPatternClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN UINT16 ByteCount
+ )
+{
+ return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts));
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * This function compares test pattern with data in buffer and
+ * return a pass/fail bitmap for 8 bytelanes (upper 8 bits are reserved)
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
+ * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
+ * @param[in] ByteCount - Byte count
+ *
+ * @retval Bitmap of results of comparison
+ */
+UINT16
+STATIC
+MemNInsDlyCompareTestPatternClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN UINT16 ByteCount
+ )
+{
+ return ~((UINT16) MemNGetBitFieldNb (NBPtr, BFTrainCmpSts2));
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates RcvEn seed value for each rank
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNPrepareRcvrEnDlySeedNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ CH_DEF_STRUCT *ChannelPtr;
+ DIE_STRUCT *MCTPtr;
+ UINT16 SeedTotal;
+ UINT16 SeedFine;
+ UINT16 SeedGross;
+ UINT16 SeedPreGross;
+ UINT16 SeedTotalPreScaling;
+ UINT8 ByteLane;
+ UINT16 Speed;
+ UINT16 PlatEst;
+ UINT8 ChipSel;
+ UINT8 Pass;
+ UINT16 *PlatEstSeed;
+ UINT16 SeedValue[9];
+ UINT16 SeedTtl[9];
+ UINT16 SeedPre[9];
+
+ TechPtr = NBPtr->TechPtr;
+ MCTPtr = NBPtr->MCTPtr;
+ ChannelPtr = TechPtr->NBPtr->ChannelPtr;
+ Speed = NBPtr->DCTPtr->Timings.Speed;
+ SeedTotalPreScaling = 0;
+ ChipSel = TechPtr->ChipSel;
+ Pass = TechPtr->Pass;
+
+ for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
+ TechPtr->Bytelane = ByteLane;
+ if (Pass == 1) {
+ // Get platform override seed
+ PlatEstSeed = (UINT16 *) FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_RXEN_SEED, MCTPtr->SocketId, ChannelPtr->ChannelID, ChipSel >> 1,
+ &(NBPtr->MCTPtr->LogicalCpuid), &(NBPtr->MemPtr->StdHeader));
+ // For Pass1, BIOS starts with the delay value obtained from the first pass of write
+ // levelization training that was done in DDR3 Training and add a delay value of 3Bh.
+ PlatEst = 0x3B;
+ NBPtr->FamilySpecificHook[OverrideRcvEnSeed] (NBPtr, &PlatEst);
+ PlatEst = ((PlatEstSeed != NULL) ? PlatEstSeed[ByteLane] : PlatEst);
+ SeedTotal = ChannelPtr->WrDqsDlys[(ChipSel / NBPtr->CsPerDelay) * TechPtr->DlyTableWidth () + ByteLane] + PlatEst;
+ SeedValue[ByteLane] = PlatEst;
+ } else {
+ // For Pass2
+ // SeedTotalPreScaling = (the total delay values in D18F2x[1,0]9C_x0000_00[24:10] from pass 1 of
+ // DQS receiver enable training) - 20h. Subtract 1UI to get back to preamble left edge.
+ if ((((ChipSel & 1) == 0) || (NBPtr->CsPerDelay == 1)) && NBPtr->FamilySpecificHook[TrainingNibbleZero] (NBPtr, &ChipSel)) {
+ // Save Seed for odd CS SeedTotalPreScaling RxEn Value
+ TechPtr->PrevPassRcvEnDly[ByteLane] = ChannelPtr->RcvEnDlys[(ChipSel / NBPtr->CsPerDelay) * TechPtr->DlyTableWidth () + ByteLane];
+ }
+ NBPtr->FamilySpecificHook[OverridePrevPassRcvEnDly] (NBPtr, &TechPtr->PrevPassRcvEnDly[ByteLane]);
+ SeedTotalPreScaling = TechPtr->PrevPassRcvEnDly[ByteLane] - 0x20;
+ // SeedTotal = SeedTotalPreScaling*target frequency/lowest supported frequency.
+ SeedTotal = (UINT16) (((UINT32) SeedTotalPreScaling * Speed) / TechPtr->PrevSpeed);
+ NBPtr->FamilySpecificHook[OverrideRcvEnSeedPassN] (NBPtr, &SeedTotal);
+ }
+ SeedTtl[ByteLane] = SeedTotal;
+
+ // SeedGross = SeedTotal DIV 32.
+ SeedGross = SeedTotal >> 5;
+ // SeedFine = SeedTotal MOD 32.
+ SeedFine = SeedTotal & 0x1F;
+ // Next, determine the gross component of SeedTotal. SeedGrossPass1=SeedTotal DIV 32.
+ // Then, determine the fine delay component of SeedTotal. SeedFinePass1=SeedTotal MOD 32.
+ // Use SeedGrossPass1 to determine SeedPreGrossPass1:
+
+ if ((SeedGross & 0x1) != 0) {
+ //if SeedGross is odd
+ SeedPreGross = 1;
+ } else {
+ //if SeedGross is even
+ SeedPreGross = 2;
+ }
+ // (SeedGross - SeedPreGross)
+ TechPtr->DiffSeedGrossSeedPreGross[ByteLane] = (SeedGross - SeedPreGross) << 5;
+
+ //BIOS programs registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 with SeedPreGrossPass1
+ //and SeedFinePass1 from the preceding steps.
+
+ NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel / NBPtr->CsPerDelay, ByteLane), (SeedPreGross << 5) | SeedFine);
+ SeedPre[ByteLane] = (SeedPreGross << 5) | SeedFine;
+
+ NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (ChipSel / NBPtr->CsPerDelay, ByteLane), SeedGross << 5);
+ }
+
+ IDS_HDT_CONSOLE_DEBUG_CODE (
+ if (Pass == 1) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedValue: ");
+ for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedValue[ByteLane]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n");
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedTotal: ");
+ for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedTtl[ByteLane]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t SeedPRE: ");
+ for (ByteLane = 0; ByteLane < (MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedPre[ByteLane]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n");
+ );
+
+ NBPtr->FamilySpecificHook[RegAccessFence] (NBPtr, NULL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Waits specified number of MEMCLKs
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] MemClkCount - Number of MEMCLKs
+ *
+ * ----------------------------------------------------------------------------
+ */
+VOID
+MemNWaitXMemClksNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 MemClkCount
+ )
+{
+ MemUWait10ns ((MemClkCount * 100 + NBPtr->DCTPtr->Timings.Speed - 1) / NBPtr->DCTPtr->Timings.Speed, NBPtr->MemPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Issues dummy TCB write read to zero out CL that is used for MemClr
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *UnUsed - unused
+ *
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+STATIC
+MemNBeforeMemClrClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN VOID *UnUsed
+ )
+{
+ UINT8 Pattern[64];
+ UINT8 i;
+
+ for (i = 0; i < 64; i++) {
+ Pattern[i] = 0;
+ }
+
+ MemNContWritePatternClientNb (NBPtr, 0x20, Pattern, 1);
+ MemNContReadPatternClientNb (NBPtr, Pattern, 0x20, 1);
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function uses the PRBS generator in the DCT to send a DDR Activate command
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] ChipSelect - Chip select 0-7
+ * @param[in] Bank - Bank Address 0-7
+ * @param[in] RowAddress - Row Address [17:0]
+ *
+ */
+
+VOID
+MemNRrwActivateCmd (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 ChipSelect,
+ IN UINT8 Bank,
+ IN UINT32 RowAddress
+ )
+{
+ // Set Chip select
+ MemNSetBitFieldNb (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
+ // Set Bank Address
+ MemNSetBitFieldNb (NBPtr, BFCmdBank, Bank);
+ // Set Row Address
+ MemNSetBitFieldNb (NBPtr, BFCmdAddress, RowAddress);
+ // Send the command
+ MemNSetBitFieldNb (NBPtr, BFSendActCmd, 1);
+ // Wait for command complete
+ MemNPollBitFieldNb (NBPtr, BFSendActCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ // Wait 75 MEMCLKs
+ NBPtr->WaitXMemClks (NBPtr, 75);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function uses the PRBS generator in the DCT to send a DDR Precharge
+ * or Precharge All command
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] ChipSelect - Chip select 0-7
+ * @param[in] Bank - Bank Address 0-7, PRECHARGE_ALL_BANKS = Precharge All
+ *
+ *
+ */
+
+VOID
+MemNRrwPrechargeCmd (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 ChipSelect,
+ IN UINT8 Bank
+ )
+{
+ // Wait 25 MEMCLKs
+ NBPtr->WaitXMemClks (NBPtr, 25);
+ // Set Chip select
+ NBPtr->SetBitField (NBPtr, BFCmdChipSelect, (1 << ChipSelect));
+ if (Bank == PRECHARGE_ALL_BANKS) {
+ // Set Row Address, bit 10
+ NBPtr->SetBitField (NBPtr, BFCmdAddress, NBPtr->GetBitField (NBPtr, BFCmdAddress) | (1 << 10) );
+ } else {
+ // Clear Row Address, bit 10
+ NBPtr->SetBitField (NBPtr, BFCmdAddress, NBPtr->GetBitField (NBPtr, BFCmdAddress) & (~(1 << 10)) );
+ // Set Bank Address
+ NBPtr->SetBitField (NBPtr, BFCmdBank, Bank);
+ }
+ // Send the command
+ NBPtr->SetBitField (NBPtr, BFSendPchgCmd, 1);
+ // Wait for command complete
+ NBPtr->PollBitField (NBPtr, BFSendPchgCmd, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ // Wait 25 MEMCLKs
+ NBPtr->WaitXMemClks (NBPtr, 25);
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function generates a continuous burst of reads for HW RcvEn
+ * training using the Unified Northbridge Reliable Read/Write Engine.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Address - Unused by this function
+ *
+ */
+VOID
+STATIC
+MemNGenHwRcvEnReadsUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address
+ )
+{
+ VOID *DummyPtr;
+ DummyPtr = NULL;
+ //
+ // Issue Stream of Reads from the Target Rank
+ //
+ NBPtr->ReadPattern (NBPtr, DummyPtr, 0, NBPtr->TechPtr->PatternLength);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function generates a continuous stream of reads from DRAM using the
+ * Unified Northbridge Reliable Read/Write Engine.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] Buffer - Unused by this function
+ * @param[in] Address - Unused by this function
+ * @param[in] ClCount - Number of cache lines to read
+ *
+ * Assumptions:
+ *
+ *
+ *
+ */
+
+VOID
+MemNContReadPatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ RRW_SETTINGS *Rrw;
+ UINT8 CmdTgt;
+ UINT8 ChipSel;
+
+ TechPtr = NBPtr->TechPtr;
+ Rrw = &NBPtr->RrwSettings;
+
+ ChipSel = TechPtr->ChipSel;
+ CmdTgt = Rrw->CmdTgt;
+ //
+ // Wait for RRW Engine to be ready and turn it on
+ //
+ NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
+ //
+ // Depending upon the Cmd Target, send Row Activate and set Chipselect
+ // for the Row or Rows that will be used
+ //
+ MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
+ NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
+ if (CmdTgt == CMD_TGT_AB) {
+ MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressB, Rrw->TgtRowAddressB);
+ NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, ChipSel);
+ }
+ // Set Comparison Masks
+ NBPtr->SetBitField (NBPtr, BFDramDqMaskLow, Rrw->CompareMaskLow);
+ NBPtr->SetBitField (NBPtr, BFDramDqMaskHigh, Rrw->CompareMaskHigh);
+ //
+ // If All Dimms are ECC Capable Test ECC. Otherwise, mask it off
+ //
+ NBPtr->SetBitField (NBPtr, BFDramEccMask, (NBPtr->MCTPtr->Status[SbEccDimms] == TRUE) ? Rrw->CompareMaskEcc : 0xFF);
+ //
+ // Program the PRBS Seed
+ //
+ NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
+ //
+ // Set the Command Count
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
+ //
+ // Program the Starting Address
+ //
+ NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
+ NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
+ if (CmdTgt == CMD_TGT_AB) {
+ NBPtr->SetBitField (NBPtr, BFTgtBankB, Rrw->TgtBankAddressB);
+ NBPtr->SetBitField (NBPtr, BFTgtAddressB, Rrw->TgtColAddressB);
+ }
+ //
+ // Reset All Errors and Disable StopOnErr
+ //
+ NBPtr->SetBitField (NBPtr, BFResetAllErr, 1);
+ NBPtr->SetBitField (NBPtr, BFStopOnErr, 0);
+ //
+ // Program the CmdTarget
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
+ //
+ // Set CmdType to read
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_READ);
+ //
+ // Start the Commands
+ //
+ AGESA_TESTPOINT (TpProcMemContinPatternGenRead, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
+ //
+ // Commands have started, wait for the reads to complete then clear the command
+ //
+ NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
+ NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
+ //
+ // Send the Precharge All Command
+ //
+ MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
+ //
+ // Turn Off the RRW Engine
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function generates a continuous stream of writes to DRAM using the
+ * Unified Northbridge Reliable Read/Write Engine.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] Address - Unused by this function
+ * @param[in] Pattern - Unused by this function
+ * @param[in] ClCount - Number of cache lines to write
+ *
+ */
+
+VOID
+MemNContWritePatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address,
+ IN UINT8 Pattern[],
+ IN UINT16 ClCount
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ RRW_SETTINGS *Rrw;
+ UINT8 CmdTgt;
+ UINT8 ChipSel;
+
+ TechPtr = NBPtr->TechPtr;
+ Rrw = &NBPtr->RrwSettings;
+
+ ChipSel = TechPtr->ChipSel;
+ CmdTgt = Rrw->CmdTgt;
+ //
+ // Wait for RRW Engine to be ready and turn it on
+ //
+ NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
+ //
+ // Depending upon the Cmd Target, send Row Activate and set Chipselect
+ // for the Row or Rows that will be used
+ //
+ MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
+ NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
+ if (CmdTgt == CMD_TGT_AB) {
+ MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressB, Rrw->TgtRowAddressB);
+ NBPtr->SetBitField (NBPtr, BFTgtChipSelectB, ChipSel);
+ }
+ //
+ // Program the PRBS Seed
+ //
+ NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
+ //
+ // Set the Command Count
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdCount, ClCount);
+ //
+ // Program the Starting Address
+ //
+ NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
+ NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
+ if (CmdTgt == CMD_TGT_AB) {
+ NBPtr->SetBitField (NBPtr, BFTgtBankB, Rrw->TgtBankAddressB);
+ NBPtr->SetBitField (NBPtr, BFTgtAddressB, Rrw->TgtColAddressB);
+ }
+ //
+ // Program the CmdTarget
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdTgt, CmdTgt);
+ //
+ // Set CmdType to Write
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
+ //
+ // Start the Commands
+ //
+ AGESA_TESTPOINT (TpProcMemContinPatternGenWrite, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
+ //
+ // Commands have started, wait for the writes to complete then clear the command
+ //
+ // Wait for TestStatus = 1 and CmdSendInProg = 0.
+ NBPtr->PollBitField (NBPtr, BFTestStatus, 1, PCI_ACCESS_TIMEOUT, FALSE);
+ NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
+ //
+ // Send the Precharge All Command
+ //
+ MemNRrwPrechargeCmd (NBPtr, ChipSel, PRECHARGE_ALL_BANKS);
+ //
+ // Turn Off the RRW Engine
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function checks the Error status bits for comparison results
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Buffer[] - Not used in this implementation
+ * @param[in] Pattern[] - Not used in this implementation
+ * @param[in] ByteCount - Not used in this implementation
+ *
+ * @return PASS - Bitmap of results of comparison
+ */
+
+UINT16
+MemNCompareTestPatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN UINT16 ByteCount
+ )
+{
+
+
+ UINT16 i;
+ UINT16 Pass;
+ UINT8 ChipSel;
+ UINT8 ColumnCount;
+ UINT8* FailingBitMaskPtr;
+ UINT8 FailingBitMask[9];
+ UINT32 NibbleErrSts;
+
+ ChipSel = NBPtr->TechPtr->ChipSel;
+ ColumnCount = NBPtr->ChannelPtr->ColumnCount;
+ // Calculate Failing Bitmask pointer
+ FailingBitMaskPtr = &(NBPtr->ChannelPtr->FailingBitMask[(ColumnCount * NBPtr->TechPtr->ChipSel)]);
+
+ //
+ // Get Failing bit data
+ //
+ *((UINT32*)FailingBitMask) = NBPtr->GetBitField (NBPtr, BFDQErrLow);
+ *((UINT32*)&FailingBitMask[4]) = NBPtr->GetBitField (NBPtr, BFDQErrHigh);
+ FailingBitMask[8] = (UINT8)NBPtr->GetBitField (NBPtr, BFEccErr);
+
+ Pass = 0x0000;
+ //
+ // Get Comparison Results - Convert Nibble Masks to Byte Masks
+ //
+ NibbleErrSts = NBPtr->GetBitField (NBPtr, BFNibbleErrSts);
+
+ for (i = 0; i < ColumnCount ; i++) {
+ Pass |= ((NibbleErrSts & 0x03) > 0 ) ? (1 << i) : 0;
+ NibbleErrSts >>= 2;
+ FailingBitMaskPtr[i] = FailingBitMask[i];
+ }
+ Pass = ~Pass;
+ return Pass;
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * This function checks the Error status bits for offset comparison results
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Buffer[] - Buffer data from DRAM (Measured data from DRAM) to compare
+ * @param[in] Pattern[] - Pattern (Expected data in ROM/CACHE) to compare against
+ * @param[in] ByteCount - Byte count
+ *
+ * @retval Bitmap of results of comparison
+ */
+UINT16
+STATIC
+MemNInsDlyCompareTestPatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN UINT16 ByteCount
+ )
+{
+ UINT16 i;
+ UINT16 Pass;
+ UINT8 ColumnCount;
+ UINT32 NibbleErr180Sts;
+
+ ColumnCount = NBPtr->ChannelPtr->ColumnCount;
+ Pass = 0x0000;
+ //
+ // Get Comparison Results - Convert Nibble Masks to Byte Masks
+ //
+ NibbleErr180Sts = NBPtr->GetBitField (NBPtr, BFNibbleErr180Sts);
+
+ for (i = 0; i < ColumnCount ; i++) {
+ Pass |= ((NibbleErr180Sts & 0x03) > 0 ) ? (1 << i) : 0;
+ NibbleErr180Sts >>= 2;
+ }
+ Pass = ~Pass;
+
+ return Pass;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function assigns read/write function pointers to CPG read/write modules.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNInitCPGUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ NBPtr->WritePattern = MemNContWritePatternUnb;
+ NBPtr->ReadPattern = MemNContReadPatternUnb;
+ NBPtr->GenHwRcvEnReads = MemNGenHwRcvEnReadsUnb;
+ NBPtr->FlushPattern = (VOID (*) (MEM_NB_BLOCK *, UINT32, UINT16)) memDefRet;
+ NBPtr->TrainingPatternInit = (AGESA_STATUS (*) (MEM_NB_BLOCK *)) memDefRetSuccess;
+ NBPtr->TrainingPatternFinalize = (AGESA_STATUS (*) (MEM_NB_BLOCK *)) memDefRetSuccess;
+ NBPtr->CompareTestPattern = MemNCompareTestPatternUnb;
+ NBPtr->InsDlyCompareTestPattern = MemNInsDlyCompareTestPatternUnb;
+ NBPtr->FamilySpecificHook[SetupHwTrainingEngine] = MemNSetupHwTrainingEngineUnb;
+ NBPtr->EnableInfiniteWritePattern = MemNEnableInfiniteWritePatternUnb;
+ NBPtr->DisableInfiniteWritePattern = MemNDisableInfiniteWritePatternUnb;
+ NBPtr->CPGInit = 0;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function generates a continuous stream of writes infinite writes to DRAM using the
+ * Unified Northbridge Reliable Read/Write Engine.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+STATIC
+MemNEnableInfiniteWritePatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ RRW_SETTINGS *Rrw;
+ UINT8 CmdTgt;
+ UINT8 ChipSel;
+ TechPtr = NBPtr->TechPtr;
+ Rrw = &NBPtr->RrwSettings;
+ ChipSel = TechPtr->ChipSel;
+ CmdTgt = Rrw->CmdTgt;
+
+ // Ensure that DisAutoRefresh and ZqCals are disabled during the use of RRWM
+ if (MemNGetBitFieldNb (NBPtr, BFDisAutoRefresh) == 0) {
+ NBPtr->OrigDisAutoRefreshState = FALSE;
+ MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 1);
+ MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 0);
+ } else {
+ NBPtr->OrigDisAutoRefreshState = TRUE;
+ }
+
+
+
+ //
+ // Enable PRBS
+ //
+
+ //
+ // Wait for RRW Engine to be ready and turn it on
+ //
+ NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 1);
+ //
+ // Depending upon the Cmd Target, send Row Activate and set Chipselect
+ // for the Row or Rows that will be used
+ //
+ MemNRrwActivateCmd (NBPtr, ChipSel, Rrw->TgtBankAddressA, Rrw->TgtRowAddressA);
+ NBPtr->SetBitField (NBPtr, BFTgtChipSelectA, ChipSel);
+ //
+ // Program the PRBS Seed
+ //
+ NBPtr->SetBitField (NBPtr, BFDataPrbsSeed, Rrw->DataPrbsSeed);
+ //
+ // Set the Command Count
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdCount, 0);
+ //
+ // Program the Starting Address
+ //
+ NBPtr->SetBitField (NBPtr, BFTgtBankA, Rrw->TgtBankAddressA);
+ NBPtr->SetBitField (NBPtr, BFTgtAddressA, Rrw->TgtColAddressA);
+ //
+ // Program the CmdTarget
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdTgt, CMD_TGT_A);
+ //
+ // Set CmdType to write
+ //
+ NBPtr->SetBitField (NBPtr, BFCmdType, CMD_TYPE_WRITE);
+ //
+ // Start the Commands
+ //
+ NBPtr->SetBitField (NBPtr, BFSendCmd, 1);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function disables the infinite stream of writes to DRAM using the
+ * Unified Northbridge Reliable Read/Write Engine.
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+STATIC
+MemNDisableInfiniteWritePatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ //
+ // Disable PRBS
+ NBPtr->SetBitField (NBPtr, BFCmdCount, 1);
+ //Wait for TestStatus = 1 and CmdSendInProg = 0
+ NBPtr->PollBitField (NBPtr, BFCmdSendInProg, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ NBPtr->SetBitField (NBPtr, BFSendCmd, 0);
+ //
+ //
+ // Turn Off the RRW Engine
+ //
+ MemNRrwPrechargeCmd (NBPtr, NBPtr->TechPtr->ChipSel, PRECHARGE_ALL_BANKS);
+ NBPtr->SetBitField (NBPtr, BFCmdTestEnable, 0);
+ //
+ // Restore DisAutoRefresh and ZQCals to original state
+ //
+ if (!NBPtr->OrigDisAutoRefreshState) {
+ MemNSetBitFieldNb (NBPtr, BFDisAutoRefresh, 0);
+ MemNSetBitFieldNb (NBPtr, BFZqcsInterval, 2);
+ }
+
+}
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function is an empty function used to intialize FamilySpecificHook array
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE - always
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNDefaultFamilyHookNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ return TRUE;
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnflow.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnflow.c
new file mode 100644
index 0000000000..4ae0fac85c
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnflow.c
@@ -0,0 +1,359 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnflow.c
+ *
+ * Common Northbridge initializer flow for MCT and DCT
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_MEM_NB_MNFLOW_FILECODE
+/* features */
+#include "mftds.h"
+
+extern MEM_PSC_FLOW_BLOCK* memPlatSpecFlowArray[];
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+STATIC
+MemNInitDCTNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+STATIC
+MemNCleanupDctRegsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+STATIC
+MemNGetPORFreqLimitTblDrvNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function programs the MCT with initial values
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - AGESA_FATAL error did not occur (it is possible to have an Error that is not AGESA_SUCCESS)
+ * @return FALSE - AGESA_FATAL error occurred
+ */
+
+BOOLEAN
+MemNInitMCTNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ UINT8 Dct;
+ BOOLEAN Flag;
+ ID_INFO CallOutIdInfo;
+
+ TechPtr = NBPtr->TechPtr;
+ // Switch Tech functions for Nb
+ NBPtr->TechBlockSwitch (NBPtr);
+ // Start Memory controller initialization sequence
+ Flag = FALSE;
+ if (TechPtr->DimmPresence (TechPtr)) {
+ AGESA_TESTPOINT (TpProcMemPlatformSpecificInit, &(NBPtr->MemPtr->StdHeader));
+ if (NBPtr->MemNPlatformSpecificFormFactorInitNb (NBPtr)) {
+ AGESA_TESTPOINT (TpProcMemSpdTiming, &(NBPtr->MemPtr->StdHeader));
+ if (TechPtr->SpdCalcWidth (TechPtr)) {
+ AGESA_TESTPOINT (TpProcMemSpeedTclConfig, &(NBPtr->MemPtr->StdHeader));
+ if (TechPtr->SpdGetTargetSpeed (TechPtr)) {
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ NBPtr->SwitchDCT (NBPtr, Dct);
+
+ Flag |= MemNInitDCTNb (NBPtr);
+ }
+
+ if (Flag && !NBPtr->IsSupported[TwoStageDramInit] && (NBPtr->MCTPtr->ErrCode != AGESA_FATAL)) {
+ MemFInitTableDrive (NBPtr, MTBeforeDInit);
+ AGESA_TESTPOINT (TpProcMemBeforeAgesaHookBeforeDramInit, &(NBPtr->MemPtr->StdHeader));
+ CallOutIdInfo.IdField.SocketId = NBPtr->MCTPtr->SocketId;
+ CallOutIdInfo.IdField.ModuleId = NBPtr->MCTPtr->DieId;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nCalling out to Platform BIOS on Socket %d Module %d...\n", CallOutIdInfo.IdField.SocketId, CallOutIdInfo.IdField.ModuleId);
+ AgesaHookBeforeDramInit ((UINTN) CallOutIdInfo.IdInformation, NBPtr->MemPtr);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nVDDIO = 1.%dV\n", (NBPtr->RefPtr->DDR3Voltage == VOLT1_5) ? 5 :
+ (NBPtr->RefPtr->DDR3Voltage == VOLT1_35) ? 35 :
+ (NBPtr->RefPtr->DDR3Voltage == VOLT1_25) ? 25 : 999);
+ AGESA_TESTPOINT (TpProcMemAfterAgesaHookBeforeDramInit, &(NBPtr->MemPtr->StdHeader));
+ IDS_OPTION_HOOK (IDS_BEFORE_DRAM_INIT, NBPtr, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->StartupDCT (NBPtr);
+ }
+ }
+ }
+ }
+ }
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode != AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the platform specific block for families that support
+ * table driven form factor
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - AGESA_SUCCESS
+ */
+
+BOOLEAN
+MemNPlatformSpecificFormFactorInitTblDrvNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dct;
+
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ NBPtr->SwitchDCT (NBPtr, Dct);
+ NBPtr->PsPtr->MemPDoPs = MemPPSCFlow;
+ NBPtr->PsPtr->MemPGetPORFreqLimit = MemNGetPORFreqLimitTblDrvNb;
+ NBPtr->PsPtr->MemPGetPass1Seeds = MemPGetPSCPass1Seed;
+ }
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function selects appropriate Tech functions for the NB.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNTechBlockSwitchNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+
+ TechPtr = NBPtr->TechPtr;
+
+ // Specify Dimm-Byte training for Nb
+ MemTDimmByteTrainInit (TechPtr);
+
+ // Filter included for RcvrEn training.
+ // note: If you'd like to drop the filter, you have to comment out these two lines together.
+ TechPtr->MaxFilterDly = MAX_FILTER_DLY_DDR3;
+ TechPtr->SaveRcvrEnDly = MemTSaveRcvrEnDlyByteFilter;
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function programs the DCT with initial values
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - Error did not occur
+ * @return FALSE - Error occurred
+ */
+
+BOOLEAN
+STATIC
+MemNInitDCTNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ TechPtr = NBPtr->TechPtr;
+ TechPtr->SetDramMode (TechPtr);
+
+ if (!NBPtr->MCTPtr->GangedMode || (NBPtr->MCTPtr->Dct == 0)) {
+ if (NBPtr->DCTPtr->Timings.DctDimmValid == 0) {
+ NBPtr->DisableDCT (NBPtr);
+ } else {
+ MemNCleanupDctRegsNb (NBPtr);
+ if (TechPtr->AutoCycTiming (TechPtr)) {
+ if (TechPtr->SpdSetBanks (TechPtr)) {
+ if (NBPtr->StitchMemory (NBPtr)) {
+ // if all dimms on a DCT are disabled, the DCT needs to be disabled.
+ if (NBPtr->DCTPtr->Timings.CsEnabled != 0) {
+ if (NBPtr->AutoConfig (NBPtr)) {
+ if (NBPtr->PlatformSpec (NBPtr)) {
+ return TRUE;
+ }
+ }
+ } else {
+ NBPtr->DisableDCT (NBPtr);
+ }
+ }
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * This function clears DCT registers
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+STATIC
+MemNCleanupDctRegsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ BIT_FIELD_NAME BitField;
+
+ for (BitField = BFCSBaseAddr0Reg; BitField <= BFCSBaseAddr7Reg; BitField++) {
+ MemNSetBitFieldNb (NBPtr, BitField, 0);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This is function gets the POR speed limit for families supports table driven form factor
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+STATIC
+MemNGetPORFreqLimitTblDrvNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 i;
+
+ i = 0;
+ while (memPlatSpecFlowArray[i] != NULL) {
+ if ((memPlatSpecFlowArray[i])->MaxFrequency (NBPtr, (memPlatSpecFlowArray[i])->EntryOfTables)) {
+ break;
+ }
+ i++;
+ }
+} \ No newline at end of file
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnmct.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnmct.c
new file mode 100644
index 0000000000..ad2c01e294
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnmct.c
@@ -0,0 +1,1313 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnmct.c
+ *
+ * Northbridge Common MCT supporting functions
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mu.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "GeneralServices.h"
+#include "cpuFeatures.h"
+#include "merrhdl.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_MEM_NB_MNMCT_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define _16MB_RJ16 0x0100
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+BOOLEAN
+STATIC
+MemNSetMTRRrangeNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Base,
+ IN OUT UINT32 *LimitPtr,
+ IN UINT32 MtrrAddr,
+ IN UINT8 MtrrType
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern BUILD_OPT_CFG UserOptions;
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Get max frequency from OEM platform definition, from
+ * any user override (limiting) of max frequency, and
+ * from any Si Revision Specific information. Return
+ * the least of these three in DIE_STRUCT.Timings.TargetSpeed.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNSyncTargetSpeedNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST UINT16 DdrMaxRateTab[] = {
+ UNSUPPORTED_DDR_FREQUENCY,
+ DDR1600_FREQUENCY,
+ DDR1333_FREQUENCY,
+ DDR1066_FREQUENCY,
+ DDR800_FREQUENCY,
+ DDR667_FREQUENCY,
+ DDR533_FREQUENCY,
+ DDR400_FREQUENCY
+ };
+
+ UINT8 Dct;
+ UINT8 Channel;
+ UINT16 MinSpeed;
+ UINT16 DdrMaxRate;
+ DCT_STRUCT *DCTPtr;
+ USER_MEMORY_TIMING_MODE *ChnlTmgMod;
+ USER_MEMORY_TIMING_MODE Mode[MAX_CHANNELS_PER_SOCKET];
+ MEMORY_BUS_SPEED MemClkFreq;
+ MEMORY_BUS_SPEED ProposedFreq;
+
+ ASSERT (NBPtr->DctCount <= sizeof (Mode));
+ MinSpeed = 16000;
+ DdrMaxRate = 16000;
+ if (NBPtr->IsSupported[CheckMaxDramRate]) {
+ // Check maximum DRAM data rate that the processor is designed to support.
+ DdrMaxRate = DdrMaxRateTab[MemNGetBitFieldNb (NBPtr, BFDdrMaxRate)];
+ NBPtr->FamilySpecificHook[GetDdrMaxRate] (NBPtr, &DdrMaxRate);
+ IDS_OPTION_HOOK (IDS_SKIP_FUSED_MAX_RATE, &DdrMaxRate, &NBPtr->MemPtr->StdHeader);
+ }
+
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ DCTPtr = NBPtr->DCTPtr;
+
+ // Check if input user time mode is valid or not
+ ASSERT ((NBPtr->RefPtr->UserTimingMode == TIMING_MODE_SPECIFIC) ||
+ (NBPtr->RefPtr->UserTimingMode == TIMING_MODE_LIMITED) ||
+ (NBPtr->RefPtr->UserTimingMode == TIMING_MODE_AUTO));
+ Mode[Dct] = NBPtr->RefPtr->UserTimingMode;
+ // Check if input clock value is valid or not
+ ASSERT ((NBPtr->ChannelPtr->TechType == DDR3_TECHNOLOGY) ?
+ (NBPtr->RefPtr->MemClockValue >= DDR667_FREQUENCY) :
+ (NBPtr->RefPtr->MemClockValue <= DDR1066_FREQUENCY));
+ MemClkFreq = NBPtr->RefPtr->MemClockValue;
+ if (DCTPtr->Timings.DctDimmValid != 0) {
+ Channel = MemNGetSocketRelativeChannelNb (NBPtr, Dct, 0);
+ ChnlTmgMod = (USER_MEMORY_TIMING_MODE *) FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_BUS_SPEED, NBPtr->MCTPtr->SocketId, Channel, 0,
+ &(NBPtr->MCTPtr->LogicalCpuid), &(NBPtr->MemPtr->StdHeader));
+ if (ChnlTmgMod != NULL) {
+ // Check if input user timing mode is valid or not
+ ASSERT ((ChnlTmgMod[0] == TIMING_MODE_SPECIFIC) || (ChnlTmgMod[0] == TIMING_MODE_LIMITED) ||
+ (ChnlTmgMod[0] != TIMING_MODE_AUTO));
+ if (ChnlTmgMod[0] != TIMING_MODE_AUTO) {
+ Mode[Dct] = ChnlTmgMod[0];
+ // Check if input clock value is valid or not
+ ASSERT ((NBPtr->ChannelPtr->TechType == DDR3_TECHNOLOGY) ?
+ ((MEMORY_BUS_SPEED)ChnlTmgMod[1] >= DDR667_FREQUENCY) :
+ ((MEMORY_BUS_SPEED)ChnlTmgMod[1] <= DDR1066_FREQUENCY));
+ MemClkFreq = (MEMORY_BUS_SPEED)ChnlTmgMod[1];
+ }
+ }
+
+ ProposedFreq = UserOptions.CfgMemoryBusFrequencyLimit;
+ if (Mode[Dct] == TIMING_MODE_LIMITED) {
+ if (MemClkFreq < ProposedFreq) {
+ ProposedFreq = MemClkFreq;
+ }
+ } else if (Mode[Dct] == TIMING_MODE_SPECIFIC) {
+ ProposedFreq = MemClkFreq;
+ }
+
+ if (Mode[Dct] == TIMING_MODE_SPECIFIC) {
+ DCTPtr->Timings.TargetSpeed = (UINT16) ProposedFreq;
+ } else {
+ // "limit" mode
+ if (DCTPtr->Timings.TargetSpeed > ProposedFreq) {
+ DCTPtr->Timings.TargetSpeed = (UINT16) ProposedFreq;
+ }
+ }
+
+ NBPtr->MemNCapSpeedBatteryLife (NBPtr);
+
+ if (DCTPtr->Timings.TargetSpeed > DdrMaxRate) {
+ if (Mode[Dct] == TIMING_MODE_SPECIFIC) {
+ PutEventLog (AGESA_ALERT, MEM_ALERT_USER_TMG_MODE_OVERRULED, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
+ SetMemError (AGESA_ALERT, NBPtr->MCTPtr);
+ }
+ DCTPtr->Timings.TargetSpeed = DdrMaxRate;
+ }
+
+ IDS_SKIP_HOOK (IDS_POR_MEM_FREQ, NBPtr, &NBPtr->MemPtr->StdHeader) {
+ //
+ //Call Platform POR Frequency Override
+ //
+ if (!MemProcessConditionalOverrides (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr, PSO_ACTION_SPEEDLIMIT, ALL_DIMMS)) {
+ //
+ // Get the POR frequency limit
+ //
+ NBPtr->PsPtr->MemPGetPORFreqLimit (NBPtr);
+ }
+ }
+ IDS_OPTION_HOOK (IDS_STRETCH_FREQUENCY_LIMIT, NBPtr, &NBPtr->MemPtr->StdHeader);
+
+ if (MinSpeed > DCTPtr->Timings.TargetSpeed) {
+ MinSpeed = DCTPtr->Timings.TargetSpeed;
+ }
+ }
+ }
+
+ if (MinSpeed == DDR667_FREQUENCY) {
+ NBPtr->StartupSpeed = DDR667_FREQUENCY;
+ }
+
+ // Sync all DCTs to the same speed
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ NBPtr->DCTPtr->Timings.TargetSpeed = MinSpeed;
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function waits for all DCTs to be ready
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - No fatal error occurs.
+ * @return FALSE - Fatal error occurs.
+ */
+
+BOOLEAN
+MemNSyncDctsReadyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ if (NBPtr->MCTPtr->DimmValid) {
+ MemNPollBitFieldNb (NBPtr, BFDramEnabled, 1, PCI_ACCESS_TIMEOUT, FALSE);
+ // Re-enable phy compensation engine after Dram init has completed
+ MemNSwitchDCTNb (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 0);
+ }
+ // Wait 750 us for the phy compensation engine to reinitialize.
+ MemUWait10ns (75000, NBPtr->MemPtr);
+
+ MemNSyncAddrMapToAllNodesNb (NBPtr);
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function create the HT memory map
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - No fatal error occurs.
+ * @return FALSE - Fatal error occurs.
+ */
+
+BOOLEAN
+MemNHtMemMapInitNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 BottomIo;
+ UINT32 HoleOffset;
+ UINT32 DctSelBaseAddr;
+ UINT32 NodeSysBase;
+ UINT32 NodeSysLimit;
+ MEM_PARAMETER_STRUCT *RefPtr;
+ DIE_STRUCT *MCTPtr;
+
+ RefPtr = NBPtr->RefPtr;
+ MCTPtr = NBPtr->MCTPtr;
+ //
+ // Physical addresses in this function are right adjusted by 16 bits ([47:16])
+ // They are BottomIO, HoleOffset, DctSelBaseAddr, NodeSysBase, NodeSysLimit.
+ //
+
+ // Enforce bottom of IO be be 128MB aligned
+ ASSERT ((RefPtr->BottomIo < (_4GB_RJ16 >> 8)) && (RefPtr->BottomIo != 0));
+ BottomIo = (RefPtr->BottomIo & 0xF8) << 8;
+
+ if (!MCTPtr->GangedMode) {
+ DctSelBaseAddr = MCTPtr->DctData[0].Timings.DctMemSize;
+ } else {
+ DctSelBaseAddr = 0;
+ }
+
+ if (MCTPtr->NodeMemSize) {
+ NodeSysBase = NBPtr->SharedPtr->CurrentNodeSysBase;
+ NodeSysLimit = NodeSysBase + MCTPtr->NodeMemSize - 1;
+ DctSelBaseAddr += NodeSysBase;
+
+ if ((NBPtr->IsSupported[ForceEnMemHoleRemapping]) || (RefPtr->MemHoleRemapping)) {
+ if ((NodeSysBase < BottomIo) && (NodeSysLimit >= BottomIo)) {
+ // HW Dram Remap
+ MCTPtr->Status[SbHWHole] = TRUE;
+ RefPtr->GStatus[GsbHWHole] = TRUE;
+ MCTPtr->NodeHoleBase = BottomIo;
+ RefPtr->HoleBase = BottomIo;
+
+ HoleOffset = _4GB_RJ16 - BottomIo;
+
+ NodeSysLimit += HoleOffset;
+
+ if ((DctSelBaseAddr > 0) && (DctSelBaseAddr < BottomIo)) {
+ HoleOffset += DctSelBaseAddr;
+ } else {
+ if (DctSelBaseAddr >= BottomIo) {
+ DctSelBaseAddr += HoleOffset;
+ }
+ HoleOffset += NodeSysBase;
+ }
+
+ MemNSetBitFieldNb (NBPtr, BFDramHoleBase, BottomIo >> 8);
+ MemNSetBitFieldNb (NBPtr, BFDramHoleOffset, HoleOffset >> 7);
+ MemNSetBitFieldNb (NBPtr, BFDramHoleValid, 1);
+
+ } else if (NodeSysBase == BottomIo) {
+ // SW Node Hoist
+ MCTPtr->Status[SbSWNodeHole] = TRUE;
+ RefPtr->GStatus[GsbSpIntRemapHole] = TRUE;
+ RefPtr->GStatus[GsbSoftHole] = TRUE;
+
+ RefPtr->HoleBase = NodeSysBase;
+ DctSelBaseAddr = _4GB_RJ16 + (DctSelBaseAddr - NodeSysBase);
+ NodeSysLimit = _4GB_RJ16 + (NodeSysLimit - NodeSysBase);
+ NodeSysBase = _4GB_RJ16;
+
+ } else if ((NodeSysBase < HT_REGION_BASE_RJ16) && (NodeSysLimit >= HT_REGION_BASE_RJ16)) {
+ if (!NBPtr->SharedPtr->UndoHoistingAbove1TB) {
+ // SW Hoisting above 1TB to avoid HT Reserved region
+ DctSelBaseAddr = _1TB_RJ16 + (DctSelBaseAddr - NodeSysBase);
+ NodeSysLimit = _1TB_RJ16 + (NodeSysLimit - NodeSysBase);
+ NodeSysBase = _1TB_RJ16;
+
+ if (RefPtr->LimitMemoryToBelow1Tb) {
+ // Flag to undo 1TB hoisting after training
+ NBPtr->SharedPtr->UndoHoistingAbove1TB = TRUE;
+ }
+ }
+
+ } else {
+ // No Remapping. Normal Contiguous mapping
+ }
+ } else {
+ // No Remapping. Normal Contiguous mapping
+ }
+
+ if (NBPtr->IsSupported[Check1GAlign]) {
+ if (UserOptions.CfgNodeMem1GBAlign) {
+ NBPtr->MemPNodeMemBoundaryNb (NBPtr, (UINT32 *)&NodeSysLimit);
+ }
+ }
+
+ MCTPtr->NodeSysBase = NodeSysBase;
+ MCTPtr->NodeSysLimit = NodeSysLimit;
+ RefPtr->SysLimit = NodeSysLimit;
+ RefPtr->Sub1THoleBase = (NodeSysLimit < HT_REGION_BASE_RJ16) ? (NodeSysLimit + 1) : RefPtr->Sub1THoleBase;
+ IDS_OPTION_HOOK (IDS_MEM_SIZE_OVERLAY, NBPtr, &NBPtr->MemPtr->StdHeader);
+
+ NBPtr->SharedPtr->TopNode = NBPtr->Node;
+
+ NBPtr->SharedPtr->NodeMap[NBPtr->Node].IsValid = TRUE;
+ NBPtr->SharedPtr->NodeMap[NBPtr->Node].SysBase = NodeSysBase;
+ NBPtr->SharedPtr->NodeMap[NBPtr->Node].SysLimit = NodeSysLimit & 0xFFFFFF00;
+
+ MemNSetBitFieldNb (NBPtr, BFDramBaseAddr, NodeSysBase >> (27 - 16));
+ MemNSetBitFieldNb (NBPtr, BFDramLimitAddr, NodeSysLimit >> (27 - 16));
+
+ if ((MCTPtr->DctData[1].Timings.DctMemSize != 0) && (!NBPtr->Ganged)) {
+ MemNSetBitFieldNb (NBPtr, BFDctSelBaseAddr, DctSelBaseAddr >> 11);
+ MemNSetBitFieldNb (NBPtr, BFDctSelHiRngEn, 1);
+ MemNSetBitFieldNb (NBPtr, BFDctSelHi, 1);
+ MemNSetBitFieldNb (NBPtr, BFDctSelBaseOffset, DctSelBaseAddr >> 10);
+ }
+
+ NBPtr->SharedPtr->CurrentNodeSysBase = (NodeSysLimit + 1) & 0xFFFFFFF0;
+ }
+ return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * Program system DRAM map to this node
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNSyncAddrMapToAllNodesNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Node;
+ UINT32 NodeSysBase;
+ UINT32 NodeSysLimit;
+ UINT8 WeReMask;
+ MEM_PARAMETER_STRUCT *RefPtr;
+
+ RefPtr = NBPtr->RefPtr;
+ for (Node = 0; Node < NBPtr->NodeCount; Node++) {
+ NodeSysBase = NBPtr->SharedPtr->NodeMap[Node].SysBase;
+ NodeSysLimit = NBPtr->SharedPtr->NodeMap[Node].SysLimit;
+ if (NBPtr->SharedPtr->NodeMap[Node].IsValid) {
+ WeReMask = 3;
+ } else {
+ WeReMask = 0;
+ }
+ // Set the Dram base and set the WE and RE flags in the base.
+ MemNSetBitFieldNb (NBPtr, BFDramBaseReg0 + Node, (NodeSysBase << 8) | WeReMask);
+ MemNSetBitFieldNb (NBPtr, BFDramBaseHiReg0 + Node, NodeSysBase >> 24);
+ // Set the Dram limit and set DstNode.
+ MemNSetBitFieldNb (NBPtr, BFDramLimitReg0 + Node, (NodeSysLimit << 8) | Node);
+ MemNSetBitFieldNb (NBPtr, BFDramLimitHiReg0 + Node, NodeSysLimit >> 24);
+
+ if (RefPtr->GStatus[GsbHWHole]) {
+ MemNSetBitFieldNb (NBPtr, BFDramMemHoistValid, 1);
+ MemNSetBitFieldNb (NBPtr, BFDramHoleBase, (RefPtr->HoleBase >> 8));
+ }
+ }
+
+ NBPtr->FamilySpecificHook[InitExtMMIOAddr] (NBPtr, NULL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function enables power down mode
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNPowerDownCtlNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_PARAMETER_STRUCT *RefPtr;
+ UINT8 PowerDownMode;
+
+ RefPtr = NBPtr->RefPtr;
+
+ // we can't enable powerdown mode when doing WL
+ if (RefPtr->EnablePowerDown) {
+ MemNSetBitFieldNb (NBPtr, BFPowerDownEn, 1);
+ PowerDownMode = (UINT8) ((UserOptions.CfgPowerDownMode == POWER_DOWN_MODE_AUTO) ? POWER_DOWN_BY_CHANNEL : UserOptions.CfgPowerDownMode);
+ IDS_OPTION_HOOK (IDS_POWERDOWN_MODE, &PowerDownMode, &(NBPtr->MemPtr->StdHeader));
+ if (PowerDownMode) {
+ MemNSetBitFieldNb (NBPtr, BFPowerDownMode, 1);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets the Optimal Critical Gross Delay Difference between
+ * the delay parameters across all Dimms on each bytelane. Then takes the
+ * largest of all the bytelanes.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDly1 - Type of first Gross Delay parameter
+ * @param[in] TrnDly2 - Type of second Gross Delay parameter
+ *
+ * @return The largest difference between the largest and smallest
+ * of the two Gross delay types within a single bytelane
+ */
+INT8
+MemNGetOptimalCGDDNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDly1,
+ IN TRN_DLY_TYPE TrnDly2
+ )
+{
+ INT8 CGDD;
+ INT8 GDD;
+ UINT8 Dimm1;
+ UINT8 Dimm2;
+ UINT8 ByteLane;
+ UINT16 CsEnabled;
+ BOOLEAN CGDDInit;
+ BOOLEAN SameDelayType;
+
+ CGDD = 0;
+ CGDDInit = FALSE;
+ SameDelayType = (BOOLEAN) (TrnDly1 == TrnDly2);
+ CsEnabled = NBPtr->DCTPtr->Timings.CsEnabled;
+
+ // If the two delay types compared are the same type, then no need to compare the same
+ // pair twice. Adjustments are made in the upper bound and lower bound of the loop to
+ // handle this.
+ for (Dimm1 = 0; Dimm1 < (SameDelayType ? (MAX_DIMMS_PER_CHANNEL - 1) : MAX_DIMMS_PER_CHANNEL); Dimm1 ++) {
+ if (CsEnabled & (UINT16) (3 << (Dimm1 << 1))) {
+ for (Dimm2 = (SameDelayType ? (Dimm1 + 1) : 0); Dimm2 < MAX_DIMMS_PER_CHANNEL; Dimm2 ++) {
+ if ((CsEnabled & (UINT16) (3 << (Dimm2 << 1)))) {
+ for (ByteLane = 0 ; ByteLane < 8 ; ByteLane++) {
+ // check each byte lane delay pair
+ GDD = (UINT8) (NBPtr->GetTrainDly (NBPtr, TrnDly1, DIMM_BYTE_ACCESS (Dimm1, ByteLane)) >> 5) -
+ (UINT8) (NBPtr->GetTrainDly (NBPtr, TrnDly2, DIMM_BYTE_ACCESS (Dimm2, ByteLane)) >> 5);
+ // If the 2 delay types to be compared are the same, then keep the absolute difference
+ if (SameDelayType && (GDD < 0)) {
+ GDD = (-GDD);
+ }
+
+ // If CGDD is yet to be initialized, initialize it
+ // Otherwise, keep the largest difference so far
+ CGDD = (!CGDDInit) ? GDD : ((CGDD > GDD) ? CGDD : GDD);
+ if (!CGDDInit) {
+ CGDDInit = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ return CGDD;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates the critical delay difference (CDD)
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDlyType1 - Type of first Gross Delay parameter
+ * @param[in] TrnDlyType2 - Type of second Gross Delay parameter
+ * @param[in] SameDimm - CDD of same DIMMs
+ * @param[in] DiffDimm - CDD of different DIMMs
+ *
+ * @return CDD term - in 1/2 MEMCLK
+ */
+INT16
+MemNCalcCDDNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDlyType1,
+ IN TRN_DLY_TYPE TrnDlyType2,
+ IN BOOLEAN SameDimm,
+ IN BOOLEAN DiffDimm
+ )
+{
+ INT16 CDD;
+ INT16 CDDtemp;
+ UINT16 TrnDly1;
+ UINT16 TrnDly2;
+ UINT8 i;
+ UINT8 j;
+ UINT8 ByteLane;
+ UINT16 CsEnabled;
+ BOOLEAN SameDlyType;
+
+ SameDlyType = (BOOLEAN) (TrnDlyType1 == TrnDlyType2);
+ CsEnabled = NBPtr->DCTPtr->Timings.CsEnabled;
+ CDD = -127;
+ // If the two delay types compared are the same type, then no need to compare the same
+ // pair twice. Adjustments are made in the upper bound and lower bound of the loop to
+ // handle this.
+ for (i = 0; i < (SameDlyType ? (NBPtr->CsPerChannel - NBPtr->CsPerDelay) : NBPtr->CsPerChannel); i = i + NBPtr->CsPerDelay) {
+ if ((CsEnabled & ((UINT16) ((NBPtr->CsPerDelay == 2) ? 3 : 1) << i)) != 0) {
+ for (j = SameDlyType ? (i + NBPtr->CsPerDelay) : 0; j < NBPtr->CsPerChannel; j = j + NBPtr->CsPerDelay) {
+ if (((CsEnabled & ((UINT16) ((NBPtr->CsPerDelay == 2)? 3 : 1) << j)) != 0) &&
+ ((SameDimm && ((i / 2) == (j / 2))) || (DiffDimm && ((i / 2) != (j / 2))))) {
+ for (ByteLane = 0; ByteLane < ((NBPtr->MCTPtr->Status[SbEccDimms] && NBPtr->IsSupported[EccByteTraining]) ? 9 : 8); ByteLane++) {
+ /// @todo: Gross delay mask should not be constant.
+ TrnDly1 = GetTrainDlyFromHeapNb (NBPtr, TrnDlyType1, DIMM_BYTE_ACCESS (i / NBPtr->CsPerDelay, ByteLane)) >> 5; // Gross delay only
+ TrnDly2 = GetTrainDlyFromHeapNb (NBPtr, TrnDlyType2, DIMM_BYTE_ACCESS (j / NBPtr->CsPerDelay, ByteLane)) >> 5; // Gross delay only
+
+ CDDtemp = TrnDly1 - TrnDly2;
+ // If the 2 delay types to be compared are the same, then keep the absolute difference
+ if ((SameDlyType) && (CDDtemp < 0)) {
+ CDDtemp = (-CDDtemp);
+ }
+
+ CDD = (CDD < CDDtemp) ? CDDtemp : CDD;
+ }
+ }
+ }
+ }
+ }
+
+ return CDD;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets DQS timing from data saved in heap.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDlyType - type of delay to be set
+ * @param[in] Drbn - encoding of Dimm-Rank-Byte-Nibble to be accessed
+ * (use either DIMM_BYTE_ACCESS(dimm,byte) or CS_NBBL_ACCESS(cs,nibble) to use this encoding
+ *
+ * @return value of the target timing.
+ */
+UINT16
+GetTrainDlyFromHeapNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDlyType,
+ IN DRBN Drbn
+ )
+{
+ UINT8 Dimm;
+ UINT8 Byte;
+ UINT16 TrainDly;
+ CH_DEF_STRUCT *ChannelPtr;
+ MEM_TECH_BLOCK *TechPtr;
+
+ Dimm = DRBN_DIMM (Drbn);
+ Byte = DRBN_BYTE (Drbn);
+ ChannelPtr = NBPtr->ChannelPtr;
+ TechPtr = NBPtr->TechPtr;
+
+ ASSERT (Dimm < (NBPtr->CsPerChannel / NBPtr->CsPerDelay));
+ ASSERT (Byte <= ECC_DLY);
+
+ if (NBPtr->MemPstate == MEMORY_PSTATE1) {
+ switch (TrnDlyType) {
+ case AccessRcvEnDly:
+ TrainDly = ChannelPtr->RcvEnDlysMemPs1[Dimm * TechPtr->DlyTableWidth () + Byte];
+ break;
+ case AccessWrDqsDly:
+ TrainDly = ChannelPtr->WrDqsDlysMemPs1[Dimm * TechPtr->DlyTableWidth () + Byte];
+ break;
+ case AccessWrDatDly:
+ TrainDly = ChannelPtr->WrDatDlysMemPs1[Dimm * TechPtr->DlyTableWidth () + Byte];
+ break;
+ case AccessRdDqsDly:
+ TrainDly = ChannelPtr->RdDqsDlysMemPs1[Dimm * TechPtr->DlyTableWidth () + Byte];
+ break;
+ default:
+ TrainDly = 0;
+ IDS_ERROR_TRAP;
+ }
+ } else {
+ switch (TrnDlyType) {
+ case AccessRcvEnDly:
+ TrainDly = ChannelPtr->RcvEnDlys[Dimm * TechPtr->DlyTableWidth () + Byte];
+ break;
+ case AccessWrDqsDly:
+ TrainDly = ChannelPtr->WrDqsDlys[Dimm * TechPtr->DlyTableWidth () + Byte];
+ break;
+ case AccessWrDatDly:
+ TrainDly = ChannelPtr->WrDatDlys[Dimm * TechPtr->DlyTableWidth () + Byte];
+ break;
+ case AccessRdDqsDly:
+ TrainDly = ChannelPtr->RdDqsDlys[Dimm * TechPtr->DlyTableWidth () + Byte];
+ break;
+ default:
+ TrainDly = 0;
+ IDS_ERROR_TRAP;
+ }
+ }
+
+ return TrainDly;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the fixed MTRRs for common legacy ranges.
+ * It sets TOP_MEM and TOM2 and some variable MTRRs with WB Uncacheable type.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - An Error value lower than AGESA_FATAL may have occurred
+ * @return FALSE - An Error value greater than or equal to AGESA_FATAL may have occurred
+ */
+
+BOOLEAN
+MemNCPUMemTypingNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 Bottom32bIO;
+ UINT32 Bottom40bIO;
+ UINT32 Cache32bTOP;
+ S_UINT64 SMsr;
+
+ MEM_DATA_STRUCT *MemPtr;
+ MEM_PARAMETER_STRUCT *RefPtr;
+ RefPtr = NBPtr->RefPtr;
+ MemPtr = NBPtr->MemPtr;
+
+ //
+ //======================================================================
+ // Set temporary top of memory from Node structure data.
+ // Adjust temp top of memory down to accommodate 32-bit IO space.
+ //======================================================================
+ //Bottom40bIO=top of memory, right justified 16 bits (defines dram versus IO space type)
+ //Bottom32bIO=sub 4GB top of memory, right justified 16 bits (defines dram versus IO space type)
+ //Cache32bTOP=sub 4GB top of WB cacheable memory, right justified 16 bits
+ //
+ if (RefPtr->HoleBase != 0) {
+ Bottom32bIO = RefPtr->HoleBase;
+ } else if (RefPtr->BottomIo != 0) {
+ Bottom32bIO = (UINT32)RefPtr->BottomIo << (24 - 16);
+ } else {
+ Bottom32bIO = (UINT32)1 << (24 - 16);
+ }
+
+ Cache32bTOP = RefPtr->SysLimit + 1;
+ if (Cache32bTOP < _4GB_RJ16) {
+ Bottom40bIO = 0;
+ if (Bottom32bIO >= Cache32bTOP) {
+ Bottom32bIO = Cache32bTOP;
+ }
+ } else {
+ Bottom40bIO = Cache32bTOP;
+ }
+
+ Cache32bTOP = Bottom32bIO;
+
+
+ //
+ //======================================================================
+ // Set default values for CPU registers
+ //======================================================================
+ //
+ LibAmdMsrRead (SYS_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.lo |= 0x1C0000; // turn on modification enable bit and
+ // mtrr enable bits
+ LibAmdMsrWrite (SYS_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ SMsr.lo = SMsr.hi = 0x1E1E1E1E;
+ LibAmdMsrWrite (0x250, (UINT64 *)&SMsr, &MemPtr->StdHeader); // 0 - 512K = WB Mem
+ LibAmdMsrWrite (0x258, (UINT64 *)&SMsr, &MemPtr->StdHeader); // 512K - 640K = WB Mem
+
+ //
+ //======================================================================
+ // Set variable MTRR values
+ //======================================================================
+ //
+ MemNSetMTRRrangeNb (NBPtr, 0, &Cache32bTOP, 0x200, 6);
+
+ RefPtr->Sub4GCacheTop = Cache32bTOP << 16;
+
+ //
+ //======================================================================
+ // Set TOP_MEM and TOM2 CPU registers
+ //======================================================================
+ //
+ SMsr.hi = Bottom32bIO >> (32 - 16);
+ SMsr.lo = Bottom32bIO << 16;
+ LibAmdMsrWrite (TOP_MEM, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ IDS_HDT_CONSOLE (MEM_FLOW, "TOP_MEM: %08x0000\n", Bottom32bIO);
+
+ if (Bottom40bIO) {
+ SMsr.hi = Bottom40bIO >> (32 - 16);
+ SMsr.lo = Bottom40bIO << 16;
+ } else {
+ SMsr.hi = 0;
+ SMsr.lo = 0;
+ }
+ LibAmdMsrWrite (TOP_MEM2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ LibAmdMsrRead (SYS_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ if (Bottom40bIO) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "TOP_MEM2: %08x0000\n", Bottom40bIO);
+ IDS_HDT_CONSOLE (MEM_FLOW, "Sub1THoleBase: %08x0000\n", RefPtr->Sub1THoleBase);
+ // Enable TOM2
+ SMsr.lo |= 0x00600000;
+ } else {
+ // Disable TOM2
+ SMsr.lo &= ~0x00600000;
+ }
+ SMsr.lo &= 0xFFF7FFFF; // turn off modification enable bit
+ LibAmdMsrWrite (SYS_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ return (BOOLEAN) (NBPtr->MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function runs on the BSP only, it sets the fixed MTRRs for common legacy ranges.
+ * It sets TOP_MEM and TOM2 and some variable MTRRs with WB Uncacheable type.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNUMAMemTypingNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 Bottom32bIO;
+ UINT32 Bottom32bUMA;
+ UINT32 Cache32bTOP;
+ UINT32 Value32;
+ UINT8 BitCount;
+ UINT8 i;
+
+ MEM_PARAMETER_STRUCT *RefPtr;
+ RefPtr = NBPtr->RefPtr;
+ BitCount = 0;
+ //
+ //======================================================================
+ // Adjust temp top of memory down to accommodate UMA memory start
+ //======================================================================
+ // Bottom32bIO=sub 4GB top of memory, right justified 16 bits (defines dram versus IO space type)
+ // Cache32bTOP=sub 4GB top of WB cacheable memory, right justified 16 bits
+ //
+ Bottom32bIO = RefPtr->Sub4GCacheTop >> 16;
+ Bottom32bUMA = RefPtr->UmaBase;
+
+ if (Bottom32bUMA < Bottom32bIO) {
+ Cache32bTOP = Bottom32bUMA;
+ RefPtr->Sub4GCacheTop = Bottom32bUMA << 16;
+ //
+ //======================================================================
+ //Set variable MTRR values
+ //======================================================================
+ //
+ Value32 = Cache32bTOP;
+ //Pre-check the bit count of bottom Uma to see if it is potentially running out of Mtrr while typing.
+ while (Value32 != 0) {
+ i = LibAmdBitScanForward (Value32);
+ Value32 &= ~ (1 << i);
+ BitCount++;
+ }
+
+ if (BitCount > 5) {
+ NBPtr->RefPtr->GStatus[GsbMTRRshort] = TRUE;
+ MemNSetMTRRUmaRegionUCNb (NBPtr, &Cache32bTOP, &Bottom32bIO);
+ } else {
+ MemNSetMTRRrangeNb (NBPtr, 0, &Cache32bTOP, 0x200, 6);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * Program MTRRs to describe given range as given cache type. Use MTRR pairs
+ * starting with the given MTRRphys Base address, and use as many as is
+ * required up to (excluding) MSR 020C, which is reserved for OS.
+ *
+ * "Limit" in the context of this procedure is not the numerically correct
+ * limit, but rather the Last address+1, for purposes of coding efficiency
+ * and readability. Size of a region is then Limit-Base.
+ *
+ * 1. Size of each range must be a power of two
+ * 2. Each range must be naturally aligned (Base is same as size)
+ *
+ * There are two code paths: the ascending path and descending path (analogous
+ * to bsf and bsr), where the next limit is a function of the next set bit in
+ * a forward or backward sequence of bits (as a function of the Limit). We
+ * start with the ascending path, to ensure that regions are naturally aligned,
+ * then we switch to the descending path to maximize MTRR usage efficiency.
+ * Base=0 is a special case where we start with the descending path.
+ * Correct Mask for region is 2comp(Size-1)-1,
+ * which is 2comp(Limit-Base-1)-1 *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Base - Base address[47:16] of specified range.
+ * @param[in] *LimitPtr - Limit address[47:16] of specified range.
+ * @param[in] MtrrAddr - address of var MTRR pair to start using.
+ * @param[in] MtrrType - Cache type for the range.
+ *
+ * @return TRUE - No failure occurred
+ * @return FALSE - Failure occurred because run out of variable-size MTRRs before completion.
+ */
+
+BOOLEAN
+STATIC
+MemNSetMTRRrangeNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Base,
+ IN OUT UINT32 *LimitPtr,
+ IN UINT32 MtrrAddr,
+ IN UINT8 MtrrType
+ )
+{
+ S_UINT64 SMsr;
+ UINT32 CurBase;
+ UINT32 CurLimit;
+ UINT32 CurSize;
+ UINT32 CurAddr;
+ UINT32 Value32;
+
+ CurBase = Base;
+ CurLimit = *LimitPtr;
+ CurAddr = MtrrAddr;
+
+ while ((CurAddr >= 0x200) && (CurAddr < 0x20A) && (CurBase < *LimitPtr)) {
+ CurSize = CurLimit = (UINT32)1 << LibAmdBitScanForward (CurBase);
+ CurLimit += CurBase;
+ if ((CurBase == 0) || (*LimitPtr < CurLimit)) {
+ CurLimit = *LimitPtr - CurBase;
+ CurSize = CurLimit = (UINT32)1 << LibAmdBitScanReverse (CurLimit);
+ CurLimit += CurBase;
+ }
+
+ // prog. MTRR with current region Base
+ SMsr.lo = (CurBase << 16) | (UINT32)MtrrType;
+ SMsr.hi = CurBase >> (32 - 16);
+ LibAmdMsrWrite (CurAddr, (UINT64 *)&SMsr, &NBPtr->MemPtr->StdHeader);
+
+ // prog. MTRR with current region Mask
+ CurAddr++; // other half of MSR pair
+ Value32 = CurSize - (UINT32)1;
+ Value32 = ~Value32;
+ SMsr.hi = (Value32 >> (32 - 16)) & NBPtr->VarMtrrHiMsk;
+ SMsr.lo = (Value32 << 16) | ((UINT32)1 << MTRR_VALID);
+ LibAmdMsrWrite (CurAddr, (UINT64 *)&SMsr, &NBPtr->MemPtr->StdHeader);
+
+ CurBase = CurLimit;
+ CurAddr++; // next MSR pair
+ }
+
+ if (CurLimit < *LimitPtr) {
+ // Announce failure
+ *LimitPtr = CurLimit;
+ IDS_ERROR_TRAP;
+ }
+
+ while ((CurAddr >= 0x200) && (CurAddr < 0x20C)) {
+ SMsr.lo = SMsr.hi = 0;
+ LibAmdMsrWrite (CurAddr, (UINT64 *)&SMsr, &NBPtr->MemPtr->StdHeader);
+ CurAddr++;
+ }
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * Program one MTRR to describe Uma region as UC cache type if we detect running out of
+ * Mtrr circumstance.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *BasePtr - Base address[47:24] of specified range.
+ * @param[in] *LimitPtr - Limit address[47:24] of specified range.
+ *
+ * @return TRUE - No fatal error occurs.
+ * @return FALSE - Fatal error occurs.
+ */
+BOOLEAN
+MemNSetMTRRUmaRegionUCNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 *BasePtr,
+ IN OUT UINT32 *LimitPtr
+ )
+{
+ S_UINT64 SMsr;
+ UINT32 Mtrr;
+ UINT32 Size;
+ UINT32 Value32;
+
+ Size = *LimitPtr - *BasePtr;
+ // Check if Size is a power of 2
+ if ((Size & (Size - 1)) != 0) {
+ for (Mtrr = 0x200; Mtrr < 0x20A; Mtrr += 2) {
+ LibAmdMsrRead (Mtrr + 1, (UINT64 *)&SMsr, &NBPtr->MemPtr->StdHeader);
+ if ((SMsr.lo & ((UINT32) 1 << 11)) == 0) {
+ MemNSetMTRRrangeNb (NBPtr, *BasePtr, LimitPtr, Mtrr, 0);
+ break;
+ }
+ }
+ if (Mtrr == 0x20A) {
+ // Run out of MTRRs
+ IDS_ERROR_TRAP;
+ }
+ } else {
+ Mtrr = 0x20A; //Reserved pair of MTRR for UMA region.
+
+ // prog. MTRR with current region Base
+ SMsr.lo = *BasePtr << 16;
+ SMsr.hi = *BasePtr >> (32 - 16);
+ LibAmdMsrWrite (Mtrr, (UINT64 *)&SMsr, &NBPtr->MemPtr->StdHeader);
+
+ // prog. MTRR with current region Mask
+ Mtrr++; // other half of MSR pair
+ Value32 = Size - (UINT32)1;
+ Value32 = ~Value32;
+ SMsr.hi = (Value32 >> (32 - 16)) & NBPtr->VarMtrrHiMsk;
+ SMsr.lo = (Value32 << 16) | ((UINT32)1 << MTRR_VALID);
+ LibAmdMsrWrite (Mtrr, (UINT64 *)&SMsr, &NBPtr->MemPtr->StdHeader);
+ }
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * Report the Uma size that is going to be allocated.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return Uma size [31:0] = Addr [47:16]
+ */
+UINT32
+MemNGetUmaSizeNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function allocates 16MB of memory for C6 storage when it is requested to be enabled
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNAllocateC6StorageClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 SysLimit;
+
+ if (IsFeatureEnabled (C6Cstate, NBPtr->MemPtr->PlatFormConfig, &(NBPtr->MemPtr->StdHeader))) {
+ SysLimit = NBPtr->RefPtr->SysLimit;
+ SysLimit -= _16MB_RJ16;
+
+ // Set Dram Limit
+ NBPtr->MCTPtr->NodeSysLimit = SysLimit;
+ NBPtr->RefPtr->SysLimit = SysLimit;
+ MemNSetBitFieldNb (NBPtr, BFDramLimitReg0, ((SysLimit << 8) & 0xFFFF0000));
+
+ // Set TOPMEM and MTRRs
+ MemNC6AdjustMSRs (NBPtr);
+
+ // Set C6Base
+ MemNSetBitFieldNb (NBPtr, BFC6Base, (SysLimit + 1) >> (24 - 16));
+
+ // C6DramLock will be set in FinalizeMCT
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function allocates 16MB of memory for C6 storage when it is requested to be enabled
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNAllocateC6StorageUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Node;
+ UINT32 SysLimit;
+ UINT32 DramLimitReg;
+
+ if (NBPtr->SharedPtr->C6Enabled || IsFeatureEnabled (C6Cstate, NBPtr->MemPtr->PlatFormConfig, &(NBPtr->MemPtr->StdHeader))) {
+
+ SysLimit = NBPtr->RefPtr->SysLimit;
+
+ // Calculate new SysLimit
+ if (!NBPtr->SharedPtr->C6Enabled) {
+ if (NBPtr->SharedPtr->NodeIntlv.NodeCnt >= 2) {
+ // Node Interleave is enabled, system memory available is reduced by 16MB * number of nodes
+ SysLimit -= _16MB_RJ16 * NBPtr->SharedPtr->NodeIntlv.NodeCnt;
+ } else {
+ // Otherwise, system memory available is reduced by 16MB
+ SysLimit -= _16MB_RJ16;
+ }
+ NBPtr->RefPtr->SysLimit = SysLimit;
+ NBPtr->SharedPtr->C6Enabled = TRUE;
+
+ // Set TOPMEM and MTRRs (only need to be done once for BSC)
+ MemNC6AdjustMSRs (NBPtr);
+ }
+
+ // Set Dram Limit
+ if (NBPtr->SharedPtr->NodeIntlv.NodeCnt >= 2) {
+ for (Node = 0; Node < NBPtr->NodeCount; Node++) {
+ DramLimitReg = MemNGetBitFieldNb (NBPtr, BFDramLimitReg0 + Node);
+ if ((DramLimitReg & 0xFFFF0000) != 0) {
+ MemNSetBitFieldNb (NBPtr, BFDramLimitReg0 + Node, ((SysLimit << 8) & 0xFFFF0000) | (DramLimitReg & 0xFFFF));
+ MemNSetBitFieldNb (NBPtr, BFDramLimitHiReg0 + Node, SysLimit >> 24);
+ }
+ }
+ // Node Interleave is enabled, CoreStateSaveDestNode points to its own node
+ MemNSetBitFieldNb (NBPtr, BFCoreStateSaveDestNode, NBPtr->Node);
+ NBPtr->MCTPtr->NodeSysLimit = SysLimit;
+ } else {
+ DramLimitReg = MemNGetBitFieldNb (NBPtr, BFDramLimitReg0 + NBPtr->SharedPtr->TopNode) & 0x0000FFFF;
+ MemNSetBitFieldNb (NBPtr, BFDramLimitReg0 + NBPtr->SharedPtr->TopNode, ((SysLimit << 8) & 0xFFFF0000) | DramLimitReg);
+ MemNSetBitFieldNb (NBPtr, BFDramLimitHiReg0 + NBPtr->SharedPtr->TopNode, SysLimit >> 24);
+
+ // Node Interleave is not enabled, CoreStateSaveDestNode points to the node that contains top memory
+ MemNSetBitFieldNb (NBPtr, BFCoreStateSaveDestNode, NBPtr->SharedPtr->TopNode);
+
+ if (NBPtr->Node == NBPtr->SharedPtr->TopNode) {
+ NBPtr->MCTPtr->NodeSysLimit = SysLimit;
+ }
+ }
+
+ // Set BFCC6SaveEn
+ MemNSetBitFieldNb (NBPtr, BFCC6SaveEn, 1);
+
+ // LockDramCfg will be set in FinalizeMCT
+ }
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function readjusts TOPMEM and MTRRs after allocating storage for C6
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemNC6AdjustMSRs (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 SysLimit;
+ UINT32 CurAddr;
+ S_UINT64 SMsr;
+
+ SysLimit = NBPtr->RefPtr->SysLimit + 1;
+ SMsr.hi = SysLimit >> (32 - 16);
+ SMsr.lo = SysLimit << 16;
+ if (SysLimit < _4GB_RJ16) {
+ LibAmdMsrWrite (TOP_MEM, (UINT64 *)&SMsr, &(NBPtr->MemPtr->StdHeader));
+ IDS_HDT_CONSOLE (MEM_FLOW, "TOP_MEM: %08x0000\n", SysLimit);
+ // If there is no UMA buffer, then set top of cache and MTRR.
+ // Otherwise, top of cache and MTRR will be set when UMA buffer is set up.
+ if (NBPtr->RefPtr->UmaMode == UMA_NONE) {
+ NBPtr->RefPtr->Sub4GCacheTop = (SysLimit << 16);
+ // Find unused MTRR to set C6 region to UC
+ for (CurAddr = 0x200; CurAddr < 0x20C; CurAddr += 2) {
+ LibAmdMsrRead (CurAddr + 1, (UINT64 *)&SMsr, &NBPtr->MemPtr->StdHeader);
+ if ((SMsr.lo & ((UINT32) 1 << 11)) == 0) {
+ // Set region base as TOM
+ SMsr.hi = SysLimit >> (32 - 16);
+ SMsr.lo = SysLimit << 16;
+ LibAmdMsrWrite (CurAddr, (UINT64 *)&SMsr, &NBPtr->MemPtr->StdHeader);
+
+ // set region mask to 16MB
+ SMsr.hi = NBPtr->VarMtrrHiMsk;
+ SMsr.lo = 0xFF000800;
+ LibAmdMsrWrite (CurAddr + 1, (UINT64 *)&SMsr, &NBPtr->MemPtr->StdHeader);
+
+ break;
+ }
+ }
+ }
+ } else {
+ LibAmdMsrWrite (TOP_MEM2, (UINT64 *)&SMsr, &(NBPtr->MemPtr->StdHeader));
+ IDS_HDT_CONSOLE (MEM_FLOW, "TOP_MEM2: %08x0000\n", SysLimit);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Family-specific hook to override the DdrMaxRate value for families with a
+ * non-GH-compatible encoding for BFDdrMaxRate
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *DdrMaxRate - Void pointer to DdrMaxRate. Used as INT16.
+ *
+ * @return TRUE
+ *
+ */
+BOOLEAN
+MemNGetMaxDdrRateUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN VOID *DdrMaxRate
+ )
+{
+ UINT8 DdrMaxRateEncoded;
+
+ DdrMaxRateEncoded = (UINT8) MemNGetBitFieldNb (NBPtr, BFDdrMaxRate);
+
+ if (DdrMaxRateEncoded == 0) {
+ * (UINT16 *) DdrMaxRate = UNSUPPORTED_DDR_FREQUENCY;
+ } else {
+ * (UINT16 *) DdrMaxRate = MemNGetMemClkFreqUnb (NBPtr, DdrMaxRateEncoded);
+ }
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function performs the action after save/restore execution
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ *
+ */
+
+BOOLEAN
+MemNAfterSaveRestoreUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ // Sync. up DctCfgSel value with NBPtr->Dct
+ MemNSetBitFieldNb (NBPtr, BFDctCfgSel, NBPtr->Dct);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function performs the action before and after excluding dimms on CNB
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *IsBefore - If the function is called before excluding dimms
+ *
+ * @return TRUE
+ *
+ */
+
+BOOLEAN
+MemNBfAfExcludeDimmClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *IsBefore
+ )
+{
+ if (*(BOOLEAN *) IsBefore == TRUE) {
+ NBPtr->BrdcstSet (NBPtr, BFEnterSelfRef, 1);
+ NBPtr->PollBitField (NBPtr, BFEnterSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE);
+ } else {
+ NBPtr->BrdcstSet (NBPtr, BFExitSelfRef, 1);
+ NBPtr->PollBitField (NBPtr, BFExitSelfRef, 0, PCI_ACCESS_TIMEOUT, TRUE);
+ }
+
+ return TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnphy.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnphy.c
new file mode 100644
index 0000000000..e2bc796126
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnphy.c
@@ -0,0 +1,2059 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnphy.c
+ *
+ * Common Northbridge Phy support
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mu.h"
+#include "PlatformMemoryConfiguration.h"
+#include "heapManager.h"
+#include "merrhdl.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+#define FILECODE PROC_MEM_NB_MNPHY_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define UNUSED_CLK 4
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/// Type of an entry for processing phy init compensation for client NB
+typedef struct {
+ BIT_FIELD_NAME IndexBitField; ///< Bit field on which the value is decided
+ BIT_FIELD_NAME StartTargetBitField; ///< First bit field to be modified
+ BIT_FIELD_NAME EndTargetBitField; ///< Last bit field to be modified
+ UINT16 ExtraValue; ///< Extra value needed to be written to bit field
+ CONST UINT16 (*TxPrePN)[3][5]; ///< Pointer to slew rate table
+} PHY_COMP_INIT_CLIENTNB;
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets a delay value a PCI register during training
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDly - type of delay to be set
+ * @param[in] DrbnVar - encoding of Dimm-Rank-Byte-Nibble to be accessed
+ * (use either DIMM_BYTE_ACCESS(dimm,byte) or CS_NBBL_ACCESS(cs,nibble) to use this encoding
+ *
+ * @return Value read
+ */
+
+UINT32
+MemNGetTrainDlyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar
+ )
+{
+ return NBPtr->MemNcmnGetSetTrainDly (NBPtr, 0, TrnDly, DrbnVar, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets a delay value a PCI register during training
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDly - type of delay to be set
+ * @param[in] DrbnVar - encoding of Dimm-Rank-Byte-Nibble to be accessed
+ * (use either DIMM_BYTE_ACCESS(dimm,byte) or CS_NBBL_ACCESS(cs,nibble) to use this encoding
+ * @param[in] Field - Value to be programmed
+ *
+ */
+
+VOID
+MemNSetTrainDlyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ )
+{
+ NBPtr->MemNcmnGetSetTrainDly (NBPtr, 1, TrnDly, DrbnVar, Field);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function executes prototypical Phy fence training function.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNPhyFenceTrainingNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ NBPtr->MemPPhyFenceTrainingNb (NBPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function executes prototypical Phy fence training function.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNPhyFenceTrainingUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 FenceThresholdTxDll;
+ UINT8 FenceThresholdRxDll;
+ UINT8 FenceThresholdTxPad;
+ UINT16 Fence2Data;
+
+ MemNSetBitFieldNb (NBPtr, BFDataFence2, 0);
+ MemNSetBitFieldNb (NBPtr, BFFence2, 0);
+ // 1. Program D18F2x[1,0]9C_x0000_0008[FenceTrSel]=10b.
+ // 2. Perform phy fence training.
+ // 3. Write the calculated fence value to D18F2x[1,0]9C_x0000_000C[FenceThresholdTxDll].
+ MemNSetBitFieldNb (NBPtr, BFFenceTrSel, 2);
+ MAKE_TSEFO (NBPtr->NBRegTable, DCT_PHY_ACCESS, 0x0C, 30, 26, BFPhyFence);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tFenceThresholdTxDll\n");
+ MemNTrainPhyFenceNb (NBPtr);
+ FenceThresholdTxDll = (UINT8) MemNGetBitFieldNb (NBPtr, BFPhyFence);
+ NBPtr->FamilySpecificHook[DetectMemPllError] (NBPtr, &FenceThresholdTxDll);
+
+ // 4. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]0F[AlwaysEnDllClks]=001b.
+ MemNSetBitFieldNb (NBPtr, BFAlwaysEnDllClks, 0x1000);
+
+ // 5. Program D18F2x[1,0]9C_x0000_0008[FenceTrSel]=01b.
+ // 6. Perform phy fence training.
+ // 7. Write the calculated fence value to D18F2x[1,0]9C_x0000_000C[FenceThresholdRxDll].
+ MemNSetBitFieldNb (NBPtr, BFFenceTrSel, 1);
+ MAKE_TSEFO (NBPtr->NBRegTable, DCT_PHY_ACCESS, 0x0C, 25, 21, BFPhyFence);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tFenceThresholdRxDll\n");
+ MemNTrainPhyFenceNb (NBPtr);
+ FenceThresholdRxDll = (UINT8) MemNGetBitFieldNb (NBPtr, BFPhyFence);
+ NBPtr->FamilySpecificHook[DetectMemPllError] (NBPtr, &FenceThresholdRxDll);
+
+ // 8. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]0F[AlwaysEnDllClks]=000b.
+ MemNSetBitFieldNb (NBPtr, BFAlwaysEnDllClks, 0x0000);
+
+ // 9. Program D18F2x[1,0]9C_x0000_0008[FenceTrSel]=11b.
+ // 10. Perform phy fence training.
+ // 11. Write the calculated fence value to D18F2x[1,0]9C_x0000_000C[FenceThresholdTxPad].
+ MemNSetBitFieldNb (NBPtr, BFFenceTrSel, 3);
+ MAKE_TSEFO (NBPtr->NBRegTable, DCT_PHY_ACCESS, 0x0C, 20, 16, BFPhyFence);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tFenceThresholdTxPad\n");
+ MemNTrainPhyFenceNb (NBPtr);
+ FenceThresholdTxPad = (UINT8) MemNGetBitFieldNb (NBPtr, BFPhyFence);
+ NBPtr->FamilySpecificHook[DetectMemPllError] (NBPtr, &FenceThresholdTxPad);
+
+ // Program Fence2 threshold for Clk, Cmd, and Addr
+ if (FenceThresholdTxPad < 16) {
+ MemNSetBitFieldNb (NBPtr, BFClkFence2, FenceThresholdTxPad | 0x10);
+ MemNSetBitFieldNb (NBPtr, BFCmdFence2, FenceThresholdTxPad | 0x10);
+ MemNSetBitFieldNb (NBPtr, BFAddrFence2, FenceThresholdTxPad | 0x10);
+ } else {
+ MemNSetBitFieldNb (NBPtr, BFClkFence2, 0);
+ MemNSetBitFieldNb (NBPtr, BFCmdFence2, 0);
+ MemNSetBitFieldNb (NBPtr, BFAddrFence2, 0);
+ }
+
+ // Program Fence2 threshold for data
+ Fence2Data = 0;
+ if (FenceThresholdTxPad < 16) {
+ Fence2Data |= FenceThresholdTxPad | 0x10;
+ }
+ if (FenceThresholdRxDll < 16) {
+ Fence2Data |= (FenceThresholdRxDll | 0x10) << 10;
+ }
+ if (FenceThresholdTxDll < 16) {
+ Fence2Data |= (FenceThresholdTxDll | 0x10) << 5;
+ }
+ MemNSetBitFieldNb (NBPtr, BFDataFence2, Fence2Data);
+ NBPtr->FamilySpecificHook[ProgramFence2RxDll] (NBPtr, &Fence2Data);
+
+ if (NBPtr->MCTPtr->Status[SbLrdimms]) {
+ // 18. If motherboard routing requires CS[7:6] to adopt address timings, e.g. 3 LRDIMMs/ch with CS[7:6]
+ // routed across all DIMM sockets, BIOS performs the following:
+ if (FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_NO_LRDIMM_CS67_ROUTING, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID, 0, NULL, NULL) != NULL) {
+ // A. Program D18F2xA8_dct[1:0][CSTimingMux67] = 1.
+ MemNSetBitFieldNb (NBPtr, BFCSTimingMux67, 1);
+ // B. Program D18F2x9C_x0D0F_8021_dct[1:0]:
+ // - DiffTimingEn = 1.
+ // - IF (D18F2x9C_x0000_0004_dct[1:0][AddrCmdFineDelay] >=
+ // D18F2x9C_x0D0F_E008_dct[1:0][FenceValue]) THEN Fence = 1 ELSE Fence = 0.
+ // - Delay = D18F2x9C_x0000_0004_dct[1:0][AddrCmdFineDelay].
+ //
+ MemNSetBitFieldNb (NBPtr, BFDiffTimingEn, 1);
+ MemNSetBitFieldNb (NBPtr, BFFence, (MemNGetBitFieldNb (NBPtr, BFAddrCmdFineDelay) >= MemNGetBitFieldNb (NBPtr, BFFenceValue)) ? 1 : 0);
+ MemNSetBitFieldNb (NBPtr, BFDelay, (MemNGetBitFieldNb (NBPtr, BFAddrCmdFineDelay)));
+ }
+ }
+
+ // 19. Reprogram F2x9C_04.
+ MemNSetBitFieldNb (NBPtr, BFAddrTmgControl, MemNGetBitFieldNb (NBPtr, BFAddrTmgControl));
+
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function executes Phy fence training
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNTrainPhyFenceNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Byte;
+ INT16 Avg;
+ UINT8 PREvalue;
+
+ if (MemNGetBitFieldNb (NBPtr, BFDisDramInterface)) {
+ return;
+ }
+
+ // 1. BIOS first programs a seed value to the phase recovery
+ // engine registers.
+ //
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tSeeds: ");
+ for (Byte = 0; Byte < MAX_BYTELANES_PER_CHANNEL; Byte++) {
+ // This includes ECC as byte 8
+ MemNSetTrainDlyNb (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (0, Byte), 19);
+ IDS_HDT_CONSOLE (MEM_FLOW, "%02x ", 19);
+ }
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tPhyFenceTrEn = 1");
+ // 2. Set F2x[1, 0]9C_x08[PhyFenceTrEn]=1.
+ MemNSetBitFieldNb (NBPtr, BFPhyFenceTrEn, 1);
+
+ if (!NBPtr->IsSupported[UnifiedNbFence]) {
+ // 3. Wait 200 MEMCLKs.
+ MemNWaitXMemClksNb (NBPtr, 200);
+ } else {
+ // 3. Wait 2000 MEMCLKs.
+ MemNWaitXMemClksNb (NBPtr, 2000);
+ }
+
+ // 4. Clear F2x[1, 0]9C_x08[PhyFenceTrEn]=0.
+ MemNSetBitFieldNb (NBPtr, BFPhyFenceTrEn, 0);
+
+ // 5. BIOS reads the phase recovery engine registers
+ // F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52.
+ // 6. Calculate the average value of the fine delay and subtract 8.
+ //
+ Avg = 0;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t PRE: ");
+ for (Byte = 0; Byte < MAX_BYTELANES_PER_CHANNEL; Byte++) {
+ //
+ // This includes ECC as byte 8. ECC Byte lane (8) is ignored by MemNGetTrainDlyNb function where
+ // ECC is not supported.
+ //
+ PREvalue = (UINT8) (0x1F & MemNGetTrainDlyNb (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (0, Byte)));
+ Avg = Avg + ((INT16) PREvalue);
+ IDS_HDT_CONSOLE (MEM_FLOW, "%02x ", PREvalue);
+ }
+ Avg = ((Avg + 8) / 9); // round up
+
+ Avg -= 8;
+ NBPtr->MemNPFenceAdjustNb (NBPtr, &Avg);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tFence: %02x\n", Avg);
+
+ // 7. Write the value to F2x[1, 0]9C_x0C[PhyFence].
+ MemNSetBitFieldNb (NBPtr, BFPhyFence, Avg);
+
+ // 8. BIOS rewrites F2x[1, 0]9C_x04, DRAM Address/Command Timing Control
+ // Register delays for both channels. This forces the phy to recompute
+ // the fence.
+ //
+ MemNSetBitFieldNb (NBPtr, BFAddrTmgControl, MemNGetBitFieldNb (NBPtr, BFAddrTmgControl));
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the DDR phy compensation logic
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNInitPhyCompNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST UINT8 TableCompRiseSlew20x[] = {7, 3, 2, 2};
+ CONST UINT8 TableCompRiseSlew15x[] = {7, 7, 3, 2};
+ CONST UINT8 TableCompFallSlew20x[] = {7, 5, 3, 2};
+ CONST UINT8 TableCompFallSlew15x[] = {7, 7, 5, 3};
+ UINT8 i;
+ UINT8 j;
+ UINT8 CurrDct;
+ UINT8 CurrChannel;
+ BOOLEAN MarginImprv;
+ MarginImprv = FALSE;
+ CurrDct = NBPtr->Dct;
+ CurrChannel = NBPtr->Channel;
+ if (NBPtr->IsSupported[CheckSlewWithMarginImprv]) {
+ if (NBPtr->MCTPtr->GangedMode == FALSE) {
+ for (i = 0; i < NBPtr->DctCount; i++) {
+ MemNSwitchDCTNb (NBPtr, i);
+ for (j = 0; j < NBPtr->ChannelCount; j++) {
+ NBPtr->SwitchChannel (NBPtr, j);
+ if ((NBPtr->ChannelPtr->Dimms == 4) && ((NBPtr->DCTPtr->Timings.Speed == DDR533_FREQUENCY) || (NBPtr->DCTPtr->Timings.Speed == DDR667_FREQUENCY))) {
+ MarginImprv = TRUE;
+ }
+ }
+ }
+ MemNSwitchDCTNb (NBPtr, CurrDct);
+ NBPtr->SwitchChannel (NBPtr, CurrChannel);
+ }
+ }
+
+ // 1. BIOS disables the phy compensation register by programming F2x9C_x08[DisAutoComp]=1
+ // 2. BIOS waits 5 us for the disabling of the compensation engine to complete.
+ // DisAutoComp will be cleared after Dram init has completed
+ //
+ MemNSwitchDCTNb (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 1);
+ MemUWait10ns (500, NBPtr->MemPtr);
+ MemNSwitchDCTNb (NBPtr, CurrDct);
+
+ // 3. For each normalized driver strength code read from
+ // F2x[1, 0]9C_x00[AddrCmdDrvStren], program the
+ // corresponding 3 bit predriver code in F2x9C_x0A[D3Cmp1NCal, D3Cmp1PCal].
+ //
+ // 4. For each normalized driver strength code read from
+ // F2x[1, 0]9C_x00[DataDrvStren], program the corresponding
+ // 3 bit predriver code in F2x9C_x0A[D3Cmp0NCal, D3Cmp0PCal, D3Cmp2NCal,
+ // D3Cmp2PCal].
+ //
+ j = (UINT8) MemNGetBitFieldNb (NBPtr, BFAddrCmdDrvStren);
+ i = (UINT8) MemNGetBitFieldNb (NBPtr, BFDataDrvStren);
+
+ MemNSwitchDCTNb (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp1NCal, TableCompRiseSlew20x[j]);
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp1PCal, TableCompFallSlew20x[j]);
+
+ if (NBPtr->IsSupported[CheckSlewWithMarginImprv]) {
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp0NCal, (MarginImprv) ? 0 : TableCompRiseSlew15x[i]);
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp0PCal, (MarginImprv) ? 0 : TableCompFallSlew15x[i]);
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp2NCal, (MarginImprv) ? 0 : TableCompRiseSlew15x[i]);
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp2PCal, (MarginImprv) ? 0 : TableCompFallSlew15x[i]);
+ }
+ if (NBPtr->IsSupported[CheckSlewWithoutMarginImprv]) {
+ ASSERT (i <= 3);
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp0NCal, TableCompRiseSlew15x[i]);
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp0PCal, TableCompFallSlew15x[i]);
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp2NCal, TableCompRiseSlew15x[i]);
+ MemNSetBitFieldNb (NBPtr, BFD3Cmp2PCal, TableCompFallSlew15x[i]);
+ }
+ MemNSwitchDCTNb (NBPtr, CurrDct);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This is a general purpose function that executes before DRAM training
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNBeforeDQSTrainingNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dct;
+ UINT8 ChipSel;
+ UINT32 TestAddrRJ16;
+ UINT32 RealAddr;
+
+ MemTBeginTraining (NBPtr->TechPtr);
+
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize != 0) {
+ for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel += 2) {
+ if (MemNGetMCTSysAddrNb (NBPtr, ChipSel, &TestAddrRJ16)) {
+
+ RealAddr = MemUSetUpperFSbase (TestAddrRJ16, NBPtr->MemPtr);
+
+ MemUDummyCLRead (RealAddr);
+
+ MemNSetBitFieldNb (NBPtr, BFErr350, 0x8000);
+ MemUWait10ns (60, NBPtr->MemPtr); // Wait 300ns
+ MemNSetBitFieldNb (NBPtr, BFErr350, 0x0000);
+ MemUWait10ns (400, NBPtr->MemPtr); // Wait 2us
+ MemUProcIOClFlush (TestAddrRJ16, 1, NBPtr->MemPtr);
+ break;
+ }
+ }
+ }
+ if (NBPtr->IsSupported[CheckEccDLLPwrDnConfig]) {
+ if (!NBPtr->MCTPtr->Status[SbEccDimms]) {
+ MemNSetBitFieldNb (NBPtr, BFEccDLLPwrDnConf, 0x0010);
+ }
+ if (NBPtr->DCTPtr->Timings.Dimmx4Present == 0) {
+ MemNSetBitFieldNb (NBPtr, BFEccDLLConf, 0x0080);
+ }
+ }
+ }
+
+ MemTEndTraining (NBPtr->TechPtr);
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * Returns the parameters for a requested delay value to be used in training
+ * The correct Min, Max and Mask are determined based on the type of Delay,
+ * and the frequency
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDly - Type of delay
+ * @param[in,out] *Parms - Pointer to the TRN_DLY-PARMS struct
+ *
+ */
+
+VOID
+MemNGetTrainDlyParmsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDly,
+ IN OUT TRN_DLY_PARMS *Parms
+ )
+{
+ Parms->Min = 0;
+
+ if (TrnDly == AccessWrDatDly) {
+ Parms->Max = 0x1F;
+ Parms->Mask = 0x01F;
+ } else if (TrnDly == AccessRdDqsDly) {
+ if ( (NBPtr->IsSupported[CheckMaxRdDqsDlyPtr]) && (NBPtr->DCTPtr->Timings.Speed > DDR667_FREQUENCY) ) {
+ Parms->Max = 0x3E;
+ Parms->Mask = 0x03E;
+ } else {
+ Parms->Max = 0x1F;
+ Parms->Mask = 0x01F;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * Returns the parameters for a requested delay value to be used in training
+ * The correct Min, Max and Mask are determined based on the type of Delay,
+ * and the frequency
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDly - Type of delay
+ * @param[in,out] *Parms - Pointer to the TRN_DLY-PARMS struct
+ *
+ */
+
+VOID
+MemNGetTrainDlyParmsClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDly,
+ IN OUT TRN_DLY_PARMS *Parms
+ )
+{
+ Parms->Min = 0;
+
+ if (TrnDly == AccessWrDatDly) {
+ Parms->Max = 0x1F;
+ Parms->Mask = 0x01F;
+ } else if (TrnDly == AccessRdDqsDly) {
+ Parms->Max = 0x3E;
+ Parms->Mask = 0x03E;
+ }
+}
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * Returns the parameters for a requested delay value to be used in training
+ * The correct Min, Max and Mask are determined based on the type of Delay,
+ * and the frequency
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDly - Type of delay
+ * @param[in,out] *Parms - Pointer to the TRN_DLY-PARMS struct
+ *
+ */
+
+VOID
+MemNGetTrainDlyParmsUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDly,
+ IN OUT TRN_DLY_PARMS *Parms
+ )
+{
+ Parms->Min = 0;
+
+ if ((TrnDly == AccessWrDatDly) || (TrnDly == AccessRdDqsDly)) {
+ Parms->Max = 0x1F;
+ Parms->Mask = 0x01F;
+ }
+}
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets or set DQS timing during training.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDly - type of delay to be set
+ * @param[in] DrbnVar - encoding of Dimm-Rank-Byte-Nibble to be accessed
+ * (use either DIMM_BYTE_ACCESS(dimm,byte) or CS_NBBL_ACCESS(cs,nibble) to use this encoding
+ * @param[in] Field - Value to be programmed
+ * @param[in] IsSet - Indicates if the function will set or get
+ *
+ * @return value read, if the function is used as a "get"
+ */
+
+UINT32
+MemNcmnGetSetTrainDlyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ )
+{
+ UINT16 Index;
+ UINT16 Offset;
+ UINT32 Value;
+ UINT32 Address;
+ UINT8 Dimm;
+ UINT8 Rank;
+ UINT8 Byte;
+ UINT8 Nibble;
+
+ Dimm = DRBN_DIMM (DrbnVar);
+ Rank = DRBN_RANK (DrbnVar);
+ Byte = DRBN_BYTE (DrbnVar);
+ Nibble = DRBN_NBBL (DrbnVar);
+
+ ASSERT (Dimm < 4);
+ ASSERT (Byte <= ECC_DLY);
+
+ switch (TrnDly) {
+ case AccessRcvEnDly:
+ Index = 0x10;
+ break;
+ case AccessWrDqsDly:
+ Index = 0x30;
+ break;
+ case AccessWrDatDly:
+ Index = 0x01;
+ break;
+ case AccessRdDqsDly:
+ Index = 0x05;
+ break;
+ case AccessPhRecDly:
+ Index = 0x50;
+ break;
+ default:
+ Index = 0;
+ IDS_ERROR_TRAP;
+ }
+
+ switch (TrnDly) {
+ case AccessRcvEnDly:
+ case AccessWrDqsDly:
+ Index += (Dimm * 3);
+ if (Byte & 0x04) {
+ // if byte 4,5,6,7
+ Index += 0x10;
+ }
+ if (Byte & 0x02) {
+ // if byte 2,3,6,7
+ Index++;
+ }
+ if (Byte > 7) {
+ Index += 2;
+ }
+ Offset = 16 * (Byte % 2);
+ Index |= (Rank << 8);
+ Index |= (Nibble << 9);
+ break;
+
+ case AccessRdDqsDly:
+ case AccessWrDatDly:
+
+ if (NBPtr->IsSupported[DimmBasedOnSpeed]) {
+ if (NBPtr->DCTPtr->Timings.Speed < DDR800_FREQUENCY) {
+ // if DDR speed is below 800, use DIMM 0 delays for all DIMMs.
+ Dimm = 0;
+ }
+ }
+
+ Index += (Dimm * 0x100);
+ if (Nibble) {
+ if (Rank) {
+ Index += 0xA0;
+ } else {
+ Index += 0x70;
+ }
+ } else if (Rank) {
+ Index += 0x60;
+ }
+ // break is not being used here because AccessRdDqsDly and AccessWrDatDly also need
+ // to run AccessPhRecDly sequence.
+ case AccessPhRecDly:
+ Index += (Byte / 4);
+ Offset = 8 * (Byte % 4);
+ break;
+ default:
+ Offset = 0;
+ IDS_ERROR_TRAP;
+ }
+
+ Address = Index;
+ MemNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ MemNPollBitFieldNb (NBPtr, BFDctAccessDone, 1, PCI_ACCESS_TIMEOUT, FALSE);
+ Value = MemNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (TrnDly == AccessRdDqsDly) {
+ NBPtr->FamilySpecificHook[AdjustRdDqsDlyOffset] (NBPtr, &Offset);
+ }
+
+ if (IsSet) {
+ if (TrnDly == AccessPhRecDly) {
+ Value = NBPtr->DctCachePtr->PhRecReg[Index & 0x03];
+ }
+
+ Value = ((UINT32)Field << Offset) | (Value & (~((UINT32) ((TrnDly == AccessRcvEnDly) ? 0x1FF : 0xFF) << Offset)));
+ MemNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+ MemNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ MemNPollBitFieldNb (NBPtr, BFDctAccessDone, 1, PCI_ACCESS_TIMEOUT, FALSE);
+
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[Index & 0x03] = Value;
+ }
+ } else {
+ Value = (Value >> Offset) & (UINT32) ((TrnDly == AccessRcvEnDly) ? 0x1FF : 0xFF);
+ }
+
+ return Value;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function gets or set DQS timing during training.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] IsSet - Indicates if the function will set or get
+ * @param[in] TrnDly - type of delay to be set
+ * @param[in] DrbnVar - encoding of Dimm-Rank-Byte-Nibble to be accessed
+ * (use either DIMM_BYTE_ACCESS(dimm,byte) or CS_NBBL_ACCESS(cs,nibble) to use this encoding
+ * @param[in] Field - Value to be programmed
+ *
+ * @return value read, if the function is used as a "get"
+ */
+UINT32
+MemNcmnGetSetTrainDlyClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ )
+{
+ UINT16 Index;
+ UINT16 Offset;
+ UINT32 Value;
+ UINT32 Address;
+ UINT8 Dimm;
+ UINT8 Byte;
+
+ Dimm = DRBN_DIMM (DrbnVar);
+ Byte = DRBN_BYTE (DrbnVar);
+
+ ASSERT (Dimm < 2);
+ ASSERT (Byte <= ECC_DLY);
+
+ if ((Byte > 7)) {
+ // Llano does not support ECC delay, so:
+ if (IsSet) {
+ // On write, ignore
+ return 0;
+ } else {
+ // On read, redirect to byte 0 to correct fence averaging
+ Byte = 0;
+ }
+ }
+
+ switch (TrnDly) {
+ case AccessRcvEnDly:
+ Index = 0x10;
+ break;
+ case AccessWrDqsDly:
+ Index = 0x30;
+ break;
+ case AccessWrDatDly:
+ Index = 0x01;
+ break;
+ case AccessRdDqsDly:
+ Index = 0x05;
+ break;
+ case AccessPhRecDly:
+ Index = 0x50;
+ break;
+ default:
+ Index = 0;
+ IDS_ERROR_TRAP;
+ }
+
+ switch (TrnDly) {
+ case AccessRcvEnDly:
+ case AccessWrDqsDly:
+ Index += (Dimm * 3);
+ if (Byte & 0x04) {
+ // if byte 4,5,6,7
+ Index += 0x10;
+ }
+ if (Byte & 0x02) {
+ // if byte 2,3,6,7
+ Index++;
+ }
+ Offset = 16 * (Byte % 2);
+ break;
+
+ case AccessRdDqsDly:
+ case AccessWrDatDly:
+ Index += (Dimm * 0x100);
+ // break is not being used here because AccessRdDqsDly and AccessWrDatDly also need
+ // to run AccessPhRecDly sequence.
+ case AccessPhRecDly:
+ Index += (Byte / 4);
+ Offset = 8 * (Byte % 4);
+ break;
+ default:
+ Offset = 0;
+ IDS_ERROR_TRAP;
+ }
+
+ Address = Index;
+ MemNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ Value = MemNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (IsSet) {
+ if (TrnDly == AccessPhRecDly) {
+ Value = NBPtr->DctCachePtr->PhRecReg[Index & 0x03];
+ }
+
+ Value = ((UINT32)Field << Offset) | (Value & (~((UINT32) ((TrnDly == AccessRcvEnDly) ? 0x1FF : 0xFF) << Offset)));
+ MemNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+ MemNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[Index & 0x03] = Value;
+ }
+ // Gross WrDatDly and WrDqsDly cannot be larger than 4
+ ASSERT (((TrnDly == AccessWrDatDly) || (TrnDly == AccessWrDqsDly)) ? (NBPtr->IsSupported[WLNegativeDelay] || (Field < 0xA0)) : TRUE);
+ } else {
+ Value = (Value >> Offset) & (UINT32) ((TrnDly == AccessRcvEnDly) ? 0x1FF : 0xFF);
+ }
+
+ return Value;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets or set DQS timing during training.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] TrnDly - type of delay to be set
+ * @param[in] DrbnVar - encoding of Dimm-Rank-Byte-Nibble to be accessed
+ * (use either DIMM_BYTE_ACCESS(dimm,byte) or CS_NBBL_ACCESS(cs,nibble) to use this encoding
+ * @param[in] Field - Value to be programmed
+ * @param[in] IsSet - Indicates if the function will set or get
+ *
+ * @return value read, if the function is used as a "get"
+ */
+
+UINT32
+MemNcmnGetSetTrainDlyUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ )
+{
+ UINT16 Index;
+ UINT16 Offset;
+ UINT32 Value;
+ UINT32 Address;
+ UINT8 Dimm;
+ UINT8 Rank;
+ UINT8 Byte;
+ UINT8 Nibble;
+ UINT8 DimmNibble;
+
+ Dimm = DRBN_DIMM (DrbnVar);
+ Rank = DRBN_RANK (DrbnVar);
+ Byte = DRBN_BYTE (DrbnVar);
+ Nibble = DRBN_NBBL (DrbnVar);
+ DimmNibble = DRBN_DIMM_NBBL (DrbnVar);
+
+ ASSERT (Dimm < (NBPtr->CsPerChannel / NBPtr->CsPerDelay));
+ ASSERT (Byte <= ECC_DLY);
+ if ((Byte == ECC_DLY) && (!NBPtr->MCTPtr->Status[SbEccDimms] || !NBPtr->IsSupported[EccByteTraining])) {
+ // When ECC is not enabled
+ if (IsSet) {
+ // On write, ignore
+ return 0;
+ } else {
+ // On read, redirect to byte 0 to correct fence averaging
+ Byte = 0;
+ }
+ }
+
+ switch (TrnDly) {
+ case AccessRcvEnDly:
+ Index = 0x10;
+ break;
+ case AccessWrDqsDly:
+ Index = 0x30;
+ break;
+ case AccessWrDatDly:
+ Index = 0x01;
+ break;
+ case AccessRdDqsDly:
+ Index = 0x05;
+ break;
+ case excel845 :
+ Index = 0x00;
+ break;
+ case AccessPhRecDly:
+ Index = 0x50;
+ break;
+ default:
+ Index = 0;
+ IDS_ERROR_TRAP;
+ }
+
+ switch (TrnDly) {
+ case AccessRcvEnDly:
+ case AccessWrDqsDly:
+ Index += (Dimm * 3);
+ if (Byte & 0x04) {
+ // if byte 4,5,6,7
+ Index += 0x10;
+ }
+ if (Byte & 0x02) {
+ // if byte 2,3,6,7
+ Index++;
+ }
+ if (Byte > 7) {
+ Index += 2;
+ }
+ Offset = 16 * (Byte % 2);
+ Index |= (Rank << 8);
+ Index |= (Nibble << 9);
+ Address = Index;
+ break;
+
+ case AccessRdDqsDly:
+ case AccessWrDatDly:
+
+ if (NBPtr->IsSupported[DimmBasedOnSpeed]) {
+ if (NBPtr->DCTPtr->Timings.Speed < DDR800_FREQUENCY) {
+ // if DDR speed is below 800, use DIMM 0 delays for all DIMMs.
+ Dimm = 0;
+ }
+ }
+
+ Index += (Dimm * 0x100);
+ if (Nibble) {
+ if (Rank) {
+ Index += 0xA0;
+ } else {
+ Index += 0x70;
+ }
+ } else if (Rank) {
+ Index += 0x60;
+ }
+ // break is not being used here because AccessRdDqsDly and AccessWrDatDly also need
+ // to run AccessPhRecDly sequence.
+ case AccessPhRecDly:
+ Index += (Byte / 4);
+ Offset = 8 * (Byte % 4);
+ Address = Index;
+ break;
+ case excel845 :
+ Address = 0x0D0F0000;
+ Index += (DimmNibble >> 1) * 0x100;
+ Index += 0x20;
+ Index = Index + Dimm;
+ Offset = 4 * ((DimmNibble & 0x01) * 2);
+ Address += Index;
+ break;
+ default:
+ Offset = 0;
+ IDS_ERROR_TRAP;
+ Address = Index;
+ }
+ MemNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ MemNPollBitFieldNb (NBPtr, BFDctAccessDone, 1, PCI_ACCESS_TIMEOUT, FALSE);
+ Value = MemNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+ if (TrnDly == AccessRdDqsDly) {
+ NBPtr->FamilySpecificHook[AdjustRdDqsDlyOffset] (NBPtr, &Offset);
+ }
+
+ if (IsSet) {
+ if (TrnDly == AccessPhRecDly) {
+ Value = NBPtr->DctCachePtr->PhRecReg[Index & 0x03];
+ }
+ if (TrnDly != excel845 ) {
+ Value = ((UINT32)Field << Offset) | (Value & (~((UINT32) ((TrnDly == AccessRcvEnDly) ? 0x3FF : 0xFF) << Offset)));
+ } else {
+ Value = ((UINT32)Field << Offset) | (Value & (~((UINT32) 0x1F << Offset)));
+ }
+ MemNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+ MemNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ MemNPollBitFieldNb (NBPtr, BFDctAccessDone, 1, PCI_ACCESS_TIMEOUT, FALSE);
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[Index & 0x03] = Value;
+ }
+ } else {
+ if (TrnDly != excel845 ) {
+ Value = (Value >> Offset) & (UINT32) ((TrnDly == AccessRcvEnDly) ? 0x3FF : 0xFF);
+ } else {
+ Value = (Value >> Offset) & (UINT32) (0x1F);
+ }
+ }
+ return Value;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes the training pattern.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return AGESA_STATUS - Result
+ * AGESA_SUCCESS - Training pattern is ready to use
+ * AGESA_ERROR - Unable to initialize the pattern.
+ */
+
+AGESA_STATUS
+MemNTrainingPatternInitNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+ TRAIN_PATTERN TrainPattern;
+ AGESA_STATUS Status;
+
+ TechPtr = NBPtr->TechPtr;
+ TrainPattern = 0;
+ //
+ // Check the training type
+ //
+ if (TechPtr->TrainingType == TRN_DQS_POSITION) {
+ //
+ // DQS Position Training
+ //
+ if (NBPtr->PosTrnPattern == POS_PATTERN_256B) {
+ //
+ // 256 Bit pattern
+ //
+ if (NBPtr->MCTPtr->Status[Sb128bitmode]) {
+ TrainPattern = TestPatternJD256B;
+ TechPtr->PatternLength = 64;
+ } else {
+ TrainPattern = TestPatternJD256A;
+ TechPtr->PatternLength = 32;
+ }
+ } else {
+ //
+ // 72 bit pattern will be used if PosTrnPattern is not specified
+ //
+ if (NBPtr->MCTPtr->Status[Sb128bitmode]) {
+ TrainPattern = TestPatternJD1B;
+ TechPtr->PatternLength = 18;
+ } else {
+ TrainPattern = TestPatternJD1A;
+ TechPtr->PatternLength = 9;
+ }
+ }
+ } else if (TechPtr->TrainingType == TRN_MAX_READ_LATENCY) {
+ //
+ // Max Read Latency Training
+ //
+ TrainPattern = TestPatternML;
+ TechPtr->PatternLength = (NBPtr->MCTPtr->Status[Sb128bitmode]) ? 6 : 3;
+ } else {
+ //
+ // Error - TechPtr->Training Type must be set to one of the types handled in this function
+ //
+ ASSERT (FALSE);
+ }
+ //
+ // Allocate training buffer
+ //
+ AllocHeapParams.RequestedBufferSize = (TechPtr->PatternLength * 64 * 2) + 16;
+ AllocHeapParams.BufferHandle = AMD_MEM_TRAIN_BUFFER_HANDLE;
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ Status = HeapAllocateBuffer (&AllocHeapParams, &NBPtr->MemPtr->StdHeader);
+ ASSERT (Status == AGESA_SUCCESS);
+ if (Status != AGESA_SUCCESS) {
+ return Status;
+ }
+ TechPtr->PatternBufPtr = AllocHeapParams.BufferPtr;
+ AlignPointerTo16Byte (&TechPtr->PatternBufPtr);
+ TechPtr->TestBufPtr = TechPtr->PatternBufPtr + (TechPtr->PatternLength * 64);
+
+ // Prepare training pattern
+ MemUFillTrainPattern (TrainPattern, TechPtr->PatternBufPtr, TechPtr->PatternLength * 64);
+
+ return Status;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function determined the settings for the Reliable Read/Write engine
+ * for each specific type of training
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *OptParam - Pointer to an Enum of TRAINING_TYPE
+ *
+ * @return TRUE
+ */
+
+BOOLEAN
+MemNSetupHwTrainingEngineUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN VOID *OptParam
+ )
+{
+ TRAINING_TYPE TrnType;
+ RRW_SETTINGS *Rrw;
+
+ TrnType = *(TRAINING_TYPE*) OptParam;
+ Rrw = &NBPtr->RrwSettings;
+ //
+ // Common Settings
+ //
+ Rrw->TgtBankAddressA = CPG_BANK_ADDRESS_A;
+ Rrw->TgtRowAddressA = CPG_ROW_ADDRESS_A;
+ Rrw->TgtColAddressA = CPG_COL_ADDRESS_A;
+ Rrw->TgtBankAddressB = CPG_BANK_ADDRESS_B;
+ Rrw->TgtRowAddressB = CPG_ROW_ADDRESS_B;
+ Rrw->TgtColAddressB = CPG_COL_ADDRESS_B;
+ Rrw->CompareMaskHigh = CPG_COMPARE_MASK_HI;
+ Rrw->CompareMaskLow = CPG_COMPARE_MASK_LOW;
+ Rrw->CompareMaskEcc = CPG_COMPARE_MASK_ECC;
+
+ switch (TrnType) {
+ case TRN_RCVR_ENABLE:
+ //
+ // Receiver Enable Training
+ //
+ NBPtr->TechPtr->PatternLength = 192;
+ break;
+ case TRN_MAX_READ_LATENCY:
+ //
+ // Max Read Latency Training
+ //
+ Rrw->CmdTgt = CMD_TGT_A;
+ NBPtr->TechPtr->PatternLength = 32;
+ Rrw->DataPrbsSeed = PRBS_SEED_32;
+ break;
+ case TRN_DQS_POSITION:
+ //
+ // Read/Write DQS Position training
+ //
+ Rrw->CmdTgt = CMD_TGT_AB;
+ NBPtr->TechPtr->PatternLength = 256;
+ Rrw->DataPrbsSeed = PRBS_SEED_256;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function finalizes the training pattern.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Index - Index of Write Data Delay Value
+ * @param[in,out] *Value - Write Data Delay Value
+ * @return BOOLEAN - TRUE - Use the value returned.
+ * FALSE - No more values in table.
+ */
+
+BOOLEAN
+MemNGetApproximateWriteDatDelayNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Index,
+ IN OUT UINT8 *Value
+ )
+{
+ CONST UINT8 WriteDatDelayValue[] = {0x10, 0x4, 0x8, 0xC, 0x14, 0x18, 0x1C, 0x1F};
+ if (Index < GET_SIZE_OF (WriteDatDelayValue)) {
+ *Value = WriteDatDelayValue[Index];
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function finalizes the training pattern.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return AGESA_STATUS - Result
+ * AGESA_SUCCESS - Training pattern has been finalized.
+ * AGESA_ERROR - Unable to initialize the pattern.
+ */
+
+AGESA_STATUS
+MemNTrainingPatternFinalizeNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ AGESA_STATUS Status;
+ //
+ // Deallocate training buffer
+ //
+ Status = HeapDeallocateBuffer (AMD_MEM_TRAIN_BUFFER_HANDLE, &NBPtr->MemPtr->StdHeader);
+ ASSERT (Status == AGESA_SUCCESS);
+ return Status;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function returns the number of Chipselects controlled by each set
+ * of Delay registers under current conditions.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return
+ */
+
+UINT8
+MemNCSPerDelayNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ if (MemNGetBitFieldNb (NBPtr, BFPerRankTimingEn) == 1) {
+ return 1;
+ } else {
+ return 2;
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function returns the minimum data eye width in 32nds of a UI for
+ * the type of data eye(Rd/Wr) that is being trained. This value will
+ * be the minimum number of consecutive delays that yield valid data.
+ * Uses TechPtr->Direction to determine read or write.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return
+ */
+
+UINT8
+MemNMinDataEyeWidthNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 MinRdDataeye;
+ UINT8 MinWrDataeye;
+ UINT8 *MinRdWrDataeyePtr;
+
+ MinRdWrDataeyePtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MIN_RD_WR_DATAEYE_WIDTH, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID, 0,
+ &(NBPtr->MCTPtr->LogicalCpuid), &(NBPtr->MemPtr->StdHeader));
+
+ if (NBPtr->TechPtr->Direction == DQS_READ_DIR) {
+ if (MinRdWrDataeyePtr != NULL) {
+ MinRdDataeye = MinRdWrDataeyePtr[0];
+ return MinRdDataeye;
+ } else {
+ return MIN_RD_DATAEYE_WIDTH_NB;
+ }
+ } else {
+ if (MinRdWrDataeyePtr != NULL) {
+ MinWrDataeye = MinRdWrDataeyePtr[1];
+ return MinWrDataeye;
+ } else {
+ return MIN_WR_DATAEYE_WIDTH_NB;
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function programs the phy registers according to the desired phy VDDIO voltage level
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNPhyVoltageLevelNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ BIT_FIELD_NAME BitField;
+ BIT_FIELD_NAME BFEnd;
+ UINT16 BFValue;
+ UINT16 RegValue;
+
+ BFValue = (UINT16) CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage) << 3;
+ BFEnd = NBPtr->IsSupported[ProgramCsrComparator] ? BFCsrComparator : BFCmpVioLvl;
+
+ for (BitField = BFDataRxVioLvl; BitField <= BFEnd; BitField++) {
+ RegValue = BFValue;
+ if (BitField == BFCsrComparator) {
+ RegValue >>= (3 - 2);
+ // Setting this bit in DCT0 adjusts the comparator for DCT0 and DCT1. Setting this bit in DCT1 has no effect.
+ NBPtr->SwitchDCT (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BitField, RegValue);
+ break;
+ } else if (BitField == BFCmpVioLvl) {
+ RegValue <<= (14 - 3);
+ // Must set this bit on DCT0 even when DCT0 has no memory
+ NBPtr->SwitchDCT (NBPtr, 0);
+ MemNSetBitFieldNb (NBPtr, BitField, RegValue);
+ }
+ MemNBrdcstSetNb (NBPtr, BitField, RegValue);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function adjusts Avg PRE value of Phy fence training according to specific CPU family.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *Value16 - Pointer to the value that we want to adjust
+ *
+ */
+VOID
+MemNPFenceAdjustUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT INT16 *Value16
+ )
+{
+ *Value16 += 2; //The Avg PRE value is subtracted by 6 only.
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes the DDR phy compensation logic
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemNInitPhyCompClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ // Slew rate table array [x][y][z]
+ // array[0]: slew rate for VDDIO 1.5V
+ // array[1]: slew rate for VDDIO 1.35V
+ // array[2]: slew rate for VDDIO 1.25V
+ // array[x][y]: slew rate for a certain frequency
+ // array[x][y][0]: frequency mask for current entry
+ CONST STATIC UINT16 TxPrePNDataDqs[3][3][5] = {
+ {{ (UINT16) DDR800, 0x924, 0x924, 0x924, 0x924},
+ { (UINT16) (DDR1066 + DDR1333), 0xFF6, 0xFF6, 0xFF6, 0xFF6},
+ { (UINT16) (DDR1600 + DDR1866), 0xFF6, 0xFF6, 0xFF6, 0xFF6}},
+ {{ (UINT16) DDR800, 0xFF6, 0xB6D, 0xB6D, 0x924},
+ { (UINT16) (DDR1066 + DDR1333), 0xFF6, 0xFF6, 0xFF6, 0xFF6},
+ { (UINT16) (DDR1600 + DDR1866), 0xFF6, 0xFF6, 0xFF6, 0xFF6}},
+ {{ (UINT16) DDR800, 0xFF6, 0xDAD, 0xDAD, 0x924},
+ { (UINT16) (DDR1066 + DDR1333), 0xFF6, 0xFF6, 0xFF6, 0xFF6},
+ { (UINT16) (DDR1600 + DDR1866), 0xFF6, 0xFF6, 0xFF6, 0xFF6}}
+ };
+ CONST STATIC UINT16 TxPrePNCmdAddr[3][3][5] = {
+ {{ (UINT16) DDR800, 0x492, 0x492, 0x492, 0x492},
+ { (UINT16) (DDR1066 + DDR1333), 0x6DB, 0x6DB, 0x6DB, 0x6DB},
+ { (UINT16) (DDR1600 + DDR1866), 0xB6D, 0xB6D, 0xB6D, 0xB6D}},
+ {{ (UINT16) DDR800, 0x492, 0x492, 0x492, 0x492},
+ { (UINT16) (DDR1066 + DDR1333), 0x924, 0x6DB, 0x6DB, 0x6DB},
+ { (UINT16) (DDR1600 + DDR1866), 0xB6D, 0xB6D, 0x924, 0x924}},
+ {{ (UINT16) DDR800, 0x492, 0x492, 0x492, 0x492},
+ { (UINT16) (DDR1066 + DDR1333), 0xDAD, 0x924, 0x6DB, 0x492},
+ { (UINT16) (DDR1600 + DDR1866), 0xFF6, 0xDAD, 0xB64, 0xB64}}
+ };
+ CONST STATIC UINT16 TxPrePNClock[3][3][5] = {
+ {{ (UINT16) DDR800, 0x924, 0x924, 0x924, 0x924},
+ { (UINT16) (DDR1066 + DDR1333), 0xFF6, 0xFF6, 0xFF6, 0xB6D},
+ { (UINT16) (DDR1600 + DDR1866), 0xFF6, 0xFF6, 0xFF6, 0xFF6}},
+ {{ (UINT16) DDR800, 0xDAD, 0xDAD, 0x924, 0x924},
+ { (UINT16) (DDR1066 + DDR1333), 0xFF6, 0xFF6, 0xFF6, 0xDAD},
+ { (UINT16) (DDR1600 + DDR1866), 0xFF6, 0xFF6, 0xFF6, 0xDAD}},
+ {{ (UINT16) DDR800, 0xDAD, 0xDAD, 0x924, 0x924},
+ { (UINT16) (DDR1066 + DDR1333), 0xFF6, 0xFF6, 0xFF6, 0xFF6},
+ { (UINT16) (DDR1600 + DDR1866), 0xFF6, 0xFF6, 0xFF6, 0xFF6}}
+ };
+
+ CONST PHY_COMP_INIT_CLIENTNB PhyCompInitBitField[] = {
+ // 3. Program TxPreP/TxPreN for Data and DQS according toTable 14 if VDDIO is 1.5V or Table 15 if 1.35V.
+ // A. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]0[A,6]={0000b, TxPreP, TxPreN}.
+ // B. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]02={1000b, TxPreP, TxPreN}.
+ {BFDqsDrvStren, BFDataByteTxPreDriverCal2Pad1, BFDataByteTxPreDriverCal2Pad1, 0, TxPrePNDataDqs},
+ {BFDataDrvStren, BFDataByteTxPreDriverCal2Pad2, BFDataByteTxPreDriverCal2Pad2, 0, TxPrePNDataDqs},
+ {BFDataDrvStren, BFDataByteTxPreDriverCal, BFDataByteTxPreDriverCal, 8, TxPrePNDataDqs},
+ // 4. Program TxPreP/TxPreN for Cmd/Addr according toTable 16 if VDDIO is 1.5V or Table 17 if 1.35V.
+ // A. Program D18F2x[1,0]9C_x0D0F_[C,8][1:0][12,0E,0A,06]={0000b, TxPreP, TxPreN}.
+ // B. Program D18F2x[1,0]9C_x0D0F_[C,8][1:0]02={1000b, TxPreP, TxPreN}.
+ {BFCsOdtDrvStren, BFCmdAddr0TxPreDriverCal2Pad1, BFCmdAddr0TxPreDriverCal2Pad2, 0, TxPrePNCmdAddr},
+ {BFAddrCmdDrvStren, BFCmdAddr1TxPreDriverCal2Pad1, BFAddrTxPreDriverCal2Pad4, 0, TxPrePNCmdAddr},
+ {BFCsOdtDrvStren, BFCmdAddr0TxPreDriverCalPad0, BFCmdAddr0TxPreDriverCalPad0, 8, TxPrePNCmdAddr},
+ {BFCkeDrvStren, BFAddrTxPreDriverCalPad0, BFAddrTxPreDriverCalPad0, 8, TxPrePNCmdAddr},
+ {BFAddrCmdDrvStren, BFCmdAddr1TxPreDriverCalPad0, BFCmdAddr1TxPreDriverCalPad0, 8, TxPrePNCmdAddr},
+ // 5. Program TxPreP/TxPreN for Clock according toTable 18 if VDDIO is 1.5V or Table 19 if 1.35V.
+ // A. Program D18F2x[1,0]9C_x0D0F_2[1:0]02={1000b, TxPreP, TxPreN}.
+ {BFClkDrvStren, BFClock0TxPreDriverCalPad0, BFClock1TxPreDriverCalPad0, 8, TxPrePNClock}
+ };
+
+ BIT_FIELD_NAME CurrentBitField;
+ UINT16 SpeedMask;
+ CONST UINT16 (*TxPrePNArray)[5];
+ UINT8 Voltage;
+ UINT8 i;
+ UINT8 j;
+ UINT8 k;
+ UINT8 Dct;
+
+ Dct = NBPtr->Dct;
+ NBPtr->SwitchDCT (NBPtr, 0);
+ // 1. Program D18F2x[1,0]9C_x0D0F_E003[DisAutoComp, DisablePreDriverCal] = {1b, 1b}.
+ MemNSetBitFieldNb (NBPtr, BFDisablePredriverCal, 0x6000);
+ NBPtr->SwitchDCT (NBPtr, Dct);
+
+ SpeedMask = (UINT16) 1 << (NBPtr->DCTPtr->Timings.Speed / 66);
+ Voltage = (UINT8) CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage);
+
+ for (j = 0; j < GET_SIZE_OF (PhyCompInitBitField); j ++) {
+ i = (UINT8) MemNGetBitFieldNb (NBPtr, PhyCompInitBitField[j].IndexBitField);
+ TxPrePNArray = PhyCompInitBitField[j].TxPrePN[Voltage];
+ for (k = 0; k < 3; k ++) {
+ if ((TxPrePNArray[k][0] & SpeedMask) != 0) {
+ for (CurrentBitField = PhyCompInitBitField[j].StartTargetBitField; CurrentBitField <= PhyCompInitBitField[j].EndTargetBitField; CurrentBitField ++) {
+ MemNSetBitFieldNb (NBPtr, CurrentBitField, ((PhyCompInitBitField[j].ExtraValue << 12) | TxPrePNArray[k][i + 1]));
+ }
+ break;
+ }
+ }
+ ASSERT (k < 3);
+ }
+
+ NBPtr->FamilySpecificHook[ForceAutoComp] (NBPtr, NBPtr);
+}
+
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function re-enable phy compensation.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNReEnablePhyCompNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ UINT8 Dct;
+
+ Dct = NBPtr->Dct;
+
+ NBPtr->SwitchDCT (NBPtr, 0);
+ // Clear DisableCal and set DisablePredriverCal
+ MemNSetBitFieldNb (NBPtr, BFDisablePredriverCal, 0x2000);
+ NBPtr->SwitchDCT (NBPtr, Dct);
+
+ return TRUE;
+}
+
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function calculates the value of WrDqDqsEarly and programs it into
+ * the DCT and adds it to the WrDqsGrossDelay of each byte lane on each
+ * DIMM of the channel.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNCalcWrDqDqsEarlyUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ DCT_STRUCT *DCTPtr;
+ CH_DEF_STRUCT *ChannelPtr;
+ UINT8 Dimm;
+ UINT8 ByteLane;
+ UINT8 *WrDqsDlysPtr;
+ UINT8 WrDqDqsEarly;
+ UINT8 ChipSel;
+
+ ASSERT ((NBPtr->IsSupported[WLSeedAdjust]) && (NBPtr->IsSupported[WLNegativeDelay]));
+
+ TechPtr = NBPtr->TechPtr;
+ ChannelPtr = NBPtr->ChannelPtr;
+ DCTPtr = NBPtr->DCTPtr;
+
+ ASSERT (NBPtr != NULL);
+ ASSERT (ChannelPtr != NULL);
+ ASSERT (DCTPtr != NULL);
+ //
+ // For each DIMM:
+ // - The Critical Gross Delay (CGD) is the minimum GrossDly of all byte lanes and all DIMMs.
+ // - If (CGD < 0) Then
+ // - D18F2xA8_dct[1:0][WrDqDqsEarly] = ABS(CGD)
+ // - WrDqsGrossDly = GrossDly + WrDqDqsEarly
+ // - Else
+ // - D18F2xA8_dct[1:0][WrDqDqsEarly] = 0.
+ // - WrDqsGrossDly = GrossDly
+ //
+ WrDqDqsEarly = 0;
+ if (TechPtr->WLCriticalDelay < 0) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCalculating WrDqDqsEarly, adjusting WrDqs.\n");
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMin. Critical Delay: %x\n", TechPtr->WLCriticalDelay);
+ // We've saved the entire negative delay value, so take the ABS and convert to GrossDly.
+ WrDqDqsEarly = (UINT8) (0x00FF &((((ABS (TechPtr->WLCriticalDelay)) + 0x1F) / 0x20)));
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tWrDqDqsEarly : %02x\n\n", WrDqDqsEarly);
+ //
+ // Loop through All WrDqsDlys on all DIMMs
+ //
+ for (ChipSel = 0; ChipSel < NBPtr->CsPerChannel; ChipSel = ChipSel + NBPtr->CsPerDelay) {
+ if ((NBPtr->MCTPtr->Status[SbLrdimms]) ? ((NBPtr->ChannelPtr->LrDimmPresent & ((UINT8) 1 << (ChipSel >> 1))) != 0) :
+ ((DCTPtr->Timings.CsEnabled & ((UINT16) ((NBPtr->CsPerDelay == 2)? 3 : 1) << ChipSel)) != 0)) {
+ //
+ // If LRDIMMs, only include the physical dimms, not logical Dimms
+ //
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tCS %x:", ChipSel);
+ Dimm = ChipSel / NBPtr->CsPerDelay;
+
+ WrDqsDlysPtr = &(ChannelPtr->WrDqsDlys[(Dimm * TechPtr->DlyTableWidth ())]);
+ for (ByteLane = 0; ByteLane < (NBPtr->MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
+ WrDqsDlysPtr[ByteLane] += (WrDqDqsEarly << 5);
+ NBPtr->SetTrainDly (NBPtr, AccessWrDqsDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), WrDqsDlysPtr[ByteLane]);
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x", WrDqsDlysPtr[ByteLane]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n");
+ }
+ }
+ }
+ MemNSetBitFieldNb (NBPtr, BFWrDqDqsEarly, WrDqDqsEarly);
+ return TRUE;
+}
+
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function forces phy to M0 state
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return none
+ * ----------------------------------------------------------------------------
+ */
+VOID
+MemNForcePhyToM0Unb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ IDS_SKIP_HOOK (IDS_FORCE_PHY_TO_M0, NBPtr, &(NBPtr->MemPtr->StdHeader)) {
+ // 1. Program D18F2x9C_x0D0F_E013_dct[1:0] = 0118h.
+ MemNBrdcstSetUnConditionalNb (NBPtr, BFPllRegWaitTime, 0x118);
+ // 2. For each byte lane and each memory P-state: Program D18F2x9C_x0D0F_0[F,7:0][53,13]_dct[1:0][RxSsbMntClkEn] = 0.
+ MemNBrdcstSetUnConditionalNb (NBPtr, BFRxSsbMntClkEn, 0);
+ // 3. D18F2xA8_dct[1:0][MemPhyPllPdMode] = 00b.
+ MemNBrdcstSetUnConditionalNb (NBPtr, BFMemPhyPllPdMode, 0);
+ // 4. Force the phy to M0 with the following sequence:
+ // A. Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 190h. Restore the default PLL lock time.
+ MemNBrdcstSetUnConditionalNb (NBPtr, BFPllLockTime, NBPtr->FreqChangeParam->PllLockTimeDefault);
+ // B. For each DCT: Program D18F2x9C_x0000_000B_dct[1:0] = 80800000h.
+ MemNBrdcstSetUnConditionalNb (NBPtr, BFDramPhyStatusReg, 0x80800000);
+ NBPtr->SwitchDCT (NBPtr, 0);
+ // C. Program D18F2x9C_x0D0F_E018_dct[0][PhyPSMasterChannel] = 0.
+ MemNSetBitFieldNb (NBPtr, BFPhyPSMasterChannel, 0);
+ // D. Program D18F2x9C_x0000_000B_dct[0] = 40000000h. CH0 only;
+ MemNSetBitFieldNb (NBPtr, BFDramPhyStatusReg, 0x40000000);
+ // E. For each DCT: Program D18F2x9C_x0000_000B_dct[1:0] = 80000000h.
+ MemNBrdcstSetUnConditionalNb (NBPtr, BFDramPhyStatusReg, 0x80000000);
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function sets SkewMemClk before enabling MemClk
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *OptParam - Optional parameter
+ *
+ * @return TRUE - always
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNSetSkewMemClkUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ UINT8 Dct;
+
+ // SkewMemClk is set to 1 if all DCTs are enabled, else 0.
+ for (Dct = 0; Dct < NBPtr->DctCount; Dct++) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ if (NBPtr->DCTPtr->Timings.DctMemSize == 0) {
+ break;
+ }
+ }
+ MemNSwitchDCTNb (NBPtr, 0);
+ if (Dct == NBPtr->DctCount) {
+ MemNSetBitFieldNb (NBPtr, BFSkewMemClk, 0x10);
+ } else {
+ MemNSetBitFieldNb (NBPtr, BFSkewMemClk, 0);
+ }
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function masks the RdDqsDly Bit 0 before writing to register for UNB.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *Offset - Bit offset of the field to be programmed
+ *
+ * @return TRUE
+ */
+BOOLEAN
+MemNAdjustRdDqsDlyOffsetUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *Offset
+ )
+{
+ *(UINT16*) Offset = *(UINT16*) Offset + 1;
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function delays MEMCLK to prevent WrDqs skew due to negative PRE result.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNCalcWrDqDqsEarlyClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ DCT_STRUCT *DCTPtr;
+ CH_DEF_STRUCT *ChannelPtr;
+ UINT8 Dimm;
+ UINT8 ByteLane;
+ UINT8 *WrDqsDlysPtr;
+ UINT8 NewClkDllDelay;
+ UINT16 ClkDllFineDly;
+ UINT32 AddrCmdTmg;
+
+ TechPtr = NBPtr->TechPtr;
+ ChannelPtr = NBPtr->ChannelPtr;
+ DCTPtr = NBPtr->DCTPtr;
+
+ ASSERT (NBPtr != NULL);
+ ASSERT (ChannelPtr != NULL);
+ ASSERT (DCTPtr != NULL);
+
+ if (NBPtr->IsSupported[WLNegativeDelay]) {
+ if (TechPtr->WLCriticalDelay < 0) {
+ NewClkDllDelay = (UINT8) ABS (TechPtr->WLCriticalDelay);
+
+ // Prepare new delay for MEMCLK
+ ClkDllFineDly = (UINT16) ((MemNGetBitFieldNb (NBPtr, BFPhyClkDllFine0) & 0xBF60) | NewClkDllDelay);
+
+ // Program bit 7(FenceBit) = 1 if NewClkDllDelay >= > F2x9C[FenceThresholdTxPad], else 0.
+ ClkDllFineDly |= (NewClkDllDelay >= MemNGetBitFieldNb (NBPtr, BFPhyFence)) ? 0x80 : 0;
+
+ // Apply new delay to both chiplets
+ MemNSetBitFieldNb (NBPtr, BFPhyClkDllFine0, ClkDllFineDly | 0x4000);
+ MemNSetBitFieldNb (NBPtr, BFPhyClkDllFine0, ClkDllFineDly);
+ MemNSetBitFieldNb (NBPtr, BFPhyClkDllFine1, ClkDllFineDly | 0x4000);
+ MemNSetBitFieldNb (NBPtr, BFPhyClkDllFine1, ClkDllFineDly);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tShift MemClk, AddrCmd, CsOdt, Cke by %d to eliminate negative WL\n", NewClkDllDelay);
+
+ //
+ // Adjust AddrCmd/CsOdt/Cke timing by amount MemClk was delayed
+ //
+ AddrCmdTmg = MemNGetBitFieldNb (NBPtr, BFAddrTmgControl);
+ AddrCmdTmg += (NewClkDllDelay << 16) | (NewClkDllDelay << 8) | NewClkDllDelay;
+ AddrCmdTmg &= 0x003F3F3F;
+ MemNSetBitFieldNb (NBPtr, BFAddrTmgControl, AddrCmdTmg);
+
+ //
+ // Adjust all WrDqsDlys on all DIMMs of the current channel
+ //
+ for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) {
+ if ((DCTPtr->Timings.CsEnabled & ((UINT16)3 << (Dimm << 1))) != 0) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCS%d\n\t\t\tWrDqs:", Dimm << 1);
+ WrDqsDlysPtr = &(ChannelPtr->WrDqsDlys[(Dimm * TechPtr->DlyTableWidth ())]);
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ WrDqsDlysPtr[ByteLane] = (UINT8) (WrDqsDlysPtr[ByteLane] + NewClkDllDelay);
+ NBPtr->SetTrainDly (NBPtr, AccessWrDqsDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), WrDqsDlysPtr[ByteLane]);
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x", WrDqsDlysPtr[ByteLane]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n");
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function initializes RxEn Delays for RxEn seedless training
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNInitializeRxEnSeedlessTrainingUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ UINT8 ByteLane;
+ // Save original PRE based RxEnDly for RxEn Seedless training
+ for (ByteLane = 0; ByteLane < (NBPtr->MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
+ NBPtr->TechPtr->RxOrig[ByteLane] = NBPtr->ChannelPtr->RcvEnDlys[(NBPtr->TechPtr->ChipSel / NBPtr->CsPerDelay) * NBPtr->TechPtr->DlyTableWidth () + ByteLane];
+ }
+ return TRUE;
+}
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function checks each bytelane for no window error.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNTrackRxEnSeedlessRdWrNoWindBLErrorUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ MemTTrackRxEnSeedlessRdWrNoWindBLError (NBPtr->TechPtr, OptParam);
+ return TRUE;
+}
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function checks each bytelane for small window error.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNTrackRxEnSeedlessRdWrSmallWindBLErrorUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ MemTTrackRxEnSeedlessRdWrSmallWindBLError (NBPtr->TechPtr, OptParam);
+ return TRUE;
+}
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * This function initializes a ByteLaneError error.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] OptParam - Optional parameter
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNInitialzeRxEnSeedlessByteLaneErrorUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ UINT8 ByteLane;
+ for (ByteLane = 0; ByteLane < (NBPtr->MCTPtr->Status[SbEccDimms] ? 9 : 8); ByteLane++) {
+ NBPtr->TechPtr->ByteLaneError[ByteLane] = FALSE; // All Bytelanes have no errors
+ }
+ return TRUE;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets phy power saving related settings in different MPstate context.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return none
+ * ----------------------------------------------------------------------------
+ */
+VOID
+MemNPhyPowerSavingMPstateUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ STATIC UINT8 Sequence[] = {8, 4, 3, 5, 2, 6, 1, 7, 0};
+ UINT16 DllPower[9];
+ UINT8 NumLanes;
+ UINT8 DllWakeTime;
+ UINT8 MaxRxStggrDly;
+ UINT8 MinRcvEnGrossDly;
+ UINT8 MinWrDatGrossDly;
+ UINT8 dRxStggrDly;
+ UINT8 dTxStggrDly;
+ UINT8 TempStggrDly;
+ UINT8 MaxTxStggrDly;
+ UINT8 Tcwl;
+ UINT8 i;
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "Start Phy power saving setting for memory Pstate %d\n", NBPtr->MemPstate);
+ // 4. Program D18F2x9C_x0D0F_0[F,8:0]13_dct[1:0][DllDisEarlyU] = 1b.
+ // 5. Program D18F2x9C_x0D0F_0[F,8:0]13_dct[1:0][DllDisEarlyL] = 1b.
+ // 6. D18F2x9C_x0D0F_0[F,7:0][53,13]_dct[1:0][RxDqsUDllPowerDown] = 1.
+ MemNSetBitFieldNb (NBPtr, BFPhy0x0D0F0F13, MemNGetBitFieldNb (NBPtr, BFPhy0x0D0F0F13) | 0x83);
+ // 7. D18F2x9C_x0D0F_812F_dct[1:0][PARTri] = ~D18F2x90_dct[1:0][ParEn].
+ // 8. D18F2x9C_x0D0F_812F_dct[1:0][Add17Tri, Add16Tri] = {1b, 1b}
+ if (NBPtr->MemPstate == MEMORY_PSTATE0) {
+ MemNSetBitFieldNb (NBPtr, BFAddrCmdTri, MemNGetBitFieldNb (NBPtr, BFAddrCmdTri) | 0xA1);
+ }
+ // 9. IF (DimmsPopulated == 1)&& ((D18F2x9C_x0000_0000_dct[1:0]_mp[1:0][CkeDrvStren]==010b) ||
+ // (D18F2x9C_x0000_0000_dct[1:0]_mp[1:0][CkeDrvStren]==011b)) THEN THEN
+ // program D18F2x9C_x0D0F_C0[40,00]_dct[1:0][LowPowerDrvStrengthEn] = 1
+ // ELSE program D18F2x9C_x0D0F_C0[40,00]_dct[1:0][LowPowerDrvStrengthEn] = 0 ENDIF.
+ if ((NBPtr->ChannelPtr->Dimms == 1) && ((MemNGetBitFieldNb (NBPtr, BFCkeDrvStren) == 2) || (MemNGetBitFieldNb (NBPtr, BFCkeDrvStren) == 3))) {
+ MemNSetBitFieldNb (NBPtr, BFLowPowerDrvStrengthEn, 0x100);
+ }
+ // 10. Program D18F2x9C_x0D0F_0[F,7:0][50,10]_dct[1:0][EnRxPadStandby] = IF
+ // (D18F2x94_dct[1:0][MemClkFreq] <= 800 MHz) THEN 1 ELSE 0 ENDIF.
+ MemNSetBitFieldNb (NBPtr, BFEnRxPadStandby, (NBPtr->DCTPtr->Timings.Speed <= DDR1600_FREQUENCY) ? 0x1000 : 0);
+ // 11. Program D18F2x9C_x0000_000D_dct[1:0]_mp[1:0] as follows:
+ // If (DDR rate < = 1600) TxMaxDurDllNoLock = RxMaxDurDllNoLock = 8h
+ // else TxMaxDurDllNoLock = RxMaxDurDllNoLock = 7h.
+ if (NBPtr->DCTPtr->Timings.Speed <= DDR1600_FREQUENCY) {
+ MemNSetBitFieldNb (NBPtr, BFTxMaxDurDllNoLock, 8);
+ MemNSetBitFieldNb (NBPtr, BFRxMaxDurDllNoLock, 8);
+ } else {
+ MemNSetBitFieldNb (NBPtr, BFTxMaxDurDllNoLock, 7);
+ MemNSetBitFieldNb (NBPtr, BFRxMaxDurDllNoLock, 7);
+ }
+ // TxCPUpdPeriod = RxCPUpdPeriod = 011b.
+ MemNSetBitFieldNb (NBPtr, BFTxCPUpdPeriod, 3);
+ MemNSetBitFieldNb (NBPtr, BFRxCPUpdPeriod, 3);
+ // TxDLLWakeupTime = RxDLLWakeupTime = 11b.
+ MemNSetBitFieldNb (NBPtr, BFTxDLLWakeupTime, 3);
+ MemNSetBitFieldNb (NBPtr, BFRxDLLWakeupTime, 3);
+
+ if (NBPtr->IsSupported[DllStaggerEn]) {
+ // 12. Program D18F2x9C_x0D0F_0[F,7:0][5C,1C]_dct[1:0] as follows.
+ // Let Numlanes = 8. = 9 with ECC.
+ NumLanes = (NBPtr->MCTPtr->Status[SbEccDimms] && NBPtr->IsSupported[EccByteTraining]) ? 9 : 8;
+ // RxDllStggrEn = TxDllStggrEn = 1.
+ for (i = 0; i < 9; i ++) {
+ DllPower[i] = 0x8080;
+ }
+ // If (DDR rate > = 1866) DllWakeTime = 1, Else DllWakeTime = 0.
+ DllWakeTime = (NBPtr->DCTPtr->Timings.Speed >= DDR1866_FREQUENCY) ? 1 : 0;
+ // Let MaxRxStggrDly = (Tcl*2) + MIN(DqsRcvEnGrossDelay for all byte lanes (see D18F2x9C_x0000_00[2A:10]_dct[1:0]_mp[1:0])) - 4.
+ MinRcvEnGrossDly = NBPtr->TechPtr->GetMinMaxGrossDly (NBPtr->TechPtr, AccessRcvEnDly, FALSE);
+ ASSERT ((NBPtr->DCTPtr->Timings.CasL * 2 + MinRcvEnGrossDly) >= 4);
+ MaxRxStggrDly = NBPtr->DCTPtr->Timings.CasL * 2 + MinRcvEnGrossDly - 4;
+ // Let (real) dRxStggrDly = (MaxRxStggrDly - DllWakeTime) / (Numlanes - 1).
+ ASSERT (MaxRxStggrDly >= DllWakeTime);
+ dRxStggrDly = (MaxRxStggrDly - DllWakeTime) / (NumLanes - 1);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tMinimum RcvEnGrossDly: 0x%02x MaxRxStggrDly: 0x%02x dRxStggrDly: 0x%02x\n", MinRcvEnGrossDly, MaxRxStggrDly, dRxStggrDly);
+ // For each byte lane in the ordered sequence {8, 4, 3, 5, 2, 6, 1, 7, 0}, program RxDllStggrDly[5:0] = an
+ // increasing value, starting with 0 for the first byte lane in the sequence and increasing at a rate of dRxStggrDly
+ // for each subsequent byte lane. Convert the real to integer by rounding down or using C (int) typecast after linearization.
+ i = 9 - NumLanes;
+ TempStggrDly = 0;
+ for (; i < 9; i ++) {
+ DllPower[Sequence[i]] |= ((TempStggrDly & 0x3F) << 8);
+ TempStggrDly = TempStggrDly + dRxStggrDly;
+ }
+
+ // Let MaxTxStggrDly = (Tcwl*2) + MIN(MIN (WrDatGrossDly for all byte lanes (see
+ // D18F2x9C_x0000_0[3:0]0[2:1]_dct[1:0]_mp[1:0])), MIN(DqsRcvEnGrossDelay for all byte lanes (see
+ // D18F2x9C_x0000_00[2A:10]_dct[1:0]_mp[1:0])) - 4.
+ Tcwl = (UINT8) MemNGetBitFieldNb (NBPtr, BFTcwl);
+ MinWrDatGrossDly = NBPtr->TechPtr->GetMinMaxGrossDly (NBPtr->TechPtr, AccessWrDatDly, FALSE);
+ MaxTxStggrDly = Tcwl * 2 + MIN (MinRcvEnGrossDly, MinWrDatGrossDly) - 4;
+ // Let dTxStggrDly = (MaxTxStggrDly - DllWakeTime) / (Numlanes - 1).
+ ASSERT (MaxTxStggrDly >= DllWakeTime);
+ dTxStggrDly = (MaxTxStggrDly - DllWakeTime) / (NumLanes - 1);
+ // For each byte lane in the ordered sequence {8, 4, 3, 5, 2, 6, 1, 7, 0}, program TxDllStggrDly[5:0] = an
+ // increasing integer value, starting with 0 for the first byte lane in the sequence and increasing at a rate of
+ // dTxStggrDly for each subsequent byte lane.
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tMinimum WrDatGrossDly: 0x%02x MaxTxStggrDly: 0x%02x dTxStggrDly: 0x%02x\n", MinWrDatGrossDly, MaxTxStggrDly, dTxStggrDly);
+ i = 9 - NumLanes;
+ TempStggrDly = 0;
+ for (; i < 9; i ++) {
+ DllPower[Sequence[i]] |= (TempStggrDly & 0x3F);
+ TempStggrDly = TempStggrDly + dTxStggrDly;
+ }
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t\tByte Lane : ECC 07 06 05 04 03 02 01 00\n");
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t\tDll Power : %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ DllPower[8], DllPower[7], DllPower[6], DllPower[5], DllPower[4], DllPower[3], DllPower[2], DllPower[1], DllPower[0]);
+
+ for (i = 0; i < NumLanes; i ++) {
+ MemNSetBitFieldNb (NBPtr, BFDataByteDllPowerMgnByte0 + i, (MemNGetBitFieldNb (NBPtr, BFDataByteDllPowerMgnByte0 + i) & 0x4040) | DllPower[i]);
+ }
+ }
+ // 13. Program D18F2x248_dct[1:0]_mp[1:0] and then D18F2x9C_x0D0F_0[F,7:0][53,13]_dct[1:0] as follows:
+ // For M1 context program RxChMntClkEn=RxSsbMntClkEn=0.
+ // For M0 context program RxChMntClkEn=RxSsbMntClkEn=1.
+ if (NBPtr->MemPstate == MEMORY_PSTATE1) {
+ MemNSetBitFieldNb (NBPtr, BFRxChMntClkEn, 0);
+ MemNSetBitFieldNb (NBPtr, BFRxSsbMntClkEn, 0);
+ } else {
+ MemNSetBitFieldNb (NBPtr, BFRxChMntClkEn, 1);
+ MemNSetBitFieldNb (NBPtr, BFRxSsbMntClkEn, 0x100);
+ }
+
+ IDS_OPTION_HOOK (IDS_PHY_DLL_STANDBY_CTRL, NBPtr, &NBPtr->MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function resets RxFifo pointer during Read DQS training
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *OptParam - Optional parameter
+ *
+ * @return TRUE
+ */
+
+BOOLEAN
+MemNResetRxFifoPtrClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ if (NBPtr->TechPtr->Direction == DQS_READ_DIR) {
+ MemNSetBitFieldNb (NBPtr, BFRxPtrInitReq, 1);
+ MemNPollBitFieldNb (NBPtr, BFRxPtrInitReq, 0, PCI_ACCESS_TIMEOUT, FALSE);
+ }
+ return TRUE;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function adjusts WrDqsBias before seed scaling
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *WrDqsBias - Pointer to WrDqsBias
+ *
+ * @return FALSE - Supported
+ * @return TRUE - Not supported
+ */
+
+BOOLEAN
+MemNAdjustWrDqsBeforeSeedScalingUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *WrDqsBias
+ )
+{
+ // Subtract (0x20 * WrDqDqsEarly) since it is a non-scalable component
+ * (INT16 *) WrDqsBias = (INT16) (0x20 * MemNGetBitFieldNb (NBPtr, BFWrDqDqsEarly));
+ return TRUE;
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnreg.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnreg.c
new file mode 100644
index 0000000000..445a4659b3
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mnreg.c
@@ -0,0 +1,608 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnreg.c
+ *
+ * Common Northbridge register access functions
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB/)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "merrhdl.h"
+#include "heapManager.h"
+#include "Filecode.h"
+#include "GeneralServices.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_MEM_NB_MNREG_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the current DCT to work on.
+ * Should be called before accessing a certain DCT
+ * All data structures will be updated to point to the current DCT
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Dct - ID of the target DCT
+ *
+ */
+
+VOID
+MemNSwitchDCTNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ )
+{
+ ASSERT (NBPtr->DctCount > Dct);
+ //
+ // Set the DctCfgSel to new DCT
+ //
+ NBPtr->FamilySpecificHook[DCTSelectSwitch] (NBPtr, &Dct);
+ NBPtr->Dct = Dct;
+ NBPtr->MCTPtr->Dct = NBPtr->Dct;
+ NBPtr->DCTPtr = &(NBPtr->MCTPtr->DctData[NBPtr->Dct]);
+ NBPtr->PsPtr = &(NBPtr->PSBlock[NBPtr->Dct]);
+ NBPtr->DctCachePtr = &(NBPtr->DctCache[NBPtr->Dct]);
+
+ MemNSwitchChannelNb (NBPtr, NBPtr->Channel);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function is used by families that use a separate DctCfgSel bit to
+ * select the current DCT which will be accessed by function 2.
+ * NOTE: This function must be called BEFORE the NBPtr->Dct variable is
+ * updated.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *Dct - Pointer to ID of the target DCT
+ *
+ */
+
+BOOLEAN
+MemNDctCfgSelectUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN VOID *Dct
+ )
+{
+ //
+ // Sanity check the current DctCfgSel setting
+ //
+ ASSERT (NBPtr->Dct == NBPtr->GetBitField (NBPtr, BFDctCfgSel));
+ //
+ // Set the DctCfgSel to new DCT
+ //
+ NBPtr->SetBitField (NBPtr, BFDctCfgSel, *(UINT8*)Dct);
+
+ return TRUE;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the current channel to work on.
+ * Should be called before accessing a certain channel
+ * All data structures will be updated to point to the current channel
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Channel - ID of the target channel
+ *
+ */
+
+VOID
+MemNSwitchChannelNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ )
+{
+ NBPtr->Channel = Channel ? 1 : 0;
+ NBPtr->ChannelPtr = &(NBPtr->DCTPtr->ChData[NBPtr->Channel]);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function gets a bit field from PCI register
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] FieldName - Field name
+ *
+ * @return Bit field value
+ */
+
+UINT32
+MemNGetBitFieldNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BIT_FIELD_NAME FieldName
+ )
+{
+ UINT32 Value;
+
+ Value = NBPtr->MemNCmnGetSetFieldNb (NBPtr, 0, FieldName, 0);
+ return Value;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets a bit field from PCI register
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] FieldName - Field name
+ * @param[in] Field - Value to be stored in PCT register
+ *
+ */
+
+VOID
+MemNSetBitFieldNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ NBPtr->MemNCmnGetSetFieldNb (NBPtr, 1, FieldName, Field);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Check if bitfields of all enabled DCTs on a die have the expected value. Ignore
+ * DCTs that are disabled.
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] FieldName - Bit Field name
+ * @param[in] Field - Value to be checked
+ *
+ * @return TRUE - All enabled DCTs have the expected value on the bitfield.
+ * @return FALSE - Not all enabled DCTs have the expected value on the bitfield.
+ *
+ * ----------------------------------------------------------------------------
+ */
+BOOLEAN
+MemNBrdcstCheckNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ UINT8 Dct;
+ UINT8 CurrentDCT;
+ Dct = NBPtr->Dct;
+ for (CurrentDCT = 0; CurrentDCT < NBPtr->DctCount; CurrentDCT++) {
+ MemNSwitchDCTNb (NBPtr, CurrentDCT);
+ if ((NBPtr->DCTPtr->Timings.DctMemSize != 0) && !((CurrentDCT == 1) && NBPtr->Ganged)) {
+ if (MemNGetBitFieldNb (NBPtr, FieldName) != Field) {
+ MemNSwitchDCTNb (NBPtr, Dct);
+ return FALSE;
+ }
+ }
+ }
+ MemNSwitchDCTNb (NBPtr, Dct);
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Set bitfields of all enabled DCTs on a die to a value. Ignore
+ * DCTs that are disabled.
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] FieldName - Bit Field name
+ * @param[in] Field - Value to be set
+ *
+ * ----------------------------------------------------------------------------
+ */
+VOID
+MemNBrdcstSetNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ UINT8 Dct;
+ UINT8 CurrentDCT;
+ Dct = NBPtr->Dct;
+ for (CurrentDCT = 0; CurrentDCT < NBPtr->DctCount; CurrentDCT++) {
+ MemNSwitchDCTNb (NBPtr, CurrentDCT);
+ if ((NBPtr->DCTPtr->Timings.DctMemSize != 0) && !((CurrentDCT == 1) && NBPtr->Ganged)) {
+ MemNSetBitFieldNb (NBPtr, FieldName, Field);
+ }
+ }
+ MemNSwitchDCTNb (NBPtr, Dct);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Set bitfields of all DCTs regardless of if they are being enabled or not on a
+ * die to a value.
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] FieldName - Bit Field name
+ * @param[in] Field - Value to be set
+ *
+ * ----------------------------------------------------------------------------
+ */
+VOID
+MemNBrdcstSetUnConditionalNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ UINT8 Dct;
+ UINT8 CurrentDCT;
+ Dct = NBPtr->Dct;
+ for (CurrentDCT = 0; CurrentDCT < NBPtr->DctCount; CurrentDCT++) {
+ MemNSwitchDCTNb (NBPtr, CurrentDCT);
+ MemNSetBitFieldNb (NBPtr, FieldName, Field);
+ }
+ MemNSwitchDCTNb (NBPtr, Dct);
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ * This function calculates the memory channel index relative to the
+ * socket, taking the Die number, the Dct, and the channel.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Dct
+ * @param[in] Channel
+ *
+ */
+UINT8
+MemNGetSocketRelativeChannelNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct,
+ IN UINT8 Channel
+ )
+{
+ return ((NBPtr->MCTPtr->DieId * NBPtr->DctCount) + Dct);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Poll a bitfield. If the bitfield does not get set to the target value within
+ * specified microseconds, it times out.
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] FieldName - Bit Field name
+ * @param[in] Field - Value to be set
+ * @param[in] MicroSecond - Number of microsecond to wait
+ * @param[in] IfBroadCast - Need to broadcast to both DCT or not
+ *
+ * ----------------------------------------------------------------------------
+ */
+VOID
+MemNPollBitFieldNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field,
+ IN UINT32 MicroSecond,
+ IN BOOLEAN IfBroadCast
+ )
+{
+ BOOLEAN ErrorRecovery;
+ BOOLEAN IgnoreErr;
+ UINT8 ExcludeDCT;
+ UINT16 ExcludeChipSelMask;
+ UINT32 EventInfo;
+ UINT64 InitTSC;
+ UINT64 CurrentTSC;
+ UINT64 TimeOut;
+ AGESA_STATUS EventClass;
+ MEM_DATA_STRUCT *MemPtr;
+ DIE_STRUCT *MCTPtr;
+ BOOLEAN TimeoutEn;
+
+ MemPtr = NBPtr->MemPtr;
+ MCTPtr = NBPtr->MCTPtr;
+ ExcludeDCT = EXCLUDE_ALL_DCT;
+ ExcludeChipSelMask = EXCLUDE_ALL_CHIPSEL;
+ TimeoutEn = TRUE;
+ IDS_TIMEOUT_CTL (&TimeoutEn);
+
+ CurrentTSC = 0;
+ LibAmdMsrRead (TSC, &InitTSC, &MemPtr->StdHeader);
+ TimeOut = InitTSC + ((UINT64) MicroSecond * MemPtr->TscRate);
+
+ while ((CurrentTSC < TimeOut) || !TimeoutEn) {
+ if (IfBroadCast) {
+ if (NBPtr->BrdcstCheck (NBPtr, FieldName, Field)) {
+ break;
+ }
+ } else {
+ if (MemNGetBitFieldNb (NBPtr, FieldName) == Field) {
+ break;
+ }
+ }
+ LibAmdMsrRead (TSC, &CurrentTSC, &MemPtr->StdHeader);
+ }
+
+ if ((CurrentTSC >= TimeOut) && TimeoutEn) {
+ ErrorRecovery = TRUE;
+ IgnoreErr = FALSE;
+ IDS_OPTION_HOOK (IDS_MEM_ERROR_RECOVERY, &ErrorRecovery, &MemPtr->StdHeader);
+ IDS_OPTION_HOOK (IDS_MEM_IGNORE_ERROR, &IgnoreErr, &MemPtr->StdHeader);
+
+ // Default event class
+ // If different event class is needed in one entry, override it.
+ EventClass = AGESA_ERROR;
+ switch (FieldName) {
+ case BFDramEnabled:
+ EventInfo = MEM_ERROR_DRAM_ENABLED_TIME_OUT;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tDramEnabled bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFDctAccessDone:
+ EventInfo = MEM_ERROR_DCT_ACCESS_DONE_TIME_OUT;
+ ExcludeDCT = NBPtr->Dct;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tDctAccessDone bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFSendCtrlWord:
+ EventInfo = MEM_ERROR_SEND_CTRL_WORD_TIME_OUT;
+ ExcludeDCT = NBPtr->Dct;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tSendCtrlWord bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFPrefDramTrainMode:
+ EventInfo = MEM_ERROR_PREF_DRAM_TRAIN_MODE_TIME_OUT;
+ ExcludeDCT = NBPtr->Dct;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tPrefDramTrainMode bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFEnterSelfRef:
+ EventInfo = MEM_ERROR_ENTER_SELF_REF_TIME_OUT;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tEnterSelfRef bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFFreqChgInProg:
+ EventInfo = MEM_ERROR_FREQ_CHG_IN_PROG_TIME_OUT;
+ ExcludeDCT = NBPtr->Dct;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tFreqChgInProg bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFExitSelfRef:
+ EventInfo = MEM_ERROR_EXIT_SELF_REF_TIME_OUT;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tExitSelfRef bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFSendMrsCmd:
+ EventInfo = MEM_ERROR_SEND_MRS_CMD_TIME_OUT;
+ ExcludeDCT = NBPtr->Dct;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tSendMrsCmd bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFSendZQCmd:
+ EventInfo = MEM_ERROR_SEND_ZQ_CMD_TIME_OUT;
+ ExcludeDCT = NBPtr->Dct;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tSendZQCmd bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFDctExtraAccessDone:
+ EventInfo = MEM_ERROR_DCT_EXTRA_ACCESS_DONE_TIME_OUT;
+ ExcludeDCT = NBPtr->Dct;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tDctExtraAccessDone bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFMemClrBusy:
+ EventInfo = MEM_ERROR_MEM_CLR_BUSY_TIME_OUT;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClrBusy bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFMemCleared:
+ EventInfo = MEM_ERROR_MEM_CLEARED_TIME_OUT;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tMemCleared bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFFlushWr:
+ EventInfo = MEM_ERROR_FLUSH_WR_TIME_OUT;
+ ExcludeDCT = NBPtr->Dct;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tFlushWr bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ case BFCurNbPstate:
+ EventInfo = MEM_ERROR_NBPSTATE_TRANSITION_TIME_OUT;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tCurNBPstate bitfield times out.\n");
+ ASSERT (ErrorRecovery || IgnoreErr);
+ break;
+ default:
+ EventClass = 0;
+ EventInfo = 0;
+ IDS_ERROR_TRAP;
+ }
+
+ PutEventLog (EventClass, EventInfo, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &MemPtr->StdHeader);
+ SetMemError (EventClass, MCTPtr);
+ if (!MemPtr->ErrorHandling (MCTPtr, ExcludeDCT, ExcludeChipSelMask, &MemPtr->StdHeader)) {
+ ASSERT (FALSE);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function changes memory Pstate context
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] MemPstate - Target Memory Pstate
+ *
+ * @return TRUE
+ * ----------------------------------------------------------------------------
+ */
+VOID
+MemNChangeMemPStateContextNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN MEM_PSTATE MemPstate
+ )
+{
+ UINT8 PSMasterChannel;
+ UINT8 Dct;
+
+ ASSERT ((MemPstate == 0) || (MemPstate == 1));
+ ASSERT (NBPtr->MemPstate == ((MemNGetBitFieldNb (NBPtr, BFMemPsSel) == 0) ? MEMORY_PSTATE0 : MEMORY_PSTATE1));
+
+ IDS_HDT_CONSOLE (MEM_SETREG, "\nGo to Memory Pstate Conext %d\n", MemPstate);
+ Dct = NBPtr->Dct;
+ MemNSwitchDCTNb (NBPtr, 0);
+ // Figure out what is the master channel
+ PSMasterChannel = (UINT8) (MemNGetBitFieldNb (NBPtr, BFPhyPSMasterChannel) >> 8);
+
+ // Switch to the master channel to change PStateToAccess
+ // PStateToAccess is only effective on the master channel
+ MemNSwitchDCTNb (NBPtr, PSMasterChannel);
+ MemNSetBitFieldNb (NBPtr, BFMemPsSel, MemPstate);
+ MemNSetBitFieldNb (NBPtr, BFPStateToAccess, MemPstate << 8);
+
+ NBPtr->MemPstate = (MemPstate == 0) ? MEMORY_PSTATE0 : MEMORY_PSTATE1;
+ MemNSwitchDCTNb (NBPtr, Dct);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function allocates buffer for NB register table
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] Handle - Handle for heap allocation for NBRegTable
+ *
+ * @return TRUE - Successfully allocates buffer the first time
+ * @return FALSE - Buffer already allocated or fails to allocate
+ */
+
+BOOLEAN
+MemNAllocateNBRegTableNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN NB_REG_TAB_HANDLE Handle
+ )
+{
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+ LOCATE_HEAP_PTR LocHeap;
+
+ // If NBRegTable for this family exists, use it
+ LocHeap.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_NB_REG_TABLE, Handle, 0, 0);
+ if (HeapLocateBuffer (&LocHeap, &(NBPtr->MemPtr->StdHeader)) == AGESA_SUCCESS) {
+ NBPtr->NBRegTable = (TSEFO *) LocHeap.BufferPtr;
+ return FALSE;
+ }
+
+ // Allocate new buffer for NBRegTable if it has not been allocated
+ AllocHeapParams.RequestedBufferSize = sizeof (TSEFO) * BFEndOfList;
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_NB_REG_TABLE, Handle, 0, 0);
+ AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
+ if (AGESA_SUCCESS != HeapAllocateBuffer (&AllocHeapParams, &(NBPtr->MemPtr->StdHeader))) {
+ ASSERT(FALSE); // NB and Tech Block Heap allocate error
+ return FALSE;
+ }
+ NBPtr->NBRegTable = (TSEFO *)AllocHeapParams.BufferPtr;
+ return TRUE;
+}
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mntrain3.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mntrain3.c
new file mode 100644
index 0000000000..cd284bb772
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/NB/mntrain3.c
@@ -0,0 +1,269 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mntrain3.c
+ *
+ * Common Northbridge function for training flow for DDR3
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB)
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_MEM_NB_MNTRAIN3_FILECODE
+/* features */
+#include "mftds.h"
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+STATIC
+MemNHwWlPart2Nb (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern MEM_FEAT_TRAIN_SEQ memTrainSequenceDDR3[];
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initiates DQS training
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+BOOLEAN
+MemNDQSTiming3Nb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ UINT8 i;
+ BOOLEAN Retval;
+ TechPtr = NBPtr->TechPtr;
+ Retval = TRUE;
+ if (TechPtr->NBPtr->MCTPtr->NodeMemSize) {
+ //Execute Technology specific training features
+ i = 0;
+ while (memTrainSequenceDDR3[i].TrainingSequenceEnabled != 0) {
+ if (memTrainSequenceDDR3[i].TrainingSequenceEnabled (NBPtr)) {
+ NBPtr->TrainingSequenceIndex = i;
+ Retval = memTrainSequenceDDR3[i].TrainingSequence (NBPtr);
+ break;
+ }
+ i++;
+ }
+ }
+ return Retval;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initiates DQS training for Server NB
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+BOOLEAN
+memNSequenceDDR3Nb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+ UINT8 i;
+ TechPtr = NBPtr->TechPtr;
+ i = NBPtr->TrainingSequenceIndex;
+ if (TechPtr->NBPtr->MCTPtr->NodeMemSize != 0) {
+ AGESA_TESTPOINT (TpProcMemBeforeAgesaHookBeforeDQSTraining, &NBPtr->MemPtr->StdHeader);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nCalling out to Platform BIOS...\n");
+ if (AgesaHookBeforeDQSTraining (NBPtr->MCTPtr->SocketId, TechPtr->NBPtr->MemPtr) == AGESA_SUCCESS) {
+ // Right now we do not have anything to do if the callout is implemented
+ }
+ AGESA_TESTPOINT (TpProcMemAfterAgesaHookBeforeDQSTraining, &NBPtr->MemPtr->StdHeader);
+ //Execute Technology specific training features
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->EnterHardwareTraining (TechPtr)) {
+ TechPtr->TechnologySpecificHook[LrdimmBuf2DramTrain] (TechPtr, NULL);
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->SwWLTraining (TechPtr)) {
+ MemFInitTableDrive (NBPtr, MTAfterSwWLTrn);
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->HwBasedWLTrainingPart1 (TechPtr)) {
+ MemFInitTableDrive (NBPtr, MTAfterHwWLTrnP1);
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->HwBasedDQSReceiverEnableTrainingPart1 (TechPtr)) {
+ MemFInitTableDrive (NBPtr, MTAfterHwRxEnTrnP1);
+ // If target speed is higher than start-up speed, do frequency change and second pass of WL
+ do {
+ if (MemNHwWlPart2Nb (TechPtr)) {
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->TrainExitHwTrn (TechPtr)) {
+ IDS_OPTION_HOOK (IDS_PHY_DLL_STANDBY_CTRL, NBPtr, &(NBPtr->MemPtr->StdHeader));
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->NonOptimizedSWDQSRecEnTrainingPart1 (TechPtr)) {
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->OptimizedSwDqsRecEnTrainingPart1 (TechPtr)) {
+ MemFInitTableDrive (NBPtr, MTAfterSwRxEnTrn);
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->NonOptimizedSRdWrPosTraining (TechPtr)) {
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->OptimizedSRdWrPosTraining (TechPtr)) {
+ MemFInitTableDrive (NBPtr, MTAfterDqsRwPosTrn);
+ if (!NBPtr->FamilySpecificHook[MemPstateStageChange] (NBPtr, NULL)) {
+ continue;
+ }
+ if (NBPtr->Execute1dMaxRdLatTraining) {
+ do {
+ if (memTrainSequenceDDR3[i].MemTechFeatBlock->MaxRdLatencyTraining (TechPtr)) {
+ MemFInitTableDrive (NBPtr, MTAfterMaxRdLatTrn);
+ }
+ } while (NBPtr->ChangeNbFrequency (NBPtr));
+ } else {
+ memTrainSequenceDDR3[i].MemTechFeatBlock->TrainExitHwTrn (TechPtr);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } while (NBPtr->MemPstateStage == MEMORY_PSTATE_2ND_STAGE);
+ }
+ }
+ }
+ }
+ MemTMarkTrainFail (TechPtr);
+ }
+ return TRUE;
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function executes HW WL at multiple speeds
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @return TRUE - No errors occurred
+ * FALSE - errors occurred
+ */
+
+BOOLEAN
+STATIC
+MemNHwWlPart2Nb (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ BOOLEAN retVal;
+ UINT8 i;
+ retVal = TRUE;
+ i = TechPtr->NBPtr->TrainingSequenceIndex;
+ while ((TechPtr->NBPtr->DCTPtr->Timings.TargetSpeed > TechPtr->NBPtr->DCTPtr->Timings.Speed) && (TechPtr->NBPtr->MemPstateStage != MEMORY_PSTATE_1ST_STAGE)) {
+ TechPtr->PrevSpeed = TechPtr->NBPtr->DCTPtr->Timings.Speed;
+ if (TechPtr->NBPtr->RampUpFrequency (TechPtr->NBPtr)) {
+ TechPtr->TechnologySpecificHook[LrdimmBuf2DramTrain] (TechPtr, NULL);
+ if (!memTrainSequenceDDR3[i].MemTechFeatBlock->HwBasedWLTrainingPart2 (TechPtr)) {
+ retVal = FALSE;
+ break;
+ }
+ MemFInitTableDrive (TechPtr->NBPtr, MTAfterHwWLTrnP2);
+ if (!memTrainSequenceDDR3[i].MemTechFeatBlock->HwBasedDQSReceiverEnableTrainingPart2 (TechPtr)) {
+ retVal = FALSE;
+ break;
+ }
+ MemFInitTableDrive (TechPtr->NBPtr, MTAfterHwRxEnTrnP2);
+ } else {
+ retVal = FALSE;
+ break;
+ }
+ }
+ return retVal;
+}