aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f15/Proc/Recovery
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f15/Proc/Recovery')
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/CPU/cpuRecovery.c103
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/CPU/cpuRecovery.h76
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/HT/htInitRecovery.c168
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/HT/htInitReset.c332
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnc32.c725
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnc32.h109
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnmctc32.c161
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnprotoc32.c61
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnda.c665
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnda.h109
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnmctda.c164
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrndr.c669
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrndr.h109
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrnmctdr.c166
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrndcthy.c75
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnhy.c725
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnhy.h109
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnmcthy.c161
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnprotohy.c61
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrndctor.c341
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnmctor.c145
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnor.c798
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnor.h129
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnprotoor.c61
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/PH/mrnPh.c666
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/PH/mrnPh.h96
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/RB/mrnRb.c665
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/RB/mrnRb.h96
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrn.c189
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrndct.c1577
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrnmct.c296
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrntrain3.c158
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrp.c258
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplribt.c182
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplrnlr.c110
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplrnpr.c110
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpmr0.c177
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpodtpat.c182
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprc10opspd.c92
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprc2ibt.c198
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprtt.c217
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpsao.c187
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrt3.c188
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtrci3.c243
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtsdi3.c361
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtspd3.c325
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtspd3.h131
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrttwl3.c369
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrtthrc.c329
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrtthrcSeedTrain.c315
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrttpos.c114
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrttsrc.c437
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrdef.c128
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrinit.c125
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrm.c288
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrport.h86
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrt3.h120
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mru.asm187
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mru.h140
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mruc.c270
-rw-r--r--src/vendorcode/amd/agesa/f15/Proc/Recovery/recoveryPage.h58
61 files changed, 15892 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/CPU/cpuRecovery.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/CPU/cpuRecovery.c
new file mode 100644
index 0000000000..4593c60228
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/CPU/cpuRecovery.c
@@ -0,0 +1,103 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU Recovery API, and related functions.
+ *
+ * Contains code that implements the CPU Recovery functionality
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: Recovery/CPU
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ **/
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "cpuRecovery.h"
+#include "cpuRegisters.h"
+#include "cpuEarlyInit.h"
+#include "Table.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_CPU_CPURECOVERY_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Performs CPU related initialization at the recovery entry point
+ *
+ * This function processes the MSR and PCI register tables.
+ *
+ * @param[in] CpuRecoveryParams Required input parameters for recovery CPU
+ * initialization.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ *
+ */
+AGESA_STATUS
+AmdCpuRecovery (
+ IN AMD_CPU_RECOVERY_PARAMS *CpuRecoveryParams
+ )
+{
+ SetRegistersFromTables (&CpuRecoveryParams->PlatformConfig, &CpuRecoveryParams->StdHeader);
+ LoadMicrocodePatch (&CpuRecoveryParams->StdHeader);
+ return (AGESA_SUCCESS);
+}
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/CPU/cpuRecovery.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/CPU/cpuRecovery.h
new file mode 100644
index 0000000000..a0fe607d39
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/CPU/cpuRecovery.h
@@ -0,0 +1,76 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU Recovery API, and related function prototypes.
+ *
+ * Contains code that implements the CPU Recovery functionality
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: Recovery/CPU
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+#ifndef _CPU_RECOVERY_H_
+#define _CPU_RECOVERY_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S, S T R U C T U R E S, E N U M S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+// These are P U B L I C functions
+AGESA_STATUS
+AmdCpuRecovery (
+ IN AMD_CPU_RECOVERY_PARAMS *CpuRecoveryParams
+ );
+
+#endif // _CPU_RECOVERY_H_
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/HT/htInitRecovery.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/HT/htInitRecovery.c
new file mode 100644
index 0000000000..2fdce7b26d
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/HT/htInitRecovery.c
@@ -0,0 +1,168 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Init the Socket and Node maps for Recovery mode.
+ *
+ * Create the Socket and Node maps just like normal boot,
+ * except that they only indicate the BSC is present.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ */
+/*
+*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+
+#include "AGESA.h"
+#include "Ids.h"
+#include "Topology.h"
+#include "heapManager.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_HT_HTINITRECOVERY_FILECODE
+
+AGESA_STATUS
+AmdHtInitRecovery (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Get new Socket and Node Maps.
+ *
+ * Put the Socket Die Table and the Node Table in heap with known handles.
+ *
+ * @param[out] SocketDieToNodeMap The Socket, Module to Node info map
+ * @param[out] NodeToSocketDieMap The Node to Socket, Module map.
+ * @param[in] StdHeader Header for library and services.
+ */
+VOID
+STATIC
+NewNodeAndSocketTablesRecovery (
+ OUT SOCKET_DIE_TO_NODE_MAP *SocketDieToNodeMap,
+ OUT NODE_TO_SOCKET_DIE_MAP *NodeToSocketDieMap,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 i;
+ UINT8 j;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ // Allocate heap for the table
+ AllocHeapParams.RequestedBufferSize = (((MAX_SOCKETS) * (MAX_DIES)) * sizeof (SOCKET_DIE_TO_NODE_ITEM));
+ AllocHeapParams.BufferHandle = SOCKET_DIE_MAP_HANDLE;
+ AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
+ if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
+ // HeapAllocateBuffer must set BufferPtr to valid or NULL.
+ *SocketDieToNodeMap = (SOCKET_DIE_TO_NODE_MAP)AllocHeapParams.BufferPtr;
+ ASSERT (SocketDieToNodeMap != NULL);
+ // Initialize shared data structures
+ for (i = 0; i < MAX_SOCKETS; i++) {
+ for (j = 0; j < MAX_DIES; j++) {
+ (**SocketDieToNodeMap)[i][j].Node = HT_LIST_TERMINAL;
+ (**SocketDieToNodeMap)[i][j].LowCore = HT_LIST_TERMINAL;
+ (**SocketDieToNodeMap)[i][j].HighCore = HT_LIST_TERMINAL;
+ }
+ }
+ }
+ // Allocate heap for the table
+ AllocHeapParams.RequestedBufferSize = (MAX_NODES * sizeof (NODE_TO_SOCKET_DIE_ITEM));
+ AllocHeapParams.BufferHandle = NODE_ID_MAP_HANDLE;
+ AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
+ if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
+ // HeapAllocateBuffer must set BufferPtr to valid or NULL.
+ *NodeToSocketDieMap = (NODE_TO_SOCKET_DIE_MAP)AllocHeapParams.BufferPtr;
+ ASSERT (NodeToSocketDieMap != NULL);
+ // Initialize shared data structures
+ for (i = 0; i < MAX_NODES; i++) {
+ (**NodeToSocketDieMap)[i].Socket = HT_LIST_TERMINAL;
+ (**NodeToSocketDieMap)[i].Die = HT_LIST_TERMINAL;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Initialize the Node and Socket maps for an AP Core.
+ *
+ * In each core's local heap, create a Node to Socket map and a Socket/Module to Node map.
+ * The mapping is filled in by reading the AP Mailboxes from PCI config on each node.
+ *
+ * @param[in] StdHeader global state, input data
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ */
+AGESA_STATUS
+AmdHtInitRecovery (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ AP_MAILBOXES NodeApMailBox;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+ SOCKET_DIE_TO_NODE_MAP SocketDieToNodeMap = NULL;
+ NODE_TO_SOCKET_DIE_MAP NodeToSocketDieMap = NULL;
+
+ NodeApMailBox.ApMailInfo.Info = 0;
+ NodeApMailBox.ApMailExtInfo.Info = 0;
+
+ // Allocate heap for caching the mailboxes
+ AllocHeapParams.RequestedBufferSize = sizeof (AP_MAILBOXES);
+ AllocHeapParams.BufferHandle = LOCAL_AP_MAIL_BOX_CACHE_HANDLE;
+ AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
+ if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
+ *(AP_MAILBOXES *)AllocHeapParams.BufferPtr = NodeApMailBox;
+ }
+
+ NewNodeAndSocketTablesRecovery (&SocketDieToNodeMap, &NodeToSocketDieMap, StdHeader);
+ // HeapAllocateBuffer must set BufferPtr to valid or NULL, so the checks below are ok.
+
+ // There is no option to not have socket - node maps, if they aren't allocated that is a fatal bug.
+ ASSERT (SocketDieToNodeMap != NULL);
+ ASSERT (NodeToSocketDieMap != NULL);
+
+ (*SocketDieToNodeMap)[0][0].Node = 0;
+ (*SocketDieToNodeMap)[0][0].LowCore = 0;
+ (*SocketDieToNodeMap)[0][0].HighCore = 0;
+
+ // We lie about being Socket 0 and Module 0 always, it isn't necessarily true.
+ (*NodeToSocketDieMap)[0].Socket = (UINT8)0;
+ (*NodeToSocketDieMap)[0].Die = (UINT8)0;
+
+ return AGESA_SUCCESS;
+}
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/HT/htInitReset.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/HT/htInitReset.c
new file mode 100644
index 0000000000..9e8b4efdb1
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/HT/htInitReset.c
@@ -0,0 +1,332 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Recovery HT, a Hypertransport init for Boot Blocks. For normal
+ * boots, run Recovery HT first in boot block, then run full HT init
+ * in the system BIOS. Recovery HT moves the devices on the chain with
+ * the southbridge to their assigned device IDS, so that all their PCI
+ * Config space is accessible.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: Recovery HyperTransport
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ */
+/*
+ *****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "AdvancedApi.h"
+#include "GeneralServices.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_HT_HTINITRESET_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_NODES 1
+#define MAX_LINKS 8
+
+extern CONST AMD_HT_RESET_INTERFACE HtOptionResetDefaults;
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/**
+ * Our global state data structure.
+ *
+ * Keep track of inputs and outputs, and keep any working state.
+ */
+typedef struct {
+ AMD_HT_RESET_INTERFACE *HtBlock; ///< The interface
+ AGESA_STATUS Status; ///< Remember the highest severity status event
+ VOID *ConfigHandle; ///< Config Pointer, opaque handle for passing to lib
+} HTR_STATE_DATA;
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/***************************************************************************
+ *** FAMILY/NORTHBRIDGE SPECIFIC FUNCTIONS ***
+ ***************************************************************************/
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Enable Routing Tables.
+ *
+ * Turns routing tables on for a node zero.
+ *
+ * @param[in] State Our State
+ */
+
+VOID
+STATIC
+HtrEnableRoutingTables (
+ IN HTR_STATE_DATA *State
+ )
+{
+ PCI_ADDR Reg;
+ UINT32 Temp;
+ Temp = 0;
+ Reg.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0x6C);
+ LibAmdPciWriteBits (Reg, 0, 0, &Temp, State->ConfigHandle);
+}
+
+/***************************************************************************
+ *** Non-coherent init code ***
+ *** Algorithms ***
+ ***************************************************************************/
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Process the SouthBridge Link.
+ *
+ * Process a non-coherent link, and setting the device ID for all devices found.
+ *
+ * @param[in] State Our State, Inputs
+ */
+VOID
+STATIC
+HtrProcessLink (
+ IN HTR_STATE_DATA *State
+ )
+{
+ UINT32 CurrentBUID;
+ UINT32 Temp;
+ UINT32 UnitIDcnt;
+ PCI_ADDR CurrentPtr;
+ UINT8 Depth;
+ BUID_SWAP_LIST *SwapPtr;
+ PCI_ADDR Link1ControlRegister;
+ BOOLEAN IsCaveDevice;
+
+ // No PCI init to run, everything has to be on Bus zero. This makes fewer
+ // northbridge dependencies.
+ //
+ // Assign BUIDs so that config space for all devices is visible.
+ //
+ if (State->HtBlock->ManualBuidSwapList != NULL) {
+ // Manual non-coherent BUID assignment
+ // Assign BUID's per manual override
+ //
+ SwapPtr = &(State->HtBlock->ManualBuidSwapList->SwapList);
+ Depth = 0;
+ while (SwapPtr->Swaps[Depth].FromId != 0xFF) {
+ CurrentPtr.AddressValue = MAKE_SBDFO (0, 0, SwapPtr->Swaps[Depth].FromId, 0, 0);
+
+ do {
+ LibAmdPciFindNextCap (&CurrentPtr, State->ConfigHandle);
+ ASSERT (CurrentPtr.AddressValue != ILLEGAL_SBDFO);
+ LibAmdPciRead (AccessWidth32, CurrentPtr, &Temp, State->ConfigHandle);
+ } while ((Temp & (UINT32)0xE00000FF) != (UINT32)0x00000008); // HyperTransport Slave Capability
+
+ CurrentBUID = SwapPtr->Swaps[Depth].ToId;
+ // Set the device's BUID
+ LibAmdPciWriteBits (CurrentPtr, 20, 16, &CurrentBUID, State->ConfigHandle);
+ Depth++;
+ }
+ } else {
+ // Automatic non-coherent device detection
+ Depth = 0;
+ CurrentBUID = 1;
+ for (;;) {
+ CurrentPtr.AddressValue = MAKE_SBDFO (0, 0, 0, 0, 0);
+
+ LibAmdPciRead (AccessWidth32, CurrentPtr, &Temp, State->ConfigHandle);
+ if (Temp == (UINT32)0xFFFFFFFF) {
+ // No device found at currentPtr
+ break;
+ }
+
+ // HyperTransport Slave Capability
+ do {
+ LibAmdPciFindNextCap (&CurrentPtr, State->ConfigHandle);
+ if (CurrentPtr.AddressValue == ILLEGAL_SBDFO) {
+ // There is a device at currentPtr, but it isn't an HT device.
+ return;
+ }
+ LibAmdPciRead (AccessWidth32, CurrentPtr, &Temp, State->ConfigHandle);
+ } while ((Temp & (UINT32)0xE00000FF) != (UINT32)0x00000008); // HyperTransport Slave Capability
+
+ // Get the device's Unit ID Count.
+ LibAmdPciReadBits (CurrentPtr, 25, 21, &UnitIDcnt, State->ConfigHandle);
+ if ((UnitIDcnt + CurrentBUID) > 24) {
+ // An error handler for the case where we run out of BUID's on a chain
+ State->Status = AGESA_ERROR;
+ ASSERT (FALSE);
+ return;
+ }
+ // While we are still certain we are accessing this device, remember if it is a cave device.
+ // This is found by reading EOC from the Link 1 Control Register.
+ Link1ControlRegister = CurrentPtr;
+ Link1ControlRegister.Address.Register += 8;
+ LibAmdPciReadBits (Link1ControlRegister, 6, 6, &Temp, State->ConfigHandle);
+ IsCaveDevice = ((Temp == 0) ? FALSE : TRUE);
+
+ // Set the device's BUID
+ IDS_HDT_CONSOLE (HT_TRACE, "Device found at depth=%d.\n", Depth);
+ LibAmdPciWriteBits (CurrentPtr, 20, 16, &CurrentBUID, State->ConfigHandle);
+
+ CurrentPtr.Address.Device = CurrentBUID;
+ // Get the device's BUID
+ LibAmdPciReadBits (CurrentPtr, 20, 16, &Temp, State->ConfigHandle);
+ if (Temp != CurrentBUID) {
+ if ((Depth == 0) && IsCaveDevice) {
+ // If the chain only consists of a single cave device, that device may have retained zero
+ // for it's BUID.
+ CurrentPtr.Address.Device = 0;
+ LibAmdPciReadBits (CurrentPtr, 20, 16, &Temp, State->ConfigHandle);
+ if (Temp == 0) {
+ // Per HyperTransport specification, devices not accepting BUID reassignment hardwire BUID to zero.
+ Depth++;
+ // Success!
+ IDS_HDT_CONSOLE (HT_TRACE, "Compliant Cave at BUID=0.\n");
+ break;
+ } else if (Temp == CurrentBUID) {
+ // and then, there are the other kind of devices ....
+ // Restore the writable BUID field (which contains the value we just wrote) to zero.
+ Temp = 0;
+ LibAmdPciWriteBits (CurrentPtr, 20, 16, &Temp, State->ConfigHandle);
+ Depth++;
+ // Success!
+ IDS_HDT_CONSOLE (HT_TRACE, "Cave left at BUID=0.\n");
+ break;
+ }
+ }
+ // An error handler for this critical error
+ State->Status = AGESA_ERROR;
+ ASSERT (FALSE);
+ return;
+ }
+
+ IDS_HDT_CONSOLE (HT_TRACE, "Compliant Device assigned at BUID=%d.\n", CurrentBUID);
+ Depth++;
+ CurrentBUID += UnitIDcnt;
+ }
+ // Provide information on automatic device results
+ State->HtBlock->Depth = Depth;
+ }
+}
+
+/***************************************************************************
+ *** HT Reset Initialize ***
+ ***************************************************************************/
+
+/**
+ * A constructor for the HyperTransport input structure.
+ *
+ * Sets inputs to valid, basic level, defaults.
+ *
+ * @param[in] StdHeader Config handle
+ * @param[in,out] AmdHtResetInterface HT Interface structure to initialize.
+ *
+ * @retval AGESA_SUCCESS Constructors are not allowed to fail
+*/
+AGESA_STATUS
+AmdHtResetConstructor (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_HT_RESET_INTERFACE *AmdHtResetInterface
+ )
+{
+ AmdHtResetInterface->ManualBuidSwapList = HtOptionResetDefaults.ManualBuidSwapList;
+ return AGESA_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Initialize HT for Reset, Boot Blocks.
+ *
+ * This is the top level external interface for Hypertransport Reset Initialization.
+ * Create our initial internal state and initialize the non-coherent chain to the
+ * southbridge. This interface must be executed by both normal and recovery boot paths.
+ *
+ * @param[in] StdHeader Interface structure
+ * @param[in] AmdHtResetInterface our interface and inputs
+ *
+ * @retval AGESA_SUCCESS Successful init
+ * @retval AGESA_ERROR Device Error, BUID max exceed error.
+ *
+ */
+AGESA_STATUS
+AmdHtInitReset (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_HT_RESET_INTERFACE *AmdHtResetInterface
+ )
+{
+ HTR_STATE_DATA State;
+ AGESA_STATUS IgnoredStatus;
+
+ State.Status = AGESA_SUCCESS;
+ if (IsBsp (StdHeader, &IgnoredStatus)) {
+ State.ConfigHandle = (AMD_CONFIG_PARAMS *)StdHeader;
+ State.HtBlock = AmdHtResetInterface;
+ HtrEnableRoutingTables (&State);
+
+ HtrProcessLink (&State);
+ }
+ return State.Status;
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnc32.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnc32.c
new file mode 100644
index 0000000000..0532373d15
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnc32.c
@@ -0,0 +1,725 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnc32.c
+ *
+ * Common Northbridge functions for C32 Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 48317 $ @e \$Date: 2011-03-07 10:38:14 -0700 (Mon, 07 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrnc32.h"
+#include "heapManager.h"
+#include "AdvancedApi.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_C32_MRNC32_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_DIES_PER_SOCKET 2
+#define MAX_DCTS_PER_DIE 2
+#define SPLIT_CHANNEL 0x20000000
+#define CHANNEL_SELECT 0x10000000
+#define MAX_DELAYS 9 /* 8 data bytes + 1 ECC byte */
+#define MAX_DIMMS 4 /* 4 DIMMs per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableC32 (
+ IN OUT TSEFO *NBRegTable
+ );
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ );
+
+UINT32
+STATIC
+MemRecNcmnGetSetTrainDlyC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ );
+
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ );
+
+VOID
+STATIC
+MemRecNSwitchNodeC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 NodeID
+ );
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+STATIC CONST UINT32 RecModeDefRegArrayC32[] = {
+ BFDramControlReg, 0x320C2A06,
+ BFDramBankAddrReg, 0x00001111,
+ BFDramMRSReg, 0x000400A4,
+ BFDramTimingLoReg, 0x000A0092,
+ BFDramTimingHiReg, 0xB6D218FF,
+ BFDramConfigLoReg, 0x00000000,
+ BFDramConfigHiReg, 0x1F48010B,
+ NULL
+};
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] NodeID - Node ID for this NB block
+ *
+ * @return TRUE - This node is a C32 and this NB block has been initialized
+ * @return FALSE - This node is not a C32
+ */
+
+BOOLEAN
+MemRecConstructNBBlockC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 i;
+ UINT8 Dct;
+ UINT8 Channel;
+ DIE_STRUCT *MCTPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemRecNIsIdSupportedC32 (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
+ return FALSE;
+ }
+
+ //
+ // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
+ //
+ MCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_C32 * (
+ sizeof (DCT_STRUCT) + (
+ MAX_CHANNELS_PER_DCT_C32 * (
+ sizeof (CH_DEF_STRUCT) + (
+ MAX_DIMMS * MAX_DELAYS * NUMBER_OF_DELAY_TABLES
+ )
+ )
+ )
+ ) + (sizeof (TSEFO) * BFEndOfList);
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0);
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
+ return FALSE;
+ }
+
+ MemPtr->DieCount = MAX_DIES_PER_SOCKET;
+ MCTPtr->DctCount = MAX_DCTS_PER_NODE_C32;
+ MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ MemPtr->DiesPerSystem[NodeID + 1].DctCount = MAX_DCTS_PER_NODE_C32;
+ MemPtr->DiesPerSystem[NodeID + 1].DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_C32 * sizeof (DCT_STRUCT);
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_C32; Dct++) {
+ MCTPtr->DctData[Dct].Dct = Dct;
+ MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_C32;
+ MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[0].ChannelID = (MCTPtr->DieId * 2) + Dct;
+ AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_C32 * sizeof (CH_DEF_STRUCT);
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_C32; Channel++) {
+ MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = (UINT16 *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS) * 2;
+ MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[Channel].Dct = Dct;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS);
+ }
+ }
+
+ //
+ // Initialize NB block's variables
+ //
+ NBPtr->NBRegTable = (TSEFO *) AllocHeapParams.BufferPtr;
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->RefPtr = MemPtr->ParameterListPtr;
+ NBPtr->MCTPtr = MCTPtr;
+ NBPtr->AllNodeMCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ NBPtr->SPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+ NBPtr->AllNodeSPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+
+ NBPtr->DctCachePtr = NBPtr->DctCache;
+
+ MemRecNInitNBRegTableC32 (NBPtr->NBRegTable);
+ NBPtr->Dct = 0;
+ NBPtr->Channel = 0;
+ NBPtr->VarMtrrHiMsk = MemRecGetVarMtrrHiMsk (&(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+
+ LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &NBPtr->MemPtr->StdHeader);
+ LibAmdMemFill (NBPtr->IsSupported, FALSE, sizeof (NBPtr->IsSupported), &NBPtr->MemPtr->StdHeader);
+ for (i = 0; i < NumberOfHooks; i++) {
+ NBPtr->FamilySpecificHook[i] = (BOOLEAN (*) (MEM_NB_BLOCK *, VOID *)) MemRecDefTrue;
+ }
+
+ NBPtr->InitRecovery = MemRecNMemInitNb;
+
+ NBPtr->RecModeDefRegArray = RecModeDefRegArrayC32;
+
+ NBPtr->SwitchNodeRec = MemRecNSwitchNodeC32;
+ NBPtr->SwitchDCT = MemRecNSwitchDctC32;
+ NBPtr->SwitchChannel = MemRecNSwitchChannelC32;
+ NBPtr->SetMaxLatency = MemRecNSetMaxLatencyNb;
+ NBPtr->GetSysAddrRec = MemRecNGetMCTSysAddrNb;
+ NBPtr->SendMrsCmd = MemRecNSendMrsCmdNb;
+ NBPtr->sendZQCmd = MemRecNSendZQCmdNb;
+ NBPtr->SetDramOdtRec = MemRecNSetDramOdtNb;
+
+ NBPtr->GetBitField = MemRecNGetBitFieldNb;
+ NBPtr->SetBitField = MemRecNSetBitFieldNb;
+ NBPtr->GetTrainDly = MemRecNGetTrainDlyNb;
+ NBPtr->SetTrainDly = MemRecNSetTrainDlyNb;
+
+ NBPtr->MemRecNCmnGetSetFieldNb = MemRecNCmnGetSetFieldC32;
+ NBPtr->MemRecNcmnGetSetTrainDlyNb = MemRecNcmnGetSetTrainDlyC32;
+ NBPtr->MemRecNSwitchDctNb = MemRecNSwitchDctC32;
+ NBPtr->TrainingFlow = MemNRecTrainingFlowNb;
+ NBPtr->MemRecNInitializeMctNb = MemRecNInitializeMctC32;
+ NBPtr->MemRecNFinalizeMctNb = MemRecNFinalizeMctC32;
+ NBPtr->IsSupported[DramModeAfterDimmPres] = TRUE;
+ MemRecNSwitchDctC32 (NBPtr, 0);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the current die to work on.
+ * Should be called before accessing a certain die
+ * All data structures will be updated to point to the current node
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] NodeID - ID of the target die
+ *
+ */
+
+VOID
+STATIC
+MemRecNSwitchNodeC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 NodeID
+ )
+{
+ NBPtr->MCTPtr = &(NBPtr->AllNodeMCTPtr[NodeID]);
+ NBPtr->Node = NodeID;
+ NBPtr->MCTPtr->NodeId = NodeID;
+ MemRecNSwitchDctC32 (NBPtr, NBPtr->Dct);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchDctC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ )
+{
+ NBPtr->Dct = Dct & 1;
+ NBPtr->SPDPtr = &(NBPtr->AllNodeSPDPtr[(NBPtr->MCTPtr->NodeId * MAX_DCTS_PER_DIE + Dct) * MAX_DIMMS_PER_CHANNEL]);
+ NBPtr->DCTPtr = &(NBPtr->MCTPtr->DctData[NBPtr->Dct]);
+
+ MemRecNSwitchChannelC32 (NBPtr, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchChannelC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ )
+{
+ NBPtr->Channel = 0;
+ NBPtr->ChannelPtr = &(NBPtr->DCTPtr->ChData[0]);
+}
+
+/*----------------------------------------------------------------------------
+ * 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
+STATIC
+MemRecNcmnGetSetTrainDlyC32 (
+ 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);
+
+ 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) != 0) {
+ // if byte 4,5,6,7
+ index += 0x10;
+ }
+ if ((Byte & 0x02) != 0) {
+ // 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:
+ Field &= ~ 0x0001;
+ case AccessWrDatDly:
+ index += (DIMM * 0x100);
+ if (Nibble != 0) {
+ if (Rank != 0) {
+ index += 0xA0;
+ } else {
+ index += 0x70;
+ }
+ } else if (Rank != 0) {
+ 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;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (IsSet != 0) {
+ if (TrnDly == AccessPhRecDly) {
+ value = NBPtr->DctCachePtr->PhRecReg[index & 0x03];
+ }
+
+ value = ((UINT32)Field << offset) | (value & (~((UINT32)0xFF << offset)));
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, value);
+ address |= DCT_ACCESS_WRITE;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[index & 0x03] = value;
+ }
+ } else {
+ value = (value >> offset) & 0xFF;
+ }
+
+ return value;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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 - Name of Field to be set
+ * @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
+STATIC
+MemRecNCmnGetSetFieldC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ SBDFO Address;
+ PCI_ADDR PciAddr;
+ UINT8 Type;
+ UINT32 Value;
+ UINT32 Highbit;
+ UINT32 Lowbit;
+ UINT32 Mask;
+
+ Value = 0;
+ if (FieldName < BFEndOfList) {
+ Address = NBPtr->NBRegTable[FieldName];
+ if (Address != 0) {
+ Lowbit = TSEFO_END (Address);
+ Highbit = TSEFO_START (Address);
+ Type = TSEFO_TYPE (Address);
+
+ // If Fn2 and DCT1 selected, set Address to be 1xx
+ if (((Address & 0xF000) == 0x2000) && (NBPtr->Dct != 0)) {
+ Address |= 0x0100;
+ }
+ if ((Address >> 29) == ((DCT_PHY_ACCESS << 1) | 1)) {
+ // Special DCT Phy access
+ Address &= 0x0FFFFFFF;
+ Lowbit = 0;
+ Highbit = 16;
+ } else {
+ // Normal DCT Phy access
+ Address = TSEFO_OFFSET (Address);
+ }
+
+
+ if (Type == NB_ACCESS) {
+ // Address |= (((UINT32) (24 + 0)) << 15);
+ PciAddr.AddressValue = Address;
+ // Fix for MCM
+ PciAddr.Address.Device = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Device;
+ PciAddr.Address.Bus = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Bus;
+ PciAddr.Address.Segment = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Segment;
+ Address = PciAddr.AddressValue;
+ LibAmdPciRead (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+ } else {
+ IDS_ERROR_TRAP;
+ }
+
+ if (IsSet != 0) {
+ // 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;
+
+ if (Type == NB_ACCESS) {
+ PciAddr.AddressValue = Address;
+ LibAmdPciWrite (AccessWidth32, PciAddr , &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ } else {
+ IDS_ERROR_TRAP;
+ }
+ } 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);
+ }
+ }
+ }
+ } else {
+ IDS_ERROR_TRAP; // Invalid bit field index
+ }
+ return Value;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes bit field translation table
+ *
+* @param[in,out] *NBRegTable - Pointer to the NB Table *
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableC32 (
+ IN OUT TSEFO *NBRegTable
+ )
+{
+ UINT16 i;
+ for (i = 0; i <= BFEndOfList; i++) {
+ NBRegTable[i] = 0;
+ }
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x00), 31, 0, BFDevVendorIDReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x60), 2, 0, BFNodeID);
+
+ 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 (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), 31, 0, BFDramControlReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 0, BFDramInitRegReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x80), 31, 0, BFDramBankAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 31, 0, BFDramMRSReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 9, 7, BFDramTerm);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 11, 10, BFDramTermDyn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x88), 31, 0, BFDramTimingLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 31, 0, BFDramTimingHiReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 31, 0, BFDramConfigLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31, 0, BFDramConfigHiReg);
+ 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, 0x98), 31, 31, BFDctAccessDone);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (3, 0xD4), 4, 0, BFNbFid);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 18, 18, BFDqsRcvEnTrain);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 31, 22, BFMaxLatency);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 15, 0, BFMrsAddress);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 18, 16, BFMrsBank);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 22, 20, BFMrsChipSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 26, 26, BFSendMrsCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 27, 27, BFDeassertMemRstX);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 28, 28, BFAssertCke);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 29, 29, BFSendZQCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 30, 30, BFSendCtrlWord);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 31, BFEnDramInit);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 7, 7, BFLevel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 12, 12, BFMrsQoff);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 18, 18, BFDisAutoRefresh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 0, 0, BFInitDram);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 16, 16, BFUnBuffDimm);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 8, 8, BFDdr3Mode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 9, 9, BFLegacyBiosMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 11, 10, BFZqcsInterval);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 14, 14, BFDisDramInterface);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 5, 5, BFSubMemclkRegDly);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 6, 6, BFOdtSwizzle);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 15, 8, BFCtrlWordCS);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 8, 8, BFDramEnabled);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 31, 0, BFDctSelBaseAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 31, 0, BFDctSelBaseOffsetReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 31, 0, BFMctCfgHiReg);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 31, 0, BFODCControl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x04, 31, 0, BFAddrTmgControl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 0, 0, BFWrtLvTrEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 1, 1, BFWrtLvTrMode);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 5, 4, BFTrDimmSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 11, 8, BFWrLvOdt);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 12, 12, BFWrLvOdtEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 30, 30, BFDisAutoComp);
+
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ * MemRecNIsIdSupportedC32
+ * 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 C32.
+ * @return FALSE - This node is not a C32.
+ *
+ */
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ )
+{
+ if ((LogicalIdPtr->Revision & AMD_F10_C32_ALL) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnc32.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnc32.h
new file mode 100644
index 0000000000..2a2f277a20
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnc32.h
@@ -0,0 +1,109 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnc32.h
+ *
+ * Northbridge C32 Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MRNC32_H_
+#define _MRNC32_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_DCTS_PER_NODE_C32 2
+#define MAX_CHANNELS_PER_DCT_C32 1
+
+#define _4GB_RJ8 ((UINT32)4 << (30 - 8))
+#define MTRR_VALID 11
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemRecConstructNBBlockC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ );
+
+VOID
+MemRecNSwitchDctC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ );
+
+VOID
+MemRecNSwitchChannelC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ );
+
+VOID
+MemRecNFinalizeMctC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemRecNInitializeMctC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+#endif /* _MRNC32_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnmctc32.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnmctc32.c
new file mode 100644
index 0000000000..0216cd81c5
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnmctc32.c
@@ -0,0 +1,161 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnmctc32.c
+ *
+ * Northbridge C32 MCT supporting functions Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrnc32.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_C32_MRNMCTC32_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets final values in BUCFG and BUCFG2
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNFinalizeMctC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_DATA_STRUCT *MemPtr;
+ S_UINT64 SMsr;
+
+ MemPtr = NBPtr->MemPtr;
+
+ // Recommended settings for F2x11C
+ MemRecNSetBitFieldNb (NBPtr, BFMctCfgHiReg, 0x2CE00F60);
+
+ LibAmdMsrRead (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ if (!NBPtr->ClToNbFlag) {
+ SMsr.lo &= ~((UINT32) 1 << 15); // ClLinesToNbDis
+ }
+ LibAmdMsrWrite (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ LibAmdMsrRead (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.hi &= ~((UINT32) 1 << (48 - 32)); // WbEnhWsbDis
+ LibAmdMsrWrite (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets initial values in BUCFG and BUCFG2
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNInitializeMctC32 (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_DATA_STRUCT *MemPtr;
+ S_UINT64 SMsr;
+
+ MemPtr = NBPtr->MemPtr;
+
+ LibAmdMsrRead (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ if (SMsr.lo & ((UINT32) 1 << 15)) {
+ NBPtr->ClToNbFlag = TRUE;
+ }
+ SMsr.lo |= (UINT32) 1 << 15; // ClLinesToNbDis
+ LibAmdMsrWrite (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ LibAmdMsrRead (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.hi |= (UINT32) 1 << (48 - 32); // WbEnhWsbDis
+ LibAmdMsrWrite (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnprotoc32.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnprotoc32.c
new file mode 100644
index 0000000000..f60b28bfee
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/C32/mrnprotoc32.c
@@ -0,0 +1,61 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnprotoc32.c
+ *
+ * Northbridge support functions for Errata and early samples Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+
+
+#include "AGESA.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_C32_MRNPROTOC32_FILECODE
+/*
+ *-----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnda.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnda.c
new file mode 100644
index 0000000000..0b8c0761bb
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnda.c
@@ -0,0 +1,665 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnda.c
+ *
+ * Common Northbridge functions for Ridgeback Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 48317 $ @e \$Date: 2011-03-07 10:38:14 -0700 (Mon, 07 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrnda.h"
+#include "heapManager.h"
+#include "AdvancedApi.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_DA_MRNDA_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#define SPLIT_CHANNEL 0x20000000
+#define CHANNEL_SELECT 0x10000000
+#define MAX_DELAYS 9 /* 8 data bytes + 1 ECC byte */
+#define MAX_DIMMS 4 /* 4 DIMMs per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableDA (
+ IN OUT TSEFO *NBRegTable
+ );
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ );
+
+UINT32
+STATIC
+MemRecNcmnGetSetTrainDlyDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ );
+
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+STATIC CONST UINT32 RecModeDefRegArrayDA[] = {
+ BFDramControlReg, 0x320C2A06,
+ BFDramBankAddrReg, 0x00001111,
+ BFDramMRSReg, 0x000400A4,
+ BFDramTimingLoReg, 0x000A0092,
+ BFDramTimingHiReg, 0xB6D218FF,
+ BFDramConfigLoReg, 0x00000000,
+ BFDramConfigHiReg, 0x1F48010B,
+ NULL
+};
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] NodeID - Node ID for this NB block
+ *
+ * @return TRUE - This node is a RB and this NB block has been initialized
+ * @return FALSE - This node is not a RB
+ */
+
+BOOLEAN
+MemRecConstructNBBlockDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 i;
+ UINT8 Dct;
+ UINT8 Channel;
+ DIE_STRUCT *MCTPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemRecNIsIdSupportedDA (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
+ return FALSE;
+ }
+
+ //
+ // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
+ //
+ MCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_DA * (
+ sizeof (DCT_STRUCT) + (
+ MAX_CHANNELS_PER_DCT_DA * (
+ sizeof (CH_DEF_STRUCT) + (
+ MAX_DIMMS * MAX_DELAYS * NUMBER_OF_DELAY_TABLES
+ )
+ )
+ )
+ ) + (sizeof (TSEFO) * BFEndOfList);
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0);
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
+ return FALSE;
+ }
+
+ MemPtr->DieCount = 1;
+ MCTPtr->DctCount = MAX_DCTS_PER_NODE_DA;
+ MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_DA * sizeof (DCT_STRUCT);
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_DA; Dct++) {
+ MCTPtr->DctData[Dct].Dct = Dct;
+ MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_DA;
+ MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[0].ChannelID = Dct;
+ AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_DA * sizeof (CH_DEF_STRUCT);
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_DA; Channel++) {
+ MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = (UINT16 *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS) * 2;
+ MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[Channel].Dct = Dct;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS);
+ }
+ }
+
+ //
+ // Initialize NB block's variables
+ //
+ NBPtr->NBRegTable = (TSEFO *) AllocHeapParams.BufferPtr;
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->RefPtr = MemPtr->ParameterListPtr;
+ NBPtr->MCTPtr = MCTPtr;
+ NBPtr->SPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+ NBPtr->AllNodeSPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+
+ NBPtr->DctCachePtr = NBPtr->DctCache;
+
+ MemRecNInitNBRegTableDA (NBPtr->NBRegTable);
+ NBPtr->Dct = 0;
+ NBPtr->Channel = 0;
+ NBPtr->VarMtrrHiMsk = MemRecGetVarMtrrHiMsk (&(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+
+ LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &NBPtr->MemPtr->StdHeader);
+ LibAmdMemFill (NBPtr->IsSupported, FALSE, sizeof (NBPtr->IsSupported), &NBPtr->MemPtr->StdHeader);
+ for (i = 0; i < NumberOfHooks; i++) {
+ NBPtr->FamilySpecificHook[i] = (BOOLEAN (*) (MEM_NB_BLOCK *, VOID *)) MemRecDefTrue;
+ }
+
+ NBPtr->InitRecovery = MemRecNMemInitNb;
+
+ NBPtr->RecModeDefRegArray = RecModeDefRegArrayDA;
+
+ NBPtr->SwitchNodeRec = (VOID (*) (MEM_NB_BLOCK *, UINT8)) MemRecDefRet;
+ NBPtr->SwitchDCT = MemRecNSwitchDctDA;
+ NBPtr->SwitchChannel = MemRecNSwitchChannelDA;
+ NBPtr->SetMaxLatency = MemRecNSetMaxLatencyNb;
+ NBPtr->GetSysAddrRec = MemRecNGetMCTSysAddrNb;
+ NBPtr->SendMrsCmd = MemRecNSendMrsCmdNb;
+ NBPtr->sendZQCmd = MemRecNSendZQCmdNb;
+ NBPtr->SetDramOdtRec = MemRecNSetDramOdtNb;
+
+ NBPtr->GetBitField = MemRecNGetBitFieldNb;
+ NBPtr->SetBitField = MemRecNSetBitFieldNb;
+ NBPtr->GetTrainDly = MemRecNGetTrainDlyNb;
+ NBPtr->SetTrainDly = MemRecNSetTrainDlyNb;
+ NBPtr->MemRecNCmnGetSetFieldNb = MemRecNCmnGetSetFieldDA;
+ NBPtr->MemRecNcmnGetSetTrainDlyNb = MemRecNcmnGetSetTrainDlyDA;
+ NBPtr->MemRecNSwitchDctNb = MemRecNSwitchDctDA;
+ NBPtr->TrainingFlow = MemNRecTrainingFlowNb;
+ NBPtr->MemRecNInitializeMctNb = MemRecNInitializeMctDA;
+ NBPtr->MemRecNFinalizeMctNb = MemRecNFinalizeMctDA;
+ NBPtr->IsSupported[DramModeBeforeDimmPres] = TRUE;
+ NBPtr->IsSupported[CheckClearOnDimmMirror] = TRUE;
+ MemRecNSwitchDctDA (NBPtr, 0);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchDctDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ )
+{
+ NBPtr->Dct = Dct & 1;
+ NBPtr->SPDPtr = &(NBPtr->AllNodeSPDPtr[Dct * MAX_DIMMS_PER_CHANNEL]);
+ NBPtr->DCTPtr = &(NBPtr->MCTPtr->DctData[NBPtr->Dct]);
+
+ MemRecNSwitchChannelDA (NBPtr, NBPtr->Channel);
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchChannelDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ )
+{
+ NBPtr->Channel = Channel & 1;
+ NBPtr->ChannelPtr = &(NBPtr->DCTPtr->ChData[NBPtr->Channel]);
+}
+/*----------------------------------------------------------------------------
+ * 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
+STATIC
+MemRecNcmnGetSetTrainDlyDA (
+ 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 < 4);
+ ASSERT (Byte <= 8);
+
+ 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:
+ Field &= ~ 0x0001;
+ 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;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (IsSet) {
+ if (TrnDly == AccessPhRecDly) {
+ Value = NBPtr->DctCachePtr->PhRecReg[Index & 0x03];
+ }
+
+ Value = ((UINT32)Field << Offset) | (Value & (~((UINT32)0xFF << Offset)));
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[Index & 0x03] = Value;
+ }
+ } else {
+ Value = (Value >> Offset) & 0xFF;
+ }
+
+ return Value;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] IsSet - Indicates if the function will set or get
+ * @param[in] FieldName - Name of field to be set
+ * @param[in] Field - Value to be programmed
+ *
+ * @return value read, if the function is used as a "get"
+ */
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ SBDFO Address;
+ PCI_ADDR PciAddr;
+ UINT8 Type;
+ UINT32 Value;
+ UINT32 Highbit;
+ UINT32 Lowbit;
+ UINT32 Mask;
+
+ Value = 0;
+ if (FieldName < BFEndOfList) {
+ Address = NBPtr->NBRegTable[FieldName];
+ if (Address) {
+ Lowbit = TSEFO_END (Address);
+ Highbit = TSEFO_START (Address);
+ Type = TSEFO_TYPE (Address);
+
+ // If Fn2 and DCT1 selected, set Address to be 1xx
+ if (((Address & 0xF000) == 0x2000) && NBPtr->Dct) {
+ Address |= 0x0100;
+ }
+ if ((Address >> 29) == ((DCT_PHY_ACCESS << 1) | 1)) {
+ // Special DCT Phy access
+ Address &= 0x0FFFFFFF;
+ Lowbit = 0;
+ Highbit = 16;
+ } else {
+ // Normal DCT Phy access
+ Address = TSEFO_OFFSET (Address);
+ }
+
+
+ if (Type == NB_ACCESS) {
+ Address |= (((UINT32) (24 + 0)) << 15);
+ PciAddr.AddressValue = Address;
+ LibAmdPciRead (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+ } else {
+ IDS_ERROR_TRAP;
+ }
+
+ 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;
+
+ if (Type == NB_ACCESS) {
+ PciAddr.AddressValue = Address;
+ LibAmdPciWrite (AccessWidth32, PciAddr , &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ } else {
+ IDS_ERROR_TRAP;
+ }
+ } 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);
+ }
+ }
+ }
+ } else {
+ IDS_ERROR_TRAP; // Invalid bit field index
+ }
+ return Value;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes bit field translation table
+ *
+ * @param[in,out] *NBRegTable - Pointer to the NB Table *
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableDA (
+ IN OUT TSEFO *NBRegTable
+ )
+{
+ UINT16 i;
+ for (i = 0; i <= BFEndOfList; i++) {
+ NBRegTable[i] = 0;
+ }
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x00), 31, 0, BFDevVendorIDReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x60), 2, 0, BFNodeID);
+
+ 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 (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), 31, 0, BFDramControlReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 0, BFDramInitRegReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x80), 31, 0, BFDramBankAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 31, 0, BFDramMRSReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 9, 7, BFDramTerm);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 11, 10, BFDramTermDyn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x88), 31, 0, BFDramTimingLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 31, 0, BFDramTimingHiReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 31, 0, BFDramConfigLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31, 0, BFDramConfigHiReg);
+ 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, 0x98), 31, 31, BFDctAccessDone);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (3, 0xD4), 4, 0, BFNbFid);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 18, 18, BFDqsRcvEnTrain);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 31, 22, BFMaxLatency);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 15, 0, BFMrsAddress);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 18, 16, BFMrsBank);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 22, 20, BFMrsChipSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 26, 26, BFSendMrsCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 27, 27, BFDeassertMemRstX);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 28, 28, BFAssertCke);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 29, 29, BFSendZQCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 30, 30, BFSendCtrlWord);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 31, BFEnDramInit);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 7, 7, BFLevel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 12, 12, BFMrsQoff);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 18, 18, BFDisAutoRefresh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 0, 0, BFInitDram);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 16, 16, BFUnBuffDimm);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 8, 8, BFDdr3Mode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 9, 9, BFLegacyBiosMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 11, 10, BFZqcsInterval);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 14, 14, BFDisDramInterface);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 6, 6, BFOdtSwizzle);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 15, 8, BFCtrlWordCS);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 8, 8, BFDramEnabled);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 31, 0, BFDctSelBaseAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 31, 0, BFDctSelBaseOffsetReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 6, 2, BFMctWrLimit);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 12, 12, BFPrefCpuDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 13, 13, BFPrefIoDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 29, 29, BFFlushWrOnStpGnt);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 31, 0, BFODCControl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x04, 31, 0, BFAddrTmgControl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 0, 0, BFWrtLvTrEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 1, 1, BFWrtLvTrMode);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 5, 4, BFTrDimmSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 11, 8, BFWrLvOdt);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 12, 12, BFWrLvOdtEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 30, 30, BFDisAutoComp);
+
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ * MemRecNIsIdSupportedDA
+ * 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
+ *
+ */
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ )
+{
+
+ if ((LogicalIdPtr->Revision & (AMD_F10_BL_ALL | AMD_F10_DA_ALL)) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnda.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnda.h
new file mode 100644
index 0000000000..1ecac2df3c
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnda.h
@@ -0,0 +1,109 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnda.h
+ *
+ * Northbridge Ridgeback Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MRNDA_H_
+#define _MRNDA_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_DCTS_PER_NODE_DA 2
+#define MAX_CHANNELS_PER_DCT_DA 1
+
+#define _4GB_RJ8 ((UINT32)4 << (30 - 8))
+#define MTRR_VALID 11
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemRecConstructNBBlockDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ );
+
+VOID
+MemRecNSwitchDctDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ );
+
+VOID
+MemRecNSwitchChannelDA (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ );
+
+VOID
+MemRecNFinalizeMctDA (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemRecNInitializeMctDA (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+#endif /* _MRNDA_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnmctda.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnmctda.c
new file mode 100644
index 0000000000..b4ff99e906
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DA/mrnmctda.c
@@ -0,0 +1,164 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnmctda.c
+ *
+ * Northbridge DA MCT supporting functions Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrnda.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_DA_MRNMCTDA_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets final values in BUCFG and BUCFG2
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNFinalizeMctDA (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_DATA_STRUCT *MemPtr;
+ S_UINT64 SMsr;
+
+ MemPtr = NBPtr->MemPtr;
+
+
+ // Recommended settings for F2x11C
+ MemRecNSetBitFieldNb (NBPtr, BFMctWrLimit, 16);
+ MemRecNSetBitFieldNb (NBPtr, BFPrefCpuDis, 0);
+ MemRecNSetBitFieldNb (NBPtr, BFPrefIoDis, 0);
+ MemRecNSetBitFieldNb (NBPtr, BFFlushWrOnStpGnt, 1);
+
+ LibAmdMsrRead (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ if (!NBPtr->ClToNbFlag) {
+ SMsr.lo &= ~((UINT32) 1 << 15); // ClLinesToNbDis
+ }
+ LibAmdMsrWrite (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ LibAmdMsrRead (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.hi &= ~((UINT32) 1 << (48 - 32)); // WbEnhWsbDis
+ LibAmdMsrWrite (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets initial values in BUCFG and BUCFG2
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNInitializeMctDA (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_DATA_STRUCT *MemPtr;
+ S_UINT64 SMsr;
+
+ MemPtr = NBPtr->MemPtr;
+
+ LibAmdMsrRead (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ if (SMsr.lo & ((UINT32) 1 << 15)) {
+ NBPtr->ClToNbFlag = TRUE;
+ }
+ SMsr.lo |= (UINT32) 1 << 15; // ClLinesToNbDis
+ LibAmdMsrWrite (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ LibAmdMsrRead (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.hi |= (UINT32) 1 << (48 - 32); // WbEnhWsbDis
+ LibAmdMsrWrite (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrndr.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrndr.c
new file mode 100644
index 0000000000..97942b1614
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrndr.c
@@ -0,0 +1,669 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrndr.c
+ *
+ * Common Northbridge functions for Ridgeback Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 48317 $ @e \$Date: 2011-03-07 10:38:14 -0700 (Mon, 07 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrndr.h"
+#include "heapManager.h"
+#include "AdvancedApi.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_DR_MRNDR_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#define SPLIT_CHANNEL 0x20000000
+#define CHANNEL_SELECT 0x10000000
+#define MAX_DELAYS 9 /* 8 data bytes + 1 ECC byte */
+#define MAX_DIMMS 4 /* 4 DIMMs per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableDR (
+ IN OUT TSEFO *NBRegTable
+ );
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldDR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ );
+
+UINT32
+STATIC
+MemRecNcmnGetSetTrainDlyDR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ );
+
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedDr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+STATIC CONST UINT32 RecModeDefRegArrayDR[] = {
+ BFDramControlReg, 0x320C2A06,
+ BFDramBankAddrReg, 0x00001111,
+ BFDramMRSReg, 0x000400A4,
+ BFDramTimingLoReg, 0x000A0092,
+ BFDramTimingHiReg, 0xB6D218FF,
+ BFDramConfigLoReg, 0x00000000,
+ BFDramConfigHiReg, 0x1F48010B,
+ NULL
+};
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] NodeID - Node ID for this NB block
+ *
+ * @return TRUE - This node is a RB and this NB block has been initialized
+ * @return FALSE - This node is not a RB
+ */
+
+BOOLEAN
+MemRecConstructNBBlockDR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 i;
+ UINT8 Dct;
+ UINT8 Channel;
+ DIE_STRUCT *MCTPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemRecNIsIdSupportedDr (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
+ return FALSE;
+ }
+
+ //
+ // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
+ //
+ MCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_DR * (
+ sizeof (DCT_STRUCT) + (
+ MAX_CHANNELS_PER_DCT_DR * (
+ sizeof (CH_DEF_STRUCT) + (
+ MAX_DIMMS * MAX_DELAYS * NUMBER_OF_DELAY_TABLES
+ )
+ )
+ )
+ ) + (sizeof (TSEFO) * BFEndOfList);
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0);
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
+ return FALSE;
+ }
+
+ MemPtr->DieCount = 1;
+ MCTPtr->DctCount = MAX_DCTS_PER_NODE_DR;
+ MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_DR * sizeof (DCT_STRUCT);
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_DR; Dct++) {
+ MCTPtr->DctData[Dct].Dct = Dct;
+ MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_DR;
+ MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[0].ChannelID = Dct;
+ AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_DR * sizeof (CH_DEF_STRUCT);
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_DR; Channel++) {
+ MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = (UINT16 *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS) * 2;
+ MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[Channel].Dct = Dct;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS);
+ }
+ }
+
+ //
+ // Initialize NB block's variables
+ //
+ NBPtr->NBRegTable = (TSEFO *) AllocHeapParams.BufferPtr;
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->RefPtr = MemPtr->ParameterListPtr;
+ NBPtr->MCTPtr = MCTPtr;
+ NBPtr->SPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+ NBPtr->AllNodeSPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+
+ NBPtr->DctCachePtr = NBPtr->DctCache;
+
+ MemRecNInitNBRegTableDR (NBPtr->NBRegTable);
+ NBPtr->Dct = 0;
+ NBPtr->Channel = 0;
+ NBPtr->VarMtrrHiMsk = MemRecGetVarMtrrHiMsk (&(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+
+ LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &NBPtr->MemPtr->StdHeader);
+ LibAmdMemFill (NBPtr->IsSupported, FALSE, sizeof (NBPtr->IsSupported), &NBPtr->MemPtr->StdHeader);
+ for (i = 0; i < NumberOfHooks; i++) {
+ NBPtr->FamilySpecificHook[i] = (BOOLEAN (*) (MEM_NB_BLOCK *, VOID *)) MemRecDefTrue;
+ }
+
+ NBPtr->InitRecovery = MemRecNMemInitNb;
+
+ NBPtr->RecModeDefRegArray = RecModeDefRegArrayDR;
+
+ NBPtr->SwitchNodeRec = (VOID (*) (MEM_NB_BLOCK *, UINT8)) MemRecDefRet;
+ NBPtr->SwitchDCT = MemRecNSwitchDctDR;
+ NBPtr->SwitchChannel = MemRecNSwitchChannelDR;
+ NBPtr->SetMaxLatency = MemRecNSetMaxLatencyNb;
+ NBPtr->GetSysAddrRec = MemRecNGetMCTSysAddrNb;
+ NBPtr->SendMrsCmd = MemRecNSendMrsCmdNb;
+ NBPtr->sendZQCmd = MemRecNSendZQCmdNb;
+ NBPtr->SetDramOdtRec = MemRecNSetDramOdtNb;
+
+ NBPtr->GetBitField = MemRecNGetBitFieldNb;
+ NBPtr->SetBitField = MemRecNSetBitFieldNb;
+ NBPtr->GetTrainDly = MemRecNGetTrainDlyNb;
+ NBPtr->SetTrainDly = MemRecNSetTrainDlyNb;
+ NBPtr->MemRecNCmnGetSetFieldNb = MemRecNCmnGetSetFieldDR;
+ NBPtr->MemRecNcmnGetSetTrainDlyNb = MemRecNcmnGetSetTrainDlyDR;
+ NBPtr->MemRecNSwitchDctNb = MemRecNSwitchDctDR;
+ NBPtr->TrainingFlow = MemNRecTrainingFlowNb;
+ NBPtr->MemRecNInitializeMctNb = MemRecNInitializeMctDR;
+ NBPtr->MemRecNFinalizeMctNb = MemRecNFinalizeMctDR;
+ NBPtr->IsSupported[DramModeBeforeDimmPres] = TRUE;
+ NBPtr->IsSupported[CheckClearOnDimmMirror] = TRUE;
+ MemRecNSwitchDctDR (NBPtr, 0);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchDctDR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ )
+{
+ NBPtr->Dct = Dct & 1;
+ NBPtr->SPDPtr = &(NBPtr->AllNodeSPDPtr[Dct * MAX_DIMMS_PER_CHANNEL]);
+ NBPtr->DCTPtr = &(NBPtr->MCTPtr->DctData[NBPtr->Dct]);
+
+ MemRecNSwitchChannelDR (NBPtr, NBPtr->Channel);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchChannelDR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ )
+{
+ NBPtr->Channel = Channel & 1;
+ NBPtr->ChannelPtr = &(NBPtr->DCTPtr->ChData[NBPtr->Channel]);
+}
+/*----------------------------------------------------------------------------
+ * 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
+STATIC
+MemRecNcmnGetSetTrainDlyDR (
+ 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 < 4);
+ ASSERT (Byte <= 8);
+
+ 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:
+ Field &= ~ 0x0001;
+ 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;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (IsSet) {
+ if (TrnDly == AccessPhRecDly) {
+ Value = NBPtr->DctCachePtr->PhRecReg[Index & 0x03];
+ }
+
+ Value = ((UINT32)Field << Offset) | (Value & (~((UINT32)0xFF << Offset)));
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[Index & 0x03] = Value;
+ }
+ } else {
+ Value = (Value >> Offset) & 0xFF;
+ }
+
+ return Value;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] IsSet - Indicates if the function will set or get
+ * @param[in] FieldName - Name of field to be set
+ * @param[in] Field - Value to be programmed
+ *
+ * @return value read, if the function is used as a "get"
+ */
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldDR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ SBDFO Address;
+ PCI_ADDR PciAddr;
+ UINT8 Type;
+ UINT32 Value;
+ UINT32 Highbit;
+ UINT32 Lowbit;
+ UINT32 Mask;
+
+ Value = 0;
+ if (FieldName < BFEndOfList) {
+ Address = NBPtr->NBRegTable[FieldName];
+ if (Address) {
+ Lowbit = TSEFO_END (Address);
+ Highbit = TSEFO_START (Address);
+ Type = TSEFO_TYPE (Address);
+
+ // If Fn2 and DCT1 selected, set Address to be 1xx
+ if (((Address & 0xF000) == 0x2000) && NBPtr->Dct) {
+ Address |= 0x0100;
+ }
+ if ((Address >> 29) == ((DCT_PHY_ACCESS << 1) | 1)) {
+ // Special DCT Phy access
+ Address &= 0x0FFFFFFF;
+ Lowbit = 0;
+ Highbit = 16;
+ } else {
+ // Normal DCT Phy access
+ Address = TSEFO_OFFSET (Address);
+ }
+
+
+ if (Type == NB_ACCESS) {
+ Address |= (((UINT32) (24 + 0)) << 15);
+ PciAddr.AddressValue = Address;
+ LibAmdPciRead (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+ } else {
+ IDS_ERROR_TRAP;
+ }
+
+ 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;
+
+ if (Type == NB_ACCESS) {
+ PciAddr.AddressValue = Address;
+ LibAmdPciWrite (AccessWidth32, PciAddr , &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ } else {
+ IDS_ERROR_TRAP;
+ }
+ } 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);
+ }
+ }
+ }
+ } else {
+ IDS_ERROR_TRAP; // Invalid bit field index
+ }
+ return Value;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes bit field translation table
+ *
+ * @param[in,out] *NBRegTable - Pointer to the NB Table *
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableDR (
+ IN OUT TSEFO *NBRegTable
+ )
+{
+ UINT16 i;
+ for (i = 0; i <= BFEndOfList; i++) {
+ NBRegTable[i] = 0;
+ }
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x00), 31, 0, BFDevVendorIDReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x60), 2, 0, BFNodeID);
+
+ 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 (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), 31, 0, BFDramControlReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 0, BFDramInitRegReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x80), 31, 0, BFDramBankAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 31, 0, BFDramMRSReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 9, 7, BFDramTerm);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 11, 10, BFDramTermDyn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x88), 31, 0, BFDramTimingLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 31, 0, BFDramTimingHiReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 31, 0, BFDramConfigLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31, 0, BFDramConfigHiReg);
+ 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, 0x98), 31, 31, BFDctAccessDone);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (3, 0xD4), 4, 0, BFNbFid);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 18, 18, BFDqsRcvEnTrain);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 31, 22, BFMaxLatency);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 15, 0, BFMrsAddress);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 18, 16, BFMrsBank);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 22, 20, BFMrsChipSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 26, 26, BFSendMrsCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 27, 27, BFDeassertMemRstX);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 28, 28, BFAssertCke);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 29, 29, BFSendZQCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 30, 30, BFSendCtrlWord);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 31, BFEnDramInit);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 7, 7, BFLevel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 12, 12, BFMrsQoff);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 18, 18, BFDisAutoRefresh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 0, 0, BFInitDram);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 16, 16, BFUnBuffDimm);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 8, 8, BFDdr3Mode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 9, 9, BFLegacyBiosMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 11, 10, BFZqcsInterval);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 14, 14, BFDisDramInterface);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 5, 5, BFSubMemclkRegDly);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 6, 6, BFOdtSwizzle);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 15, 8, BFCtrlWordCS);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 8, 8, BFDramEnabled);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 31, 0, BFDctSelBaseAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 31, 0, BFDctSelBaseOffsetReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 6, 2, BFMctWrLimit);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 12, 12, BFPrefCpuDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 13, 13, BFPrefIoDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 29, 29, BFFlushWrOnStpGnt);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 31, 0, BFODCControl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x04, 31, 0, BFAddrTmgControl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 0, 0, BFWrtLvTrEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 1, 1, BFWrtLvTrMode);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 5, 4, BFTrDimmSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 11, 8, BFWrLvOdt);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 12, 12, BFWrLvOdtEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 30, 30, BFDisAutoComp);
+
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ * MemRecNIsIdSupportedDr
+ * 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
+ *
+ */
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedDr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ )
+{
+
+ if ((LogicalIdPtr->Revision & (AMD_F10_RB_ALL
+ | AMD_F10_BL_ALL
+ | AMD_F10_DA_ALL )) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrndr.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrndr.h
new file mode 100644
index 0000000000..6e03cb83b7
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrndr.h
@@ -0,0 +1,109 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mndr.h
+ *
+ * Northbridge Ridgeback Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MRNDR_H_
+#define _MRNDR_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_DCTS_PER_NODE_DR 2
+#define MAX_CHANNELS_PER_DCT_DR 1
+
+#define _4GB_RJ8 ((UINT32)4 << (30 - 8))
+#define MTRR_VALID 11
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemRecConstructNBBlockDR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ );
+
+VOID
+MemRecNSwitchDctDR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ );
+
+VOID
+MemRecNSwitchChannelDR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ );
+
+VOID
+MemRecNFinalizeMctDR (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemRecNInitializeMctDR (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+#endif /* _MRNDR_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrnmctdr.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrnmctdr.c
new file mode 100644
index 0000000000..fdb787179c
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/DR/mrnmctdr.c
@@ -0,0 +1,166 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnmctdr.c
+ *
+ * Northbridge DR MCT supporting functions Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mrndr.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_DR_MRNMCTDR_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets final values in BUCFG and BUCFG2
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNFinalizeMctDR (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_DATA_STRUCT *MemPtr;
+ S_UINT64 SMsr;
+
+ MemPtr = NBPtr->MemPtr;
+
+
+ // Recommended settings for F2x11C
+ MemRecNSetBitFieldNb (NBPtr, BFMctWrLimit, 16);
+ MemRecNSetBitFieldNb (NBPtr, BFPrefCpuDis, 0);
+ MemRecNSetBitFieldNb (NBPtr, BFPrefIoDis, 0);
+ MemRecNSetBitFieldNb (NBPtr, BFFlushWrOnStpGnt, 1);
+
+ LibAmdMsrRead (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ if (!NBPtr->ClToNbFlag) {
+ SMsr.lo &= ~((UINT32) 1 << 15); // ClLinesToNbDis
+ }
+ LibAmdMsrWrite (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ LibAmdMsrRead (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.hi &= ~((UINT32) 1 << (48 - 32)); // WbEnhWsbDis
+ LibAmdMsrWrite (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets initial values in BUCFG and BUCFG2
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNInitializeMctDR (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_DATA_STRUCT *MemPtr;
+ S_UINT64 SMsr;
+
+ MemPtr = NBPtr->MemPtr;
+
+ LibAmdMsrRead (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ if (SMsr.lo & ((UINT32) 1 << 15)) {
+ NBPtr->ClToNbFlag = TRUE;
+ }
+ SMsr.lo |= (UINT32) 1 << 15; // ClLinesToNbDis
+ LibAmdMsrWrite (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ LibAmdMsrRead (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.hi |= (UINT32) 1 << (48 - 32); // WbEnhWsbDis
+ LibAmdMsrWrite (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrndcthy.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrndcthy.c
new file mode 100644
index 0000000000..11b0839aa6
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrndcthy.c
@@ -0,0 +1,75 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrndctHy.c
+ *
+ * Northbridge DCT support for Hydra Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mru.h"
+#include "mrnhy.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_HY_MRNDCTHY_FILECODE
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnhy.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnhy.c
new file mode 100644
index 0000000000..365b7de70a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnhy.c
@@ -0,0 +1,725 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnhy.c
+ *
+ * Common Northbridge functions for Hydra Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 48317 $ @e \$Date: 2011-03-07 10:38:14 -0700 (Mon, 07 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrnhy.h"
+#include "heapManager.h"
+#include "AdvancedApi.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+#define FILECODE PROC_RECOVERY_MEM_NB_HY_MRNHY_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_DIES_PER_SOCKET 2
+#define MAX_DCTS_PER_DIE 2
+#define SPLIT_CHANNEL 0x20000000
+#define CHANNEL_SELECT 0x10000000
+#define MAX_DELAYS 9 /* 8 data bytes + 1 ECC byte */
+#define MAX_DIMMS 4 /* 4 DIMMs per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableHy (
+ IN OUT TSEFO *NBRegTable
+ );
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ );
+
+UINT32
+STATIC
+MemRecNcmnGetSetTrainDlyHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ );
+
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ );
+
+VOID
+STATIC
+MemRecNSwitchNodeHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 NodeID
+ );
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+STATIC CONST UINT32 RecModeDefRegArrayHy[] = {
+ BFDramControlReg, 0x320C2A06,
+ BFDramBankAddrReg, 0x00001111,
+ BFDramMRSReg, 0x000400A4,
+ BFDramTimingLoReg, 0x000A0092,
+ BFDramTimingHiReg, 0xB6D218FF,
+ BFDramConfigLoReg, 0x00000000,
+ BFDramConfigHiReg, 0x1F48010B,
+ NULL
+};
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] NodeID - Node ID for this NB block
+ *
+ * @return TRUE - This node is a Hydra and this NB block has been initialized
+ * @return FALSE - This node is not a Hydra
+ */
+
+BOOLEAN
+MemRecConstructNBBlockHY (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 i;
+ UINT8 Dct;
+ UINT8 Channel;
+ DIE_STRUCT *MCTPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemRecNIsIdSupportedHy (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
+ return FALSE;
+ }
+
+ //
+ // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
+ //
+ MCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_HY * (
+ sizeof (DCT_STRUCT) + (
+ MAX_CHANNELS_PER_DCT_HY * (
+ sizeof (CH_DEF_STRUCT) + (
+ MAX_DIMMS * MAX_DELAYS * NUMBER_OF_DELAY_TABLES
+ )
+ )
+ )
+ ) + (sizeof (TSEFO) * BFEndOfList);
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0);
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
+ return FALSE;
+ }
+
+ MemPtr->DieCount = MAX_DIES_PER_SOCKET;
+ MCTPtr->DctCount = MAX_DCTS_PER_NODE_HY;
+ MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ MemPtr->DiesPerSystem[NodeID + 1].DctCount = MAX_DCTS_PER_NODE_HY;
+ MemPtr->DiesPerSystem[NodeID + 1].DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_HY * sizeof (DCT_STRUCT);
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_HY; Dct++) {
+ MCTPtr->DctData[Dct].Dct = Dct;
+ MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_HY;
+ MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[0].ChannelID = (MCTPtr->DieId * 2) + Dct;
+ AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_HY * sizeof (CH_DEF_STRUCT);
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_HY; Channel++) {
+ MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = (UINT16 *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS) * 2;
+ MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[Channel].Dct = Dct;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS);
+ }
+ }
+
+ //
+ // Initialize NB block's variables
+ //
+ NBPtr->NBRegTable = (TSEFO *) AllocHeapParams.BufferPtr;
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->RefPtr = MemPtr->ParameterListPtr;
+ NBPtr->MCTPtr = MCTPtr;
+ NBPtr->AllNodeMCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ NBPtr->SPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+ NBPtr->AllNodeSPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+
+ NBPtr->DctCachePtr = NBPtr->DctCache;
+
+ MemRecNInitNBRegTableHy (NBPtr->NBRegTable);
+ NBPtr->Dct = 0;
+ NBPtr->Channel = 0;
+ NBPtr->VarMtrrHiMsk = MemRecGetVarMtrrHiMsk (&(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+
+ LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &NBPtr->MemPtr->StdHeader);
+ LibAmdMemFill (NBPtr->IsSupported, FALSE, sizeof (NBPtr->IsSupported), &NBPtr->MemPtr->StdHeader);
+ for (i = 0; i < NumberOfHooks; i++) {
+ NBPtr->FamilySpecificHook[i] = (BOOLEAN (*) (MEM_NB_BLOCK *, VOID *)) MemRecDefTrue;
+ }
+
+ NBPtr->InitRecovery = MemRecNMemInitNb;
+
+ NBPtr->RecModeDefRegArray = RecModeDefRegArrayHy;
+
+ NBPtr->SwitchNodeRec = MemRecNSwitchNodeHy;
+ NBPtr->SwitchDCT = MemRecNSwitchDctHy;
+ NBPtr->SwitchChannel = MemRecNSwitchChannelHy;
+ NBPtr->SetMaxLatency = MemRecNSetMaxLatencyNb;
+ NBPtr->GetSysAddrRec = MemRecNGetMCTSysAddrNb;
+ NBPtr->SendMrsCmd = MemRecNSendMrsCmdNb;
+ NBPtr->sendZQCmd = MemRecNSendZQCmdNb;
+ NBPtr->SetDramOdtRec = MemRecNSetDramOdtNb;
+
+ NBPtr->GetBitField = MemRecNGetBitFieldNb;
+ NBPtr->SetBitField = MemRecNSetBitFieldNb;
+ NBPtr->GetTrainDly = MemRecNGetTrainDlyNb;
+ NBPtr->SetTrainDly = MemRecNSetTrainDlyNb;
+
+ NBPtr->MemRecNCmnGetSetFieldNb = MemRecNCmnGetSetFieldHy;
+ NBPtr->MemRecNcmnGetSetTrainDlyNb = MemRecNcmnGetSetTrainDlyHy;
+ NBPtr->MemRecNSwitchDctNb = MemRecNSwitchDctHy;
+ NBPtr->TrainingFlow = MemNRecTrainingFlowNb;
+ NBPtr->MemRecNInitializeMctNb = MemRecNInitializeMctHy;
+ NBPtr->MemRecNFinalizeMctNb = MemRecNFinalizeMctHy;
+ NBPtr->IsSupported[DramModeAfterDimmPres] = TRUE;
+ MemRecNSwitchDctHy (NBPtr, 0);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the current die to work on.
+ * Should be called before accessing a certain die
+ * All data structures will be updated to point to the current node
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] NodeID - ID of the target die
+ *
+ */
+
+VOID
+STATIC
+MemRecNSwitchNodeHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 NodeID
+ )
+{
+ NBPtr->MCTPtr = &(NBPtr->AllNodeMCTPtr[NodeID]);
+ NBPtr->Node = NodeID;
+ NBPtr->MCTPtr->NodeId = NodeID;
+ MemRecNSwitchDctHy (NBPtr, NBPtr->Dct);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchDctHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ )
+{
+ NBPtr->Dct = Dct & 1;
+ NBPtr->SPDPtr = &(NBPtr->AllNodeSPDPtr[(NBPtr->MCTPtr->NodeId * MAX_DCTS_PER_DIE + Dct) * MAX_DIMMS_PER_CHANNEL]);
+ NBPtr->DCTPtr = &(NBPtr->MCTPtr->DctData[NBPtr->Dct]);
+
+ MemRecNSwitchChannelHy (NBPtr, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchChannelHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ )
+{
+ NBPtr->Channel = 0;
+ NBPtr->ChannelPtr = &(NBPtr->DCTPtr->ChData[0]);
+}
+
+/*----------------------------------------------------------------------------
+ * 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
+STATIC
+MemRecNcmnGetSetTrainDlyHy (
+ 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);
+
+ 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) != 0) {
+ // if byte 4,5,6,7
+ index += 0x10;
+ }
+ if ((Byte & 0x02) != 0) {
+ // 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:
+ Field &= ~ 0x0001;
+ case AccessWrDatDly:
+ index += (DIMM * 0x100);
+ if (Nibble != 0) {
+ if (Rank != 0) {
+ index += 0xA0;
+ } else {
+ index += 0x70;
+ }
+ } else if (Rank != 0) {
+ 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;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (IsSet != 0) {
+ if (TrnDly == AccessPhRecDly) {
+ value = NBPtr->DctCachePtr->PhRecReg[index & 0x03];
+ }
+
+ value = ((UINT32)Field << offset) | (value & (~((UINT32)0xFF << offset)));
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, value);
+ address |= DCT_ACCESS_WRITE;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[index & 0x03] = value;
+ }
+ } else {
+ value = (value >> offset) & 0xFF;
+ }
+
+ return value;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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 - Name of Field to be set
+ * @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
+STATIC
+MemRecNCmnGetSetFieldHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ SBDFO Address;
+ PCI_ADDR PciAddr;
+ UINT8 Type;
+ UINT32 Value;
+ UINT32 Highbit;
+ UINT32 Lowbit;
+ UINT32 Mask;
+
+ Value = 0;
+ if (FieldName < BFEndOfList) {
+ Address = NBPtr->NBRegTable[FieldName];
+ if (Address != 0) {
+ Lowbit = TSEFO_END (Address);
+ Highbit = TSEFO_START (Address);
+ Type = TSEFO_TYPE (Address);
+
+ // If Fn2 and DCT1 selected, set Address to be 1xx
+ if (((Address & 0xF000) == 0x2000) && (NBPtr->Dct != 0)) {
+ Address |= 0x0100;
+ }
+ if ((Address >> 29) == ((DCT_PHY_ACCESS << 1) | 1)) {
+ // Special DCT Phy access
+ Address &= 0x0FFFFFFF;
+ Lowbit = 0;
+ Highbit = 16;
+ } else {
+ // Normal DCT Phy access
+ Address = TSEFO_OFFSET (Address);
+ }
+
+
+ if (Type == NB_ACCESS) {
+ // Address |= (((UINT32) (24 + 0)) << 15);
+ PciAddr.AddressValue = Address;
+ // Fix for MCM
+ PciAddr.Address.Device = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Device;
+ PciAddr.Address.Bus = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Bus;
+ PciAddr.Address.Segment = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Segment;
+ Address = PciAddr.AddressValue;
+ LibAmdPciRead (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+ } else {
+ IDS_ERROR_TRAP;
+ }
+
+ if (IsSet != 0) {
+ // 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;
+
+ if (Type == NB_ACCESS) {
+ PciAddr.AddressValue = Address;
+ LibAmdPciWrite (AccessWidth32, PciAddr , &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ } else {
+ IDS_ERROR_TRAP;
+ }
+ } 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);
+ }
+ }
+ }
+ } else {
+ IDS_ERROR_TRAP; // Invalid bit field index
+ }
+ return Value;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes bit field translation table
+ *
+* @param[in,out] *NBRegTable - Pointer to the NB Table *
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableHy (
+ IN OUT TSEFO *NBRegTable
+ )
+{
+ UINT16 i;
+ for (i = 0; i <= BFEndOfList; i++) {
+ NBRegTable[i] = 0;
+ }
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x00), 31, 0, BFDevVendorIDReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x60), 2, 0, BFNodeID);
+
+ 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 (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), 31, 0, BFDramControlReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 0, BFDramInitRegReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x80), 31, 0, BFDramBankAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 31, 0, BFDramMRSReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 9, 7, BFDramTerm);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 11, 10, BFDramTermDyn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x88), 31, 0, BFDramTimingLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 31, 0, BFDramTimingHiReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 31, 0, BFDramConfigLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31, 0, BFDramConfigHiReg);
+ 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, 0x98), 31, 31, BFDctAccessDone);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (3, 0xD4), 4, 0, BFNbFid);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 18, 18, BFDqsRcvEnTrain);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 31, 22, BFMaxLatency);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 15, 0, BFMrsAddress);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 18, 16, BFMrsBank);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 22, 20, BFMrsChipSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 26, 26, BFSendMrsCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 27, 27, BFDeassertMemRstX);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 28, 28, BFAssertCke);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 29, 29, BFSendZQCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 30, 30, BFSendCtrlWord);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 31, BFEnDramInit);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 7, 7, BFLevel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 12, 12, BFMrsQoff);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 18, 18, BFDisAutoRefresh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 0, 0, BFInitDram);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 16, 16, BFUnBuffDimm);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 15, 12, BFX4Dimm);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 8, 8, BFDdr3Mode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 9, 9, BFLegacyBiosMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 11, 10, BFZqcsInterval);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 14, 14, BFDisDramInterface);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 5, 5, BFSubMemclkRegDly);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 6, 6, BFOdtSwizzle);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 15, 8, BFCtrlWordCS);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 8, 8, BFDramEnabled);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 31, 0, BFDctSelBaseAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 31, 0, BFDctSelBaseOffsetReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 31, 0, BFMctCfgHiReg);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 31, 0, BFODCControl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x04, 31, 0, BFAddrTmgControl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 0, 0, BFWrtLvTrEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 1, 1, BFWrtLvTrMode);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 5, 4, BFTrDimmSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 11, 8, BFWrLvOdt);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 12, 12, BFWrLvOdtEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 30, 30, BFDisAutoComp);
+
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ * MemRecNIsIdSupportedHy
+ * 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 Hydra.
+ * @return FALSE - This node is not a Hydra.
+ *
+ */
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ )
+{
+ if ((LogicalIdPtr->Revision & AMD_F10_HY_ALL) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnhy.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnhy.h
new file mode 100644
index 0000000000..b3fcad2732
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnhy.h
@@ -0,0 +1,109 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnhy.h
+ *
+ * Northbridge Hydra Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MRNHY_H_
+#define _MRNHY_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_DCTS_PER_NODE_HY 2
+#define MAX_CHANNELS_PER_DCT_HY 1
+
+#define _4GB_RJ8 ((UINT32)4 << (30 - 8))
+#define MTRR_VALID 11
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemRecConstructNBBlockHY (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ );
+
+VOID
+MemRecNSwitchDctHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ );
+
+VOID
+MemRecNSwitchChannelHy (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ );
+
+VOID
+MemRecNFinalizeMctHy (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemRecNInitializeMctHy (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+#endif /* _MRNHY_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnmcthy.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnmcthy.c
new file mode 100644
index 0000000000..eb9a246ea1
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnmcthy.c
@@ -0,0 +1,161 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnmctdr.c
+ *
+ * Northbridge DR MCT supporting functions Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrnhy.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_HY_MRNMCTHY_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets final values in BUCFG and BUCFG2
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNFinalizeMctHy (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_DATA_STRUCT *MemPtr;
+ S_UINT64 SMsr;
+
+ MemPtr = NBPtr->MemPtr;
+
+ // Recommended settings for F2x11C
+ MemRecNSetBitFieldNb (NBPtr, BFMctCfgHiReg, 0x2CE00F60);
+
+ LibAmdMsrRead (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ if (!NBPtr->ClToNbFlag) {
+ SMsr.lo &= ~((UINT32) 1 << 15); // ClLinesToNbDis
+ }
+ LibAmdMsrWrite (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ LibAmdMsrRead (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.hi &= ~((UINT32) 1 << (48 - 32)); // WbEnhWsbDis
+ LibAmdMsrWrite (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets initial values in BUCFG and BUCFG2
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNInitializeMctHy (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MEM_DATA_STRUCT *MemPtr;
+ S_UINT64 SMsr;
+
+ MemPtr = NBPtr->MemPtr;
+
+ LibAmdMsrRead (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ if (SMsr.lo & ((UINT32) 1 << 15)) {
+ NBPtr->ClToNbFlag = TRUE;
+ }
+ SMsr.lo |= (UINT32) 1 << 15; // ClLinesToNbDis
+ LibAmdMsrWrite (BU_CFG2, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ LibAmdMsrRead (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.hi |= (UINT32) 1 << (48 - 32); // WbEnhWsbDis
+ LibAmdMsrWrite (BU_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnprotohy.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnprotohy.c
new file mode 100644
index 0000000000..5773c1fe82
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/HY/mrnprotohy.c
@@ -0,0 +1,61 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnproto.c
+ *
+ * Northbridge support functions for Errata and early samples Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+
+
+#include "AGESA.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_HY_MRNPROTOHY_FILECODE
+/*
+ *-----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrndctor.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrndctor.c
new file mode 100644
index 0000000000..e12d273c4a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrndctor.c
@@ -0,0 +1,341 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrndctOr.c
+ *
+ * Northbridge DCT support for Orochi Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 49896 $ @e \$Date: 2011-03-30 02:18:18 -0600 (Wed, 30 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mp.h"
+#include "mru.h"
+#include "mrt3.h"
+#include "mrnor.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_OR_MRNDCTOR_FILECODE
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function gets platform specific config/timing values from the interface layer and
+ * programs them into DCT.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - An Error value lower than AGESA_ERROR may have occurred
+ * @return FALSE - An Error value greater than or equal to AGESA_ERROR may have occurred
+ */
+
+BOOLEAN
+MemRecNPlatformSpecOr (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ CONST UINT32 OdtPattern3D[][4] = {
+ {0x00000000, 0x00000000, 0x00000404, 0x00000000},
+ {0x00000101, 0x00000404, 0x00000105, 0x00000405},
+ {0x00000303, 0x05050606, 0x00000307, 0x0D070607},
+ {0x00000000, 0x00000000, 0x020A0000, 0x080A0000},
+ {0x04040A0A, 0x04040000, 0x040C0A0E, 0x04060000},
+ {0x05050B0B, 0x05050E0E, 0x050D0B0F, 0x05070E0F}
+ };
+
+ UINT32 PhyRODTCSHigh;
+ UINT32 PhyRODTCSLow;
+ UINT32 PhyWODTCSHigh;
+ UINT32 PhyWODTCSLow;
+ UINT8 MaxDimmPerCH;
+ UINT32 ODC;
+ UINT32 AddrCmd;
+ UINT8 i;
+ CH_DEF_STRUCT *ChannelPtr;
+
+ ChannelPtr = NBPtr->ChannelPtr;
+
+ MaxDimmPerCH = RecGetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, 0, ChannelPtr->ChannelID);
+
+ // Set ODC, AddrCmdTmg
+ if (ChannelPtr->Dimms == 1) {
+ ODC = 0x10112222;
+ AddrCmd = 0x003B0000;
+ } else {
+ ODC = 0x10222222;
+ AddrCmd = 0x00390039;
+ }
+ if (ChannelPtr->DimmQrPresent != 0) {
+ ODC = 0x10222222;
+ }
+ MemRecNSetBitFieldNb (NBPtr, BFODCControl, ODC);
+ MemRecNSetBitFieldNb (NBPtr, BFAddrTmgControl, AddrCmd);
+
+ // Find Rtt_Nom, Rtt_Wr
+ if (ChannelPtr->DimmQrPresent == 0) {
+ if (ChannelPtr->Dimms == 1) {
+ NBPtr->PsPtr->DramTerm = 2;
+ NBPtr->PsPtr->DynamicDramTerm = 0;
+ } else {
+ NBPtr->PsPtr->DramTerm = 3;
+ NBPtr->PsPtr->DynamicDramTerm = 2;
+ }
+ } else {
+ NBPtr->PsPtr->DramTerm = 2;
+ NBPtr->PsPtr->DynamicDramTerm = 2;
+ }
+
+ // Set ODT patterns
+ PhyRODTCSLow = 0x00000000;
+ PhyRODTCSHigh = 0x00000000;
+ PhyWODTCSHigh = 0x00000000;
+ if (MaxDimmPerCH != 3) {
+ if (ChannelPtr->DimmQrPresent == 0) {
+ if (ChannelPtr->Dimms == 1) {
+ PhyWODTCSLow = 0x08020401;
+ } else {
+ PhyRODTCSLow = 0x01010202;
+ PhyWODTCSLow = 0x09030603;
+ }
+ } else {
+ if (ChannelPtr->Dimms == 1) {
+ PhyWODTCSLow = 0x080A0505;
+ PhyWODTCSHigh = 0x020A0505;
+ } else {
+ PhyRODTCSHigh = 0x05050A0A;
+ PhyRODTCSLow = 0x05050A0A;
+ PhyWODTCSHigh = 0x050D0A0E;
+ PhyWODTCSLow = 0x05070A0E;
+ }
+ }
+ } else {
+ i = ChannelPtr->Dimms + ((ChannelPtr->DimmQrPresent != 0) ? 3 : 0) - 1;
+ PhyWODTCSLow = OdtPattern3D[i][0];
+ PhyWODTCSHigh = OdtPattern3D[i][1];
+ PhyRODTCSLow = OdtPattern3D[i][2];
+ PhyRODTCSHigh = OdtPattern3D[i][3];
+ }
+
+ MemRecNSetBitFieldNb (NBPtr, BFPhyWODTCSLow, PhyWODTCSLow);
+ MemRecNSetBitFieldNb (NBPtr, BFPhyRODTCSLow, PhyRODTCSLow);
+ MemRecNSetBitFieldNb (NBPtr, BFPhyRODTCSHigh, PhyRODTCSHigh);
+ MemRecNSetBitFieldNb (NBPtr, BFPhyWODTCSHigh, PhyWODTCSHigh);
+ return TRUE;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Set Dram ODT for mission mode and write leveling mode.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] OdtMode - Mission mode or write leveling mode
+ * @param[in] ChipSelect - Chip select number
+ * @param[in] TargetCS - Chip select number that is being trained
+ *
+ */
+
+VOID
+MemRecNSetDramOdtOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN ODT_MODE OdtMode,
+ IN UINT8 ChipSelect,
+ IN UINT8 TargetCS
+ )
+{
+ UINT8 DramTerm;
+ UINT8 DramTermDyn;
+
+ // Dram nominal termination & Dram dynamic termination
+ DramTerm = NBPtr->PsPtr->DramTerm;
+ DramTermDyn = NBPtr->PsPtr->DynamicDramTerm;
+
+ if (OdtMode == WRITE_LEVELING_MODE) {
+ if (ChipSelect == TargetCS) {
+ DramTerm = DramTermDyn;
+ MemRecNSetBitFieldNb (NBPtr, BFWrLvOdt, 0xF); // Use MRS commands to disable ODT#
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes the DRAM devices on all DCTs at the same time
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+VOID
+MemRecNStartupDCTOr (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ // Program D18F2x[1,0]9C_x0000_000B = 80000000h.
+ MemRecNSetBitFieldNb (NBPtr, BFDramPhyStatusReg, 0x80000000);
+
+ // Program D18F2x[1,0]9C_x0D0F_E013[PllRegWaitTime] = 0118h.
+ MemRecNSetBitFieldNb (NBPtr, BFPllRegWaitTime, 0x118);
+
+ // Phy Voltage Level Programming
+ MemRecNPhyVoltageLevelNb (NBPtr);
+
+ // Run frequency change sequence
+ MemRecNSetBitFieldNb (NBPtr, BFPllLockTime, 0x190);
+ MemRecNSetBitFieldNb (NBPtr, BFMemClkFreq, 4);
+
+ MemRecNSetBitFieldNb (NBPtr, BFMemClkFreqVal, 1);
+ while (MemRecNGetBitFieldNb (NBPtr, BFFreqChgInProg) == 1) {};
+
+ MemRecNSetBitFieldNb (NBPtr, BFPllLockTime, 0x000F);
+
+ // Run DramInit sequence
+ AGESA_TESTPOINT (TpProcMemDramInit, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->TechPtr->DramInit (NBPtr->TechPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSetMaxLatencyOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 MaxRcvEnDly
+ )
+{
+ UINT32 N;
+ UINT32 T;
+ UINT32 P;
+ UINT32 MemClkPeriod;
+ UINT32 NBClkFreq;
+
+ // Find NB frequency
+ NBClkFreq = (200 * (MemRecNGetBitFieldNb (NBPtr, BFNbFid) + 4)) >> MemRecNGetBitFieldNb (NBPtr, BFNbDid);
+
+ // 1. P = N = T = 0.
+ P = N = T = 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
+ P += 2;
+
+ // 4. P = P + (8 - D18F2x210_dct[1:0]_nbp[3:0][RdPtrInit]) + 1
+ P = P + (8 - 6) + 1;
+
+ // 6. If (D18F2xA8_dct[1:0][SubMemclkRegDly] = 0 & D18F2x90_dct[1:0][UnbuffDimm] = 0)
+ // then P = P + 2
+ P += 2;
+
+ // 7. P = P + (2 * (D18F2x200_dct[1:0][Tcl] - 1 clocks))
+ P = P + (2 * (6 - 1));
+
+ // 5. P = P + 5
+ P += 5;
+
+ // 8. 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))
+ P = P + (MaxRcvEnDly / 32) + 2;
+
+ // 9. P = P + 5
+ P += 5;
+
+ // 10. T = T + 800 ps
+ T += 800;
+
+ // 11. N = (P/(MemClkFreq * 2) + T) * NclkFreq; Convert from PCLKs plus time to NCLKs.
+ MemClkPeriod = 1000000 / DDR667_FREQUENCY;
+ N = ((((P * MemClkPeriod + 1) / 2) + T) * NBClkFreq + 999999) / 1000000;
+
+ // 12. N = N - 1. See step 9.
+ N = N - 1;
+
+ // 13. D18F2x210_dct[1:0]_nbp[3:0][MaxRdLatency] = CEIL(N) - 1
+ N = N - 1;
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "NB Freq: %d MHz\n", NBClkFreq);
+ IDS_HDT_CONSOLE (MEM_FLOW, "MaxRdLat: %03x\n", N);
+ MemRecNSetBitFieldNb (NBPtr, BFMaxLatency, N);
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnmctor.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnmctor.c
new file mode 100644
index 0000000000..fc09d176fb
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnmctor.c
@@ -0,0 +1,145 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnmctor.c
+ *
+ * Northbridge OR MCT supporting functions Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 48317 $ @e \$Date: 2011-03-07 10:38:14 -0700 (Mon, 07 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mrnor.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_OR_MRNMCTOR_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function is the Recovery memory configuration function for OR DDR3
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return AGESA_STATUS
+ * - AGESA_ALERT
+ * - AGESA_FATAL
+ * - AGESA_SUCCESS
+ * - AGESA_WARNING
+ */
+
+AGESA_STATUS
+MemRecNMemInitOr (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ AGESA_STATUS Status;
+ MEM_TECH_BLOCK *TechPtr;
+
+ TechPtr = NBPtr->TechPtr;
+
+ Status = AGESA_FATAL;
+ if (TechPtr->DimmPresence (TechPtr)) {
+
+ if (MemRecNAutoConfigNb (NBPtr)) {
+
+ AGESA_TESTPOINT (TpProcMemPlatformSpecificConfig, &(NBPtr->MemPtr->StdHeader));
+ if (MemRecNPlatformSpecOr (NBPtr)) {
+ AgesaHookBeforeDramInitRecovery (0, NBPtr->MemPtr);
+ AGESA_TESTPOINT (TpProcMemStartDcts, &(NBPtr->MemPtr->StdHeader));
+ MemRecNStartupDCTOr (NBPtr);
+
+ AGESA_TESTPOINT (TpProcMemMtrrConfiguration, &(NBPtr->MemPtr->StdHeader));
+ MemRecNCPUMemRecTypingNb (NBPtr);
+
+ AGESA_TESTPOINT (TpProcMemDramTraining, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->TrainingFlow (NBPtr);
+
+ Status = AGESA_SUCCESS;
+ }
+ }
+ }
+
+ return Status;
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnor.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnor.c
new file mode 100644
index 0000000000..8fcfc96932
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnor.c
@@ -0,0 +1,798 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnor.c
+ *
+ * Common Northbridge functions for Orochi Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 49896 $ @e \$Date: 2011-03-30 02:18:18 -0600 (Wed, 30 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrnor.h"
+#include "heapManager.h"
+#include "AdvancedApi.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+#define FILECODE PROC_RECOVERY_MEM_NB_OR_MRNOR_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#define MAX_DCTS_PER_DIE 2
+#define SPLIT_CHANNEL 0x20000000
+#define CHANNEL_SELECT 0x10000000
+#define MAX_DELAYS 9 /* 8 data bytes + 1 ECC byte */
+#define MAX_DIMMS 4 /* 4 DIMMs per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableOr (
+ IN OUT TSEFO *NBRegTable
+ );
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ );
+
+UINT32
+STATIC
+MemRecNcmnGetSetTrainDlyOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ );
+
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ );
+
+VOID
+STATIC
+MemRecNSwitchNodeOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 NodeID
+ );
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+STATIC CONST UINT32 RecModeDefRegArrayOR[] = {
+ BFDramBankAddrReg, 0x00001111,
+ BFTref, 0x00000002,
+ BFDramTimingLoReg, 0x00000000,
+ BFDramTiming0, 0x0F060606,
+ BFDramTiming1, 0x04100415,
+ BFDramTiming2, 0x05050505,
+ BFDramTiming3, 0x00000405,
+ BFDramTiming4, 0x000B0B0B,
+ BFDramTiming5, 0x0B0B0B0B,
+ BFDramTiming6, 0x00171600,
+ BFDramTiming10, 0x00000006,
+ BFDramNBP0, 0x32000006,
+ BFDramConfigHiReg, 0x00180800,
+ BFDramODTCtlReg, 0x00006061,
+ BFPhyFence, 0x000056B5,
+ BFSwNbPstateLoDis, 0x00000001,
+ NULL
+};
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] NodeID - Node ID for this NB block
+ *
+ * @return TRUE - This node is a Orochi and this NB block has been initialized
+ * @return FALSE - This node is not a Orochi
+ */
+
+BOOLEAN
+MemRecConstructNBBlockOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 i;
+ UINT8 Dct;
+ UINT8 Channel;
+ DIE_STRUCT *MCTPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemRecNIsIdSupportedOr (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
+ return FALSE;
+ }
+
+ //
+ // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
+ //
+ MCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_OR * (
+ sizeof (DCT_STRUCT) + (
+ MAX_CHANNELS_PER_DCT_OR * (
+ sizeof (CH_DEF_STRUCT) + (
+ MAX_DIMMS * MAX_DELAYS * NUMBER_OF_DELAY_TABLES
+ )
+ )
+ )
+ ) + sizeof (MEM_PS_BLOCK) + (sizeof (TSEFO) * BFEndOfList);
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0);
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
+ return FALSE;
+ }
+
+ MemPtr->DieCount = MAX_DIES_PER_SOCKET_OR;
+ MCTPtr->DctCount = MAX_DCTS_PER_NODE_OR;
+ MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ MemPtr->DiesPerSystem[NodeID + 1].DctCount = MAX_DCTS_PER_NODE_OR;
+ MemPtr->DiesPerSystem[NodeID + 1].DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_OR * sizeof (DCT_STRUCT);
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_OR; Dct++) {
+ MCTPtr->DctData[Dct].Dct = Dct;
+ MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_OR;
+ MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[0].ChannelID = (MCTPtr->DieId * 2) + Dct;
+ AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_OR * sizeof (CH_DEF_STRUCT);
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_OR; Channel++) {
+ MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = (UINT16 *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS) * 2;
+ MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[Channel].Dct = Dct;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS);
+ }
+ }
+ NBPtr->PsPtr = (MEM_PS_BLOCK *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += sizeof (MEM_PS_BLOCK);
+
+ //
+ // Initialize NB block's variables
+ //
+ NBPtr->NBRegTable = (TSEFO *) AllocHeapParams.BufferPtr;
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->RefPtr = MemPtr->ParameterListPtr;
+ NBPtr->MCTPtr = MCTPtr;
+ NBPtr->AllNodeMCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ NBPtr->SPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+ NBPtr->AllNodeSPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+
+ NBPtr->DctCachePtr = NBPtr->DctCache;
+
+ MemRecNInitNBRegTableOr (NBPtr->NBRegTable);
+ NBPtr->Dct = 0;
+ NBPtr->Channel = 0;
+ NBPtr->VarMtrrHiMsk = MemRecGetVarMtrrHiMsk (&(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+
+ LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &NBPtr->MemPtr->StdHeader);
+ LibAmdMemFill (NBPtr->IsSupported, FALSE, sizeof (NBPtr->IsSupported), &NBPtr->MemPtr->StdHeader);
+ for (i = 0; i < NumberOfHooks; i++) {
+ NBPtr->FamilySpecificHook[i] = (BOOLEAN (*) (MEM_NB_BLOCK *, VOID *)) MemRecDefTrue;
+ }
+
+ NBPtr->InitRecovery = MemRecNMemInitOr;
+
+ NBPtr->RecModeDefRegArray = RecModeDefRegArrayOR;
+
+ NBPtr->SwitchNodeRec = MemRecNSwitchNodeOr;
+ NBPtr->SwitchDCT = MemRecNSwitchDctOr;
+ NBPtr->SwitchChannel = MemRecNSwitchChannelOr;
+ NBPtr->SetMaxLatency = MemRecNSetMaxLatencyOr;
+ NBPtr->GetSysAddrRec = MemRecNGetMCTSysAddrNb;
+ NBPtr->SendMrsCmd = MemRecNSendMrsCmdNb;
+ NBPtr->sendZQCmd = MemRecNSendZQCmdNb;
+ NBPtr->SetDramOdtRec = MemRecNSetDramOdtOr;
+
+ NBPtr->GetBitField = MemRecNGetBitFieldNb;
+ NBPtr->SetBitField = MemRecNSetBitFieldNb;
+ NBPtr->GetTrainDly = MemRecNGetTrainDlyNb;
+ NBPtr->SetTrainDly = MemRecNSetTrainDlyNb;
+
+ NBPtr->MemRecNCmnGetSetFieldNb = MemRecNCmnGetSetFieldOr;
+ NBPtr->MemRecNcmnGetSetTrainDlyNb = MemRecNcmnGetSetTrainDlyOr;
+ NBPtr->MemRecNSwitchDctNb = MemRecNSwitchDctOr;
+ NBPtr->TrainingFlow = MemNRecTrainingFlowUnb;
+ NBPtr->ReadPattern = MemRecNContReadPatternUnb;
+ NBPtr->WritePattern = MemRecNContWritePatternUnb;
+ NBPtr->CompareTestPattern = MemRecNCompareTestPatternUnb;
+
+ NBPtr->IsSupported[CheckDramTerm] = TRUE;
+ NBPtr->IsSupported[CheckDramTermDyn] = TRUE;
+ MemRecNSwitchDctOr (NBPtr, 0);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the current die to work on.
+ * Should be called before accessing a certain die
+ * All data structures will be updated to point to the current node
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] NodeID - ID of the target die
+ *
+ */
+
+VOID
+STATIC
+MemRecNSwitchNodeOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 NodeID
+ )
+{
+ NBPtr->MCTPtr = &(NBPtr->AllNodeMCTPtr[NodeID]);
+ NBPtr->Node = NodeID;
+ NBPtr->MCTPtr->NodeId = NodeID;
+ MemRecNSwitchDctOr (NBPtr, NBPtr->Dct);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchDctOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ )
+{
+ NBPtr->Dct = Dct & 1;
+ NBPtr->SPDPtr = &(NBPtr->AllNodeSPDPtr[(NBPtr->MCTPtr->NodeId * MAX_DCTS_PER_DIE + Dct) * MAX_DIMMS_PER_CHANNEL]);
+ NBPtr->DCTPtr = &(NBPtr->MCTPtr->DctData[NBPtr->Dct]);
+
+ MemRecNSwitchChannelOr (NBPtr, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchChannelOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ )
+{
+ NBPtr->Channel = 0;
+ NBPtr->ChannelPtr = &(NBPtr->DCTPtr->ChData[0]);
+}
+
+/*----------------------------------------------------------------------------
+ * 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
+STATIC
+MemRecNcmnGetSetTrainDlyOr (
+ 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;
+ UINT32 mask;
+
+ DIMM = DRBN_DIMM (DrbnVar);
+ Byte = DRBN_BYTE (DrbnVar);
+
+ mask = 0xFF;
+
+ switch (TrnDly) {
+ case AccessRcvEnDly:
+ mask = 0x1FF;
+ 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) != 0) {
+ // if byte 4,5,6,7
+ index += 0x10;
+ }
+ if ((Byte & 0x02) != 0) {
+ // 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;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (IsSet != 0) {
+ if (TrnDly == AccessPhRecDly) {
+ value = NBPtr->DctCachePtr->PhRecReg[index & 0x03];
+ }
+
+ value = ((UINT32)Field << offset) | (value & (~(mask << offset)));
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, value);
+ address |= DCT_ACCESS_WRITE;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[index & 0x03] = value;
+ }
+ } else {
+ value = (value >> offset) & mask;
+ }
+
+ return value;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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 - Name of Field to be set
+ * @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
+STATIC
+MemRecNCmnGetSetFieldOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ TSEFO Address;
+ PCI_ADDR PciAddr;
+ UINT8 Type;
+ UINT32 Value;
+ UINT32 Highbit;
+ UINT32 Lowbit;
+ UINT32 Mask;
+
+ Value = 0;
+ if (FieldName < BFEndOfList) {
+ Address = NBPtr->NBRegTable[FieldName];
+ if (Address != 0) {
+ Lowbit = TSEFO_END (Address);
+ Highbit = TSEFO_START (Address);
+ Type = TSEFO_TYPE (Address);
+
+ // If Fn2 and DCT1 selected, set Address to be 1xx
+ if ((Type == NB_ACCESS) && ((Address & 0xF000) == 0x2000)) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctCfgSel, NBPtr->Dct);
+ }
+ if ((Address >> 29) == ((DCT_PHY_ACCESS << 1) | 1)) {
+ // Special DCT Phy access
+ Address &= 0x0FFFFFFF;
+ Lowbit = 0;
+ Highbit = 16;
+ } else {
+ // Normal DCT Phy access
+ Address = TSEFO_OFFSET (Address);
+ }
+
+
+ if (Type == NB_ACCESS) {
+ // Address |= (((UINT32) (24 + 0)) << 15);
+ PciAddr.AddressValue = Address;
+ // Fix for MCM
+ PciAddr.Address.Device = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Device;
+ PciAddr.Address.Bus = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Bus;
+ PciAddr.Address.Segment = NBPtr->MemPtr->DiesPerSystem[NBPtr->Node].PciAddr.Address.Segment;
+ Address = PciAddr.AddressValue;
+ LibAmdPciRead (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
+ 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) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+ } else {
+ IDS_ERROR_TRAP;
+ }
+
+ if (IsSet != 0) {
+ // 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;
+
+ if (Type == NB_ACCESS) {
+ PciAddr.AddressValue = Address;
+ LibAmdPciWrite (AccessWidth32, PciAddr , &Value, &NBPtr->MemPtr->StdHeader);
+ 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) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ } else {
+ IDS_ERROR_TRAP;
+ }
+ } 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);
+ }
+ }
+ }
+ } else {
+ IDS_ERROR_TRAP; // Invalid bit field index
+ }
+ return Value;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes bit field translation table
+ *
+* @param[in,out] *NBRegTable - Pointer to the NB Table *
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableOr (
+ IN OUT TSEFO *NBRegTable
+ )
+{
+ UINT16 i;
+ for (i = 0; i <= BFEndOfList; i++) {
+ NBRegTable[i] = 0;
+ }
+
+ 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, 0x10C), 0, 0, BFDctCfgSel);
+
+ 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, 0x7C), 31, 0, BFDramInitRegReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x80), 31, 0, BFDramBankAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x88), 31, 0, BFDramTimingLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 31, 0, BFDramConfigLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31, 0, BFDramConfigHiReg);
+ 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, 0x98), 31, 31, BFDctAccessDone);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 17, 0, BFMrsAddress);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 20, 18, BFMrsBank);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 23, 21, BFMrsChipSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 26, 26, BFSendMrsCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 27, 27, BFDeassertMemRstX);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 28, 28, BFAssertCke);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 29, 29, BFSendZQCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 30, 30, BFSendCtrlWord);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 31, BFEnDramInit);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 7, 7, BFLevel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 12, 12, BFMrsQoff);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 17, 16, BFTref);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 18, 18, BFDisAutoRefresh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 15, 12, BFX4Dimm);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 16, 16, BFUnBuffDimm);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 4, 0, BFMemClkFreq);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 7, 7, BFMemClkFreqVal);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 11, 10, BFZqcsInterval);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 14, 14, BFDisDramInterface);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 21, 21, BFFreqChgInProg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 5, 5, BFSubMemclkRegDly);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 15, 8, BFCtrlWordCS);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 31, 0, BFDctSelBaseAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 31, 0, BFDctSelBaseOffsetReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x200), 31, 0, BFDramTiming0);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x204), 31, 0, BFDramTiming1);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x208), 31, 0, BFDramTiming2);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x20C), 31, 0, BFDramTiming3);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x210), 31, 0, BFDramNBP0);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x210), 31, 22, BFMaxLatency);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x214), 31, 0, BFDramTiming4);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x218), 31, 0, BFDramTiming5);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x21C), 31, 0, BFDramTiming6);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x22C), 31, 0, BFDramTiming10);
+
+ 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), 31, 0, BFDramODTCtlReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 3, 2, BFCmdTestEnable);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 7, 5, BFCmdType);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 10, 10, BFTestStatus);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 11, 11, BFSendCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x250), 12, 12, BFCmdSendInProg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x254), 26, 24, BFTgtChipSelectA );
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x260), 20, 0, BFCmdCount);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x268), 17, 0, BFNibbleErrSts);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x270), 18, 0, BFDataPrbsSeed);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x28C), 31, 0, BFDramCmd2Reg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x160), 5, 1, BFNbFid);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x160), 7, 7, BFNbDid);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (5, 0x170), 14, 14, BFSwNbPstateLoDis);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 31, 0, BFODCControl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x04, 31, 0, BFAddrTmgControl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 0, 0, BFWrtLvTrEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 1, 1, BFWrtLvTrMode);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 5, 4, BFTrDimmSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 11, 8, BFWrLvOdt);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 12, 12, BFWrLvOdtEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 13, 13, BFDqsRcvTrEn);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0B, 31, 0, BFDramPhyStatusReg);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0C, 31, 16, BFPhyFence);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0FE013, _NOT_USED_, _NOT_USED_, BFPllRegWaitTime);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0FE006, _NOT_USED_, _NOT_USED_, BFPllLockTime);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F0F1F, _NOT_USED_, _NOT_USED_, BFDataRxVioLvl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F2F1F, _NOT_USED_, _NOT_USED_, BFClkRxVioLvl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F4009, _NOT_USED_, _NOT_USED_, BFCmpVioLvl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F8F1F, _NOT_USED_, _NOT_USED_, BFCmdRxVioLvl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0FC01F, _NOT_USED_, _NOT_USED_, BFAddrRxVioLvl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F0F30, _NOT_USED_, _NOT_USED_, BFBlockRxDqsLock);
+//DMACH
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0FE003, _NOT_USED_, _NOT_USED_, BFDisablePredriverCal);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 2, 0, BFCkeDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 6, 4, BFCsOdtDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 10, 8, BFAddrCmdDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 14, 12, BFClkDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 18, 16, BFDataDrvStren);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 22, 20, BFDqsDrvStren);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D08E003, _NOT_USED_, _NOT_USED_, BFDisablePredriverCal);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F0F02, _NOT_USED_, _NOT_USED_, BFDataByteTxPreDriverCal);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F0F06, _NOT_USED_, _NOT_USED_, BFDataByteTxPreDriverCal2Pad1);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F0F0A, _NOT_USED_, _NOT_USED_, BFDataByteTxPreDriverCal2Pad2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F8006, _NOT_USED_, _NOT_USED_, BFCmdAddr0TxPreDriverCal2Pad1);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F800A, _NOT_USED_, _NOT_USED_, BFCmdAddr0TxPreDriverCal2Pad2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F8106, _NOT_USED_, _NOT_USED_, BFCmdAddr1TxPreDriverCal2Pad1);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F810A, _NOT_USED_, _NOT_USED_, BFCmdAddr1TxPreDriverCal2Pad2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0FC006, _NOT_USED_, _NOT_USED_, BFAddrTxPreDriverCal2Pad1);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0FC00A, _NOT_USED_, _NOT_USED_, BFAddrTxPreDriverCal2Pad2);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0FC00E, _NOT_USED_, _NOT_USED_, BFAddrTxPreDriverCal2Pad3);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0FC012, _NOT_USED_, _NOT_USED_, BFAddrTxPreDriverCal2Pad4);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F8002, _NOT_USED_, _NOT_USED_, BFCmdAddr0TxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F8102, _NOT_USED_, _NOT_USED_, BFCmdAddr1TxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0FC002, _NOT_USED_, _NOT_USED_, BFAddrTxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F2002, _NOT_USED_, _NOT_USED_, BFClock0TxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F2102, _NOT_USED_, _NOT_USED_, BFClock1TxPreDriverCalPad0);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x0D0F2202, _NOT_USED_, _NOT_USED_, BFClock2TxPreDriverCalPad0);
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ * MemRecNIsIdSupportedOr
+ * 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 Orochi.
+ * @return FALSE - This node is not a Orochi.
+ *
+ */
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ )
+{
+ if (((LogicalIdPtr->Family & AMD_FAMILY_15_OR) != 0)
+ && ((LogicalIdPtr->Revision & AMD_F15_ALL) != 0)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnor.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnor.h
new file mode 100644
index 0000000000..6fbf8a637c
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnor.h
@@ -0,0 +1,129 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mnor.h
+ *
+ * Northbridge Orochi Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 49947 $ @e \$Date: 2011-03-30 17:32:05 -0600 (Wed, 30 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MRNOR_H_
+#define _MRNOR_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_DIES_PER_SOCKET_OR 2
+#define MAX_DCTS_PER_NODE_OR 2
+#define MAX_CHANNELS_PER_DCT_OR 1
+
+#define _4GB_RJ8 ((UINT32)4 << (30 - 8))
+#define MTRR_VALID 11
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemRecConstructNBBlockOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ );
+
+VOID
+MemRecNSwitchDctOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ );
+
+VOID
+MemRecNSwitchChannelOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ );
+
+VOID
+MemRecNSetDramOdtOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN ODT_MODE OdtMode,
+ IN UINT8 ChipSelect,
+ IN UINT8 TargetCS
+ );
+
+AGESA_STATUS
+MemRecNMemInitOr (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+BOOLEAN
+MemRecNPlatformSpecOr (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemRecNStartupDCTOr (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+MemRecNSetMaxLatencyOr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 MaxRcvEnDly
+ );
+
+#endif /* _MRNOR_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnprotoor.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnprotoor.c
new file mode 100644
index 0000000000..b06c17d300
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/OR/mrnprotoor.c
@@ -0,0 +1,61 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnproto.c
+ *
+ * Northbridge support functions for Errata and early samples Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+
+
+#include "AGESA.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_OR_MRNPROTOOR_FILECODE
+/*
+ *-----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/PH/mrnPh.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/PH/mrnPh.c
new file mode 100644
index 0000000000..724469b04e
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/PH/mrnPh.c
@@ -0,0 +1,666 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnPh.c
+ *
+ * Common Northbridge functions for Pharaoh Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 48317 $ @e \$Date: 2011-03-07 10:38:14 -0700 (Mon, 07 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrnda.h"
+#include "mrnPh.h"
+#include "heapManager.h"
+#include "AdvancedApi.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_PH_MRNPH_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#define SPLIT_CHANNEL 0x20000000
+#define CHANNEL_SELECT 0x10000000
+#define MAX_DELAYS 9 /* 8 data bytes + 1 ECC byte */
+#define MAX_DIMMS 4 /* 4 DIMMs per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTablePh (
+ IN OUT TSEFO *NBRegTable
+ );
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ );
+
+UINT32
+STATIC
+MemRecNcmnGetSetTrainDlyPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ );
+
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+STATIC CONST UINT32 RecModeDefRegArrayPh[] = {
+ BFDramControlReg, 0x320C2A06,
+ BFDramBankAddrReg, 0x00001111,
+ BFDramMRSReg, 0x000400A4,
+ BFDramTimingLoReg, 0x000A0092,
+ BFDramTimingHiReg, 0xB6D218FF,
+ BFDramConfigLoReg, 0x00000000,
+ BFDramConfigHiReg, 0x1F48010B,
+ NULL
+};
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] NodeID - Node ID for this NB block
+ *
+ * @return TRUE - This node is a RB and this NB block has been initialized
+ * @return FALSE - This node is not a RB
+ */
+
+BOOLEAN
+MemRecConstructNBBlockPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 i;
+ UINT8 Dct;
+ UINT8 Channel;
+ DIE_STRUCT *MCTPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemRecNIsIdSupportedPh (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
+ return FALSE;
+ }
+
+ //
+ // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
+ //
+ MCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_DA * (
+ sizeof (DCT_STRUCT) + (
+ MAX_CHANNELS_PER_DCT_DA * (
+ sizeof (CH_DEF_STRUCT) + (
+ MAX_DIMMS * MAX_DELAYS * NUMBER_OF_DELAY_TABLES
+ )
+ )
+ )
+ ) + (sizeof (TSEFO) * BFEndOfList);
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0);
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
+ return FALSE;
+ }
+
+ MemPtr->DieCount = 1;
+ MCTPtr->DctCount = MAX_DCTS_PER_NODE_DA;
+ MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_DA * sizeof (DCT_STRUCT);
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_DA; Dct++) {
+ MCTPtr->DctData[Dct].Dct = Dct;
+ MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_DA;
+ MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[0].ChannelID = Dct;
+ AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_DA * sizeof (CH_DEF_STRUCT);
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_DA; Channel++) {
+ MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = (UINT16 *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS) * 2;
+ MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[Channel].Dct = Dct;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS);
+ }
+ }
+
+ //
+ // Initialize NB block's variables
+ //
+ NBPtr->NBRegTable = (TSEFO *) AllocHeapParams.BufferPtr;
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->RefPtr = MemPtr->ParameterListPtr;
+ NBPtr->MCTPtr = MCTPtr;
+ NBPtr->SPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+ NBPtr->AllNodeSPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+
+ NBPtr->DctCachePtr = NBPtr->DctCache;
+
+ MemRecNInitNBRegTablePh (NBPtr->NBRegTable);
+ NBPtr->Dct = 0;
+ NBPtr->Channel = 0;
+ NBPtr->VarMtrrHiMsk = MemRecGetVarMtrrHiMsk (&(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+
+ LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &NBPtr->MemPtr->StdHeader);
+ LibAmdMemFill (NBPtr->IsSupported, FALSE, sizeof (NBPtr->IsSupported), &NBPtr->MemPtr->StdHeader);
+ for (i = 0; i < NumberOfHooks; i++) {
+ NBPtr->FamilySpecificHook[i] = (BOOLEAN (*) (MEM_NB_BLOCK *, VOID *)) MemRecDefTrue;
+ }
+
+ NBPtr->InitRecovery = MemRecNMemInitNb;
+
+ NBPtr->RecModeDefRegArray = RecModeDefRegArrayPh;
+
+ NBPtr->SwitchNodeRec = (VOID (*) (MEM_NB_BLOCK *, UINT8)) MemRecDefRet;
+ NBPtr->SwitchDCT = MemRecNSwitchDctPh;
+ NBPtr->SwitchChannel = MemRecNSwitchChannelPh;
+ NBPtr->SetMaxLatency = MemRecNSetMaxLatencyNb;
+ NBPtr->GetSysAddrRec = MemRecNGetMCTSysAddrNb;
+ NBPtr->SendMrsCmd = MemRecNSendMrsCmdNb;
+ NBPtr->sendZQCmd = MemRecNSendZQCmdNb;
+ NBPtr->SetDramOdtRec = MemRecNSetDramOdtNb;
+
+ NBPtr->GetBitField = MemRecNGetBitFieldNb;
+ NBPtr->SetBitField = MemRecNSetBitFieldNb;
+ NBPtr->GetTrainDly = MemRecNGetTrainDlyNb;
+ NBPtr->SetTrainDly = MemRecNSetTrainDlyNb;
+ NBPtr->MemRecNCmnGetSetFieldNb = MemRecNCmnGetSetFieldPh;
+ NBPtr->MemRecNcmnGetSetTrainDlyNb = MemRecNcmnGetSetTrainDlyPh;
+ NBPtr->MemRecNSwitchDctNb = MemRecNSwitchDctPh;
+ NBPtr->TrainingFlow = MemNRecTrainingFlowNb;
+ NBPtr->MemRecNInitializeMctNb = MemRecNInitializeMctDA;
+ NBPtr->MemRecNFinalizeMctNb = MemRecNFinalizeMctDA;
+ NBPtr->IsSupported[DramModeBeforeDimmPres] = TRUE;
+ NBPtr->IsSupported[CheckClearOnDimmMirror] = TRUE;
+ MemRecNSwitchDctPh (NBPtr, 0);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchDctPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ )
+{
+ NBPtr->Dct = Dct & 1;
+ NBPtr->SPDPtr = &(NBPtr->AllNodeSPDPtr[Dct * MAX_DIMMS_PER_CHANNEL]);
+ NBPtr->DCTPtr = &(NBPtr->MCTPtr->DctData[NBPtr->Dct]);
+
+ MemRecNSwitchChannelPh (NBPtr, NBPtr->Channel);
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchChannelPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ )
+{
+ NBPtr->Channel = Channel & 1;
+ NBPtr->ChannelPtr = &(NBPtr->DCTPtr->ChData[NBPtr->Channel]);
+}
+/*----------------------------------------------------------------------------
+ * 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
+STATIC
+MemRecNcmnGetSetTrainDlyPh (
+ 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 < 4);
+ ASSERT (Byte <= 8);
+
+ 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:
+ Field &= ~ 0x0001;
+ 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;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (IsSet) {
+ if (TrnDly == AccessPhRecDly) {
+ Value = NBPtr->DctCachePtr->PhRecReg[Index & 0x03];
+ }
+
+ Value = ((UINT32)Field << Offset) | (Value & (~((UINT32)0xFF << Offset)));
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[Index & 0x03] = Value;
+ }
+ } else {
+ Value = (Value >> Offset) & 0xFF;
+ }
+
+ return Value;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] IsSet - Indicates if the function will set or get
+ * @param[in] FieldName - Name of field to be set
+ * @param[in] Field - Value to be programmed
+ *
+ * @return value read, if the function is used as a "get"
+ */
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ SBDFO Address;
+ PCI_ADDR PciAddr;
+ UINT8 Type;
+ UINT32 Value;
+ UINT32 Highbit;
+ UINT32 Lowbit;
+ UINT32 Mask;
+
+ Value = 0;
+ if (FieldName < BFEndOfList) {
+ Address = NBPtr->NBRegTable[FieldName];
+ if (Address) {
+ Lowbit = TSEFO_END (Address);
+ Highbit = TSEFO_START (Address);
+ Type = TSEFO_TYPE (Address);
+
+ // If Fn2 and DCT1 selected, set Address to be 1xx
+ if (((Address & 0xF000) == 0x2000) && NBPtr->Dct) {
+ Address |= 0x0100;
+ }
+ if ((Address >> 29) == ((DCT_PHY_ACCESS << 1) | 1)) {
+ // Special DCT Phy access
+ Address &= 0x0FFFFFFF;
+ Lowbit = 0;
+ Highbit = 16;
+ } else {
+ // Normal DCT Phy access
+ Address = TSEFO_OFFSET (Address);
+ }
+
+
+ if (Type == NB_ACCESS) {
+ Address |= (((UINT32) (24 + 0)) << 15);
+ PciAddr.AddressValue = Address;
+ LibAmdPciRead (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+ } else {
+ IDS_ERROR_TRAP;
+ }
+
+ 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;
+
+ if (Type == NB_ACCESS) {
+ PciAddr.AddressValue = Address;
+ LibAmdPciWrite (AccessWidth32, PciAddr , &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ } else {
+ IDS_ERROR_TRAP;
+ }
+ } 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);
+ }
+ }
+ }
+ } else {
+ IDS_ERROR_TRAP; // Invalid bit field index
+ }
+ return Value;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes bit field translation table
+ *
+ * @param[in,out] *NBRegTable - Pointer to the NB Table *
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTablePh (
+ IN OUT TSEFO *NBRegTable
+ )
+{
+ UINT16 i;
+ for (i = 0; i <= BFEndOfList; i++) {
+ NBRegTable[i] = 0;
+ }
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x00), 31, 0, BFDevVendorIDReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x60), 2, 0, BFNodeID);
+
+ 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 (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), 31, 0, BFDramControlReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 0, BFDramInitRegReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x80), 31, 0, BFDramBankAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 31, 0, BFDramMRSReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 9, 7, BFDramTerm);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 11, 10, BFDramTermDyn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x88), 31, 0, BFDramTimingLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 31, 0, BFDramTimingHiReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 31, 0, BFDramConfigLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31, 0, BFDramConfigHiReg);
+ 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, 0x98), 31, 31, BFDctAccessDone);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (3, 0xD4), 4, 0, BFNbFid);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 18, 18, BFDqsRcvEnTrain);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 31, 22, BFMaxLatency);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 15, 0, BFMrsAddress);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 18, 16, BFMrsBank);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 22, 20, BFMrsChipSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 26, 26, BFSendMrsCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 27, 27, BFDeassertMemRstX);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 28, 28, BFAssertCke);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 29, 29, BFSendZQCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 30, 30, BFSendCtrlWord);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 31, BFEnDramInit);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 7, 7, BFLevel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 12, 12, BFMrsQoff);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 18, 18, BFDisAutoRefresh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 0, 0, BFInitDram);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 16, 16, BFUnBuffDimm);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 8, 8, BFDdr3Mode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 9, 9, BFLegacyBiosMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 11, 10, BFZqcsInterval);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 14, 14, BFDisDramInterface);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 6, 6, BFOdtSwizzle);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 15, 8, BFCtrlWordCS);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 8, 8, BFDramEnabled);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 31, 0, BFDctSelBaseAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 31, 0, BFDctSelBaseOffsetReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 6, 2, BFMctWrLimit);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 12, 12, BFPrefCpuDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 13, 13, BFPrefIoDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 29, 29, BFFlushWrOnStpGnt);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 31, 0, BFODCControl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x04, 31, 0, BFAddrTmgControl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 0, 0, BFWrtLvTrEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 1, 1, BFWrtLvTrMode);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 5, 4, BFTrDimmSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 11, 8, BFWrLvOdt);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 12, 12, BFWrLvOdtEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 30, 30, BFDisAutoComp);
+
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ * MemRecNIsIdSupportedPh
+ * 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
+ *
+ */
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ )
+{
+
+ if ((LogicalIdPtr->Revision & AMD_F10_PH_ALL) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/PH/mrnPh.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/PH/mrnPh.h
new file mode 100644
index 0000000000..8fe4ade6c8
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/PH/mrnPh.h
@@ -0,0 +1,96 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnPh.h
+ *
+ * Northbridge PH Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MRNPH_H_
+#define _MRNPH_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+#define _4GB_RJ8 ((UINT32)4 << (30 - 8))
+#define MTRR_VALID 11
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemRecConstructNBBlockPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ );
+
+VOID
+MemRecNSwitchDctPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ );
+
+VOID
+MemRecNSwitchChannelPh (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ );
+
+#endif /* _MRNPH_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/RB/mrnRb.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/RB/mrnRb.c
new file mode 100644
index 0000000000..5a7418623e
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/RB/mrnRb.c
@@ -0,0 +1,665 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnRb.c
+ *
+ * Common Northbridge functions for RidgeBack Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 48317 $ @e \$Date: 2011-03-07 10:38:14 -0700 (Mon, 07 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mrnda.h"
+#include "mrnRb.h"
+#include "heapManager.h"
+#include "AdvancedApi.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_NB_RB_MRNRB_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#define SPLIT_CHANNEL 0x20000000
+#define CHANNEL_SELECT 0x10000000
+#define MAX_DELAYS 9 /* 8 data bytes + 1 ECC byte */
+#define MAX_DIMMS 4 /* 4 DIMMs per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableRb (
+ IN OUT TSEFO *NBRegTable
+ );
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ );
+
+UINT32
+STATIC
+MemRecNcmnGetSetTrainDlyRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ );
+
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+STATIC CONST UINT32 RecModeDefRegArrayRb[] = {
+ BFDramControlReg, 0x320C2A06,
+ BFDramBankAddrReg, 0x00001111,
+ BFDramMRSReg, 0x000400A4,
+ BFDramTimingLoReg, 0x000A0092,
+ BFDramTimingHiReg, 0xB6D218FF,
+ BFDramConfigLoReg, 0x00000000,
+ BFDramConfigHiReg, 0x1F48010B,
+ NULL
+};
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] NodeID - Node ID for this NB block
+ *
+ * @return TRUE - This node is a RB and this NB block has been initialized
+ * @return FALSE - This node is not a RB
+ */
+
+BOOLEAN
+MemRecConstructNBBlockRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ )
+{
+ UINT8 i;
+ UINT8 Dct;
+ UINT8 Channel;
+ DIE_STRUCT *MCTPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+ //
+ // Determine if this is the expected NB Type
+ //
+ GetLogicalIdOfSocket (MemPtr->DiesPerSystem[NodeID].SocketId, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+ if (!MemRecNIsIdSupportedRb (NBPtr, &(MemPtr->DiesPerSystem[NodeID].LogicalCpuid))) {
+ return FALSE;
+ }
+
+ //
+ // Allocate buffer for DCT_STRUCTs and CH_DEF_STRUCTs
+ //
+ MCTPtr = &MemPtr->DiesPerSystem[NodeID];
+ AllocHeapParams.RequestedBufferSize = MAX_DCTS_PER_NODE_DA * (
+ sizeof (DCT_STRUCT) + (
+ MAX_CHANNELS_PER_DCT_DA * (
+ sizeof (CH_DEF_STRUCT) + (
+ MAX_DIMMS * MAX_DELAYS * NUMBER_OF_DELAY_TABLES
+ )
+ )
+ )
+ ) + (sizeof (TSEFO) * BFEndOfList);
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DCT_STRUCT_HANDLE, NodeID, 0, 0);
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
+ return FALSE;
+ }
+
+ MCTPtr->DctCount = MAX_DCTS_PER_NODE_DA;
+ MCTPtr->DctData = (DCT_STRUCT *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += MAX_DCTS_PER_NODE_DA * sizeof (DCT_STRUCT);
+ for (Dct = 0; Dct < MAX_DCTS_PER_NODE_DA; Dct++) {
+ MCTPtr->DctData[Dct].Dct = Dct;
+ MCTPtr->DctData[Dct].ChannelCount = MAX_CHANNELS_PER_DCT_DA;
+ MCTPtr->DctData[Dct].ChData = (CH_DEF_STRUCT *) AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[0].ChannelID = Dct;
+ AllocHeapParams.BufferPtr += MAX_CHANNELS_PER_DCT_DA * sizeof (CH_DEF_STRUCT);
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_DCT_DA; Channel++) {
+ MCTPtr->DctData[Dct].ChData[Channel].RcvEnDlys = (UINT16 *) AllocHeapParams.BufferPtr;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS) * 2;
+ MCTPtr->DctData[Dct].ChData[Channel].WrDqsDlys = AllocHeapParams.BufferPtr;
+ MCTPtr->DctData[Dct].ChData[Channel].Dct = Dct;
+ AllocHeapParams.BufferPtr += (MAX_DIMMS * MAX_DELAYS);
+ }
+ }
+
+ //
+ // Initialize NB block's variables
+ //
+ NBPtr->NBRegTable = (TSEFO *) AllocHeapParams.BufferPtr;
+ NBPtr->MemPtr = MemPtr;
+ NBPtr->RefPtr = MemPtr->ParameterListPtr;
+ NBPtr->MCTPtr = MCTPtr;
+ NBPtr->SPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+ NBPtr->AllNodeSPDPtr = &MemPtr->SpdDataStructure[MemPtr->DiesPerSystem[NodeID].SocketId * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL];
+
+ NBPtr->DctCachePtr = NBPtr->DctCache;
+
+ MemRecNInitNBRegTableRb (NBPtr->NBRegTable);
+ NBPtr->Dct = 0;
+ NBPtr->Channel = 0;
+ NBPtr->VarMtrrHiMsk = MemRecGetVarMtrrHiMsk (&(MemPtr->DiesPerSystem[NodeID].LogicalCpuid), &(MemPtr->StdHeader));
+
+ LibAmdMemFill (NBPtr->DctCache, 0, sizeof (NBPtr->DctCache), &NBPtr->MemPtr->StdHeader);
+ LibAmdMemFill (NBPtr->IsSupported, FALSE, sizeof (NBPtr->IsSupported), &NBPtr->MemPtr->StdHeader);
+ for (i = 0; i < NumberOfHooks; i++) {
+ NBPtr->FamilySpecificHook[i] = (BOOLEAN (*) (MEM_NB_BLOCK *, VOID *)) MemRecDefTrue;
+ }
+
+ NBPtr->InitRecovery = MemRecNMemInitNb;
+
+ NBPtr->RecModeDefRegArray = RecModeDefRegArrayRb;
+
+ NBPtr->SwitchNodeRec = (VOID (*) (MEM_NB_BLOCK *, UINT8)) MemRecDefRet;
+ NBPtr->SwitchDCT = MemRecNSwitchDctRb;
+ NBPtr->SwitchChannel = MemRecNSwitchChannelRb;
+ NBPtr->SetMaxLatency = MemRecNSetMaxLatencyNb;
+ NBPtr->GetSysAddrRec = MemRecNGetMCTSysAddrNb;
+ NBPtr->SendMrsCmd = MemRecNSendMrsCmdNb;
+ NBPtr->sendZQCmd = MemRecNSendZQCmdNb;
+ NBPtr->SetDramOdtRec = MemRecNSetDramOdtNb;
+
+ NBPtr->GetBitField = MemRecNGetBitFieldNb;
+ NBPtr->SetBitField = MemRecNSetBitFieldNb;
+ NBPtr->GetTrainDly = MemRecNGetTrainDlyNb;
+ NBPtr->SetTrainDly = MemRecNSetTrainDlyNb;
+ NBPtr->MemRecNCmnGetSetFieldNb = MemRecNCmnGetSetFieldRb;
+ NBPtr->MemRecNcmnGetSetTrainDlyNb = MemRecNcmnGetSetTrainDlyRb;
+ NBPtr->MemRecNSwitchDctNb = MemRecNSwitchDctRb;
+ NBPtr->TrainingFlow = MemNRecTrainingFlowNb;
+ NBPtr->MemRecNInitializeMctNb = MemRecNInitializeMctDA;
+ NBPtr->MemRecNFinalizeMctNb = MemRecNFinalizeMctDA;
+ NBPtr->IsSupported[DramModeBeforeDimmPres] = TRUE;
+ NBPtr->IsSupported[CheckClearOnDimmMirror] = TRUE;
+ MemRecNSwitchDctRb (NBPtr, 0);
+
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchDctRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ )
+{
+ NBPtr->Dct = Dct & 1;
+ NBPtr->SPDPtr = &(NBPtr->AllNodeSPDPtr[Dct * MAX_DIMMS_PER_CHANNEL]);
+ NBPtr->DCTPtr = &(NBPtr->MCTPtr->DctData[NBPtr->Dct]);
+
+ MemRecNSwitchChannelRb (NBPtr, NBPtr->Channel);
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSwitchChannelRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ )
+{
+ NBPtr->Channel = Channel & 1;
+ NBPtr->ChannelPtr = &(NBPtr->DCTPtr->ChData[NBPtr->Channel]);
+}
+/*----------------------------------------------------------------------------
+ * 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
+STATIC
+MemRecNcmnGetSetTrainDlyRb (
+ 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 < 4);
+ ASSERT (Byte <= 8);
+
+ 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:
+ Field &= ~ 0x0001;
+ 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;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (IsSet) {
+ if (TrnDly == AccessPhRecDly) {
+ Value = NBPtr->DctCachePtr->PhRecReg[Index & 0x03];
+ }
+
+ Value = ((UINT32)Field << Offset) | (Value & (~((UINT32)0xFF << Offset)));
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ if (TrnDly == AccessPhRecDly) {
+ NBPtr->DctCachePtr->PhRecReg[Index & 0x03] = Value;
+ }
+ } else {
+ Value = (Value >> Offset) & 0xFF;
+ }
+
+ return Value;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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] IsSet - Indicates if the function will set or get
+ * @param[in] FieldName - Name of field to be set
+ * @param[in] Field - Value to be programmed
+ *
+ * @return value read, if the function is used as a "get"
+ */
+
+UINT32
+STATIC
+MemRecNCmnGetSetFieldRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 IsSet,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ SBDFO Address;
+ PCI_ADDR PciAddr;
+ UINT8 Type;
+ UINT32 Value;
+ UINT32 Highbit;
+ UINT32 Lowbit;
+ UINT32 Mask;
+
+ Value = 0;
+ if (FieldName < BFEndOfList) {
+ Address = NBPtr->NBRegTable[FieldName];
+ if (Address) {
+ Lowbit = TSEFO_END (Address);
+ Highbit = TSEFO_START (Address);
+ Type = TSEFO_TYPE (Address);
+
+ // If Fn2 and DCT1 selected, set Address to be 1xx
+ if (((Address & 0xF000) == 0x2000) && NBPtr->Dct) {
+ Address |= 0x0100;
+ }
+ if ((Address >> 29) == ((DCT_PHY_ACCESS << 1) | 1)) {
+ // Special DCT Phy access
+ Address &= 0x0FFFFFFF;
+ Lowbit = 0;
+ Highbit = 16;
+ } else {
+ // Normal DCT Phy access
+ Address = TSEFO_OFFSET (Address);
+ }
+
+
+ if (Type == NB_ACCESS) {
+ Address |= (((UINT32) (24 + 0)) << 15);
+ PciAddr.AddressValue = Address;
+ LibAmdPciRead (AccessWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+ } else {
+ IDS_ERROR_TRAP;
+ }
+
+ 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;
+
+ if (Type == NB_ACCESS) {
+ PciAddr.AddressValue = Address;
+ LibAmdPciWrite (AccessWidth32, PciAddr , &Value, &NBPtr->MemPtr->StdHeader);
+ } else if (Type == DCT_PHY_ACCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ while (MemRecNGetBitFieldNb (NBPtr, BFDctAccessDone) == 0) {}
+ } else {
+ IDS_ERROR_TRAP;
+ }
+ } 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);
+ }
+ }
+ }
+ } else {
+ IDS_ERROR_TRAP; // Invalid bit field index
+ }
+ return Value;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes bit field translation table
+ *
+ * @param[in,out] *NBRegTable - Pointer to the NB Table *
+ */
+
+VOID
+STATIC
+MemRecNInitNBRegTableRb (
+ IN OUT TSEFO *NBRegTable
+ )
+{
+ UINT16 i;
+ for (i = 0; i <= BFEndOfList; i++) {
+ NBRegTable[i] = 0;
+ }
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x00), 31, 0, BFDevVendorIDReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (0, 0x60), 2, 0, BFNodeID);
+
+ 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 (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), 31, 0, BFDramControlReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 0, BFDramInitRegReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x80), 31, 0, BFDramBankAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 31, 0, BFDramMRSReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 9, 7, BFDramTerm);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x84), 11, 10, BFDramTermDyn);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x88), 31, 0, BFDramTimingLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 31, 0, BFDramTimingHiReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 31, 0, BFDramConfigLoReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 31, 0, BFDramConfigHiReg);
+ 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, 0x98), 31, 31, BFDctAccessDone);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (3, 0xD4), 4, 0, BFNbFid);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 18, 18, BFDqsRcvEnTrain);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x78), 31, 22, BFMaxLatency);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 15, 0, BFMrsAddress);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 18, 16, BFMrsBank);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 22, 20, BFMrsChipSel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 26, 26, BFSendMrsCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 27, 27, BFDeassertMemRstX);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 28, 28, BFAssertCke);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 29, 29, BFSendZQCmd);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 30, 30, BFSendCtrlWord);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 31, 31, BFEnDramInit);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 7, 7, BFLevel);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x7C), 12, 12, BFMrsQoff);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x8C), 18, 18, BFDisAutoRefresh);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 0, 0, BFInitDram);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x90), 16, 16, BFUnBuffDimm);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 8, 8, BFDdr3Mode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 9, 9, BFLegacyBiosMode);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 11, 10, BFZqcsInterval);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x94), 14, 14, BFDisDramInterface);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 6, 6, BFOdtSwizzle);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0xA8), 15, 8, BFCtrlWordCS);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 8, 8, BFDramEnabled);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x110), 31, 0, BFDctSelBaseAddrReg);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x114), 31, 0, BFDctSelBaseOffsetReg);
+
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 6, 2, BFMctWrLimit);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 12, 12, BFPrefCpuDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 13, 13, BFPrefIoDis);
+ MAKE_TSEFO (NBRegTable, NB_ACCESS, _FN (2, 0x11C), 29, 29, BFFlushWrOnStpGnt);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x00, 31, 0, BFODCControl);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x04, 31, 0, BFAddrTmgControl);
+
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 0, 0, BFWrtLvTrEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 1, 1, BFWrtLvTrMode);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 5, 4, BFTrDimmSel);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 11, 8, BFWrLvOdt);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 12, 12, BFWrLvOdtEn);
+ MAKE_TSEFO (NBRegTable, DCT_PHY_ACCESS, 0x08, 30, 30, BFDisAutoComp);
+
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ * MemRecNIsIdSupportedRb
+ * 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
+ *
+ */
+BOOLEAN
+STATIC
+MemRecNIsIdSupportedRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID *LogicalIdPtr
+ )
+{
+
+ if ((LogicalIdPtr->Revision & AMD_F10_RB_ALL) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/RB/mrnRb.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/RB/mrnRb.h
new file mode 100644
index 0000000000..9915c76bb4
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/RB/mrnRb.h
@@ -0,0 +1,96 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnRb.h
+ *
+ * Northbridge RB Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MRNRB_H_
+#define _MRNRB_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+#define _4GB_RJ8 ((UINT32)4 << (30 - 8))
+#define MTRR_VALID 11
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+BOOLEAN
+MemRecConstructNBBlockRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT MEM_DATA_STRUCT *MemPtr,
+ IN UINT8 NodeID
+ );
+
+VOID
+MemRecNSwitchDctRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Dct
+ );
+
+VOID
+MemRecNSwitchChannelRb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Channel
+ );
+
+#endif /* _MRNRB_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrn.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrn.c
new file mode 100644
index 0000000000..44abf5e6d2
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrn.c
@@ -0,0 +1,189 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrn.c
+ *
+ * Common Northbridge functions for Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/NB)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "mm.h"
+#include "mn.h"
+#include "Filecode.h"
+#define FILECODE PROC_RECOVERY_MEM_NB_MRN_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#define MAX_DCTS_PER_DIE 2
+#define SPLIT_CHANNEL 0x20000000
+#define CHANNEL_SELECT 0x10000000
+#define MAX_DELAYS 9 /* 8 data bytes + 1 ECC byte */
+#define MAX_DIMMS 4 /* 4 DIMMs per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNGetBitFieldNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BIT_FIELD_NAME FieldName
+ )
+{
+ return NBPtr->MemRecNCmnGetSetFieldNb (NBPtr, 0, FieldName, 0);
+}
+
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSetBitFieldNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BIT_FIELD_NAME FieldName,
+ IN UINT32 Field
+ )
+{
+ NBPtr->MemRecNCmnGetSetFieldNb (NBPtr, 1, FieldName, Field);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNGetTrainDlyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar
+ )
+{
+ return NBPtr->MemRecNcmnGetSetTrainDlyNb (NBPtr, 0, TrnDly, DrbnVar, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+ * @param[in] Field - Value to be programmed
+ *
+ */
+
+VOID
+MemRecNSetTrainDlyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN TRN_DLY_TYPE TrnDly,
+ IN DRBN DrbnVar,
+ IN UINT16 Field
+ )
+{
+ NBPtr->MemRecNcmnGetSetTrainDlyNb (NBPtr, 1, TrnDly, DrbnVar, Field);
+}
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrndct.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrndct.c
new file mode 100644
index 0000000000..2333be70d5
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrndct.c
@@ -0,0 +1,1577 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrndct.c
+ *
+ * Northbridge common DCT support for Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/NB)
+ * @e \$Revision: 50454 $ @e \$Date: 2011-04-10 21:20:37 -0600 (Sun, 10 Apr 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "cpuFamRegisters.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mru.h"
+#include "ma.h"
+#include "Filecode.h"
+#define FILECODE PROC_RECOVERY_MEM_NB_MRNDCT_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define RECDEF_CSMASK_REG 0x00083FE0
+#define RECDEF_DRAM_BASE_REG 0x00000003
+
+
+/*----------------------------------------------------------------------------
+ * 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)[4]; ///< Pointer to slew rate table
+} REC_PHY_COMP_INIT_CLIENTNB;
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+VOID
+STATIC
+MemRecTCtlOnDimmMirrorNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BOOLEAN SetFlag
+ );
+
+VOID
+STATIC
+MemRecNSwapBitsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+STATIC
+MemRecNProgNbPstateDependentRegClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+STATIC
+MemRecNTrainPhyFenceNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ );
+
+VOID
+STATIC
+MemRecNCommonReadWritePatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 CmdType,
+ IN UINT16 ClCount
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function programs the memory controller with configuration parameters
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - An Error value lower than AGESA_ERROR may have occurred
+ * @return FALSE - An Error value greater than or equal to AGESA_ERROR may have occurred
+ */
+
+BOOLEAN
+MemRecNAutoConfigNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dimm;
+ UINT8 Dct;
+ UINT8 ChipSel;
+ UINT32 CSBase;
+ DCT_STRUCT *DCTPtr;
+ CH_DEF_STRUCT *ChannelPtr;
+ UINT16 i;
+
+ Dct = NBPtr->Dct;
+ DCTPtr = NBPtr->DCTPtr;
+ ChannelPtr = NBPtr->ChannelPtr;
+
+ //Prepare variables for future usage.
+ for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) {
+ if ((ChannelPtr->ChDimmValid & (UINT8) 1 << Dimm) != 0) {
+ DCTPtr->Timings.CsPresent |= (UINT16) 1 << (Dimm * 2);
+ if (((ChannelPtr->DimmDrPresent & (UINT8) 1 << Dimm) == 0) && ((ChannelPtr->DimmQrPresent & (UINT8) 1 << Dimm) == 0)) {
+ continue;
+ } else {
+ DCTPtr->Timings.CsPresent |= (UINT16) 1 << (Dimm * 2 + 1);
+ }
+ }
+ }
+
+ Dimm = NBPtr->DimmToBeUsed;
+
+ //Temporarily set all CS Base/Limit registers (corresponding to Dimms exist on a channel) with 256MB size for WL training.
+ CSBase = 0;
+ for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel++) {
+ if (DCTPtr->Timings.CsPresent & (UINT8) 1 << ChipSel) {
+
+ CSBase &= (UINT32) ~0x08; //Clear OnDimmMirror bit.
+ if (((ChipSel & 1) != 0) && ((ChannelPtr->DimmMirrorPresent & (UINT8) 1 << (ChipSel >> 1)) != 0)) {
+ CSBase |= (UINT32) 0x08; //Set OnDimmMirror bit.
+ }
+ MemRecNSetBitFieldNb (NBPtr, (BFCSBaseAddr0Reg + ChipSel), (CSBase | 0x01));
+ CSBase += 0x100000;
+ if ((ChipSel & 1) == 0) {
+ MemRecNSetBitFieldNb (NBPtr, (BFCSMask0Reg + (ChipSel >> 1)), RECDEF_CSMASK_REG);
+ }
+ }
+ }
+ MemRecNSetBitFieldNb (NBPtr, BFDramBaseReg0, RECDEF_DRAM_BASE_REG);
+ MemRecNSetBitFieldNb (NBPtr, BFDramLimitReg0, 0x70000);
+
+ // Disable the other DCT
+ NBPtr->MemRecNSwitchDctNb (NBPtr, Dct ^ 0x01);
+ MemRecNSetBitFieldNb (NBPtr, BFDisDramInterface, 1);
+ NBPtr->MemRecNSwitchDctNb (NBPtr, Dct);
+ if (Dct != 0) {
+ // If DCT 1, set DctSelBase registers
+ MemRecNSetBitFieldNb (NBPtr, BFDctSelBaseAddrReg, 0x00000003);
+ MemRecNSetBitFieldNb (NBPtr, BFDctSelBaseOffsetReg, 0x00000000);
+ }
+
+ // Use default values for common registers
+ i = 0;
+ while (NBPtr->RecModeDefRegArray[i] != NULL) {
+ MemRecNSetBitFieldNb (NBPtr, NBPtr->RecModeDefRegArray[i], NBPtr->RecModeDefRegArray[i + 1]);
+ i += 2;
+ }
+
+ // Other specific settings
+ MemRecNSetBitFieldNb (NBPtr, BFX4Dimm, ChannelPtr->Dimmx4Present );
+
+ if ((ChannelPtr->RegDimmPresent == 0) && (ChannelPtr->SODimmPresent == 0)) {
+ MemRecNSetBitFieldNb (NBPtr, BFUnBuffDimm, 1);
+ }
+
+ if ((NBPtr->ChannelPtr->RegDimmPresent != 0) && (NBPtr->ChannelPtr->TechType == DDR3_TECHNOLOGY)) {
+ MemRecNSetBitFieldNb (NBPtr, BFSubMemclkRegDly, 1);
+ }
+ MemRecNSetBitFieldNb (NBPtr, BFOdtSwizzle, 1);
+
+ return TRUE;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function gets platform specific config/timing values from the interface layer and
+ * programs them into DCT.
+ *
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return TRUE - An Error value lower than AGESA_ERROR may have occurred
+ * @return FALSE - An Error value greater than or equal to AGESA_ERROR may have occurred
+ */
+
+BOOLEAN
+MemRecNPlatformSpecNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 p;
+
+ p = 0;
+ for (p = 0; p < MAX_PLATFORM_TYPES; p++) {
+ if (NBPtr->MemPtr->GetPlatformCfg[p] (NBPtr->MemPtr, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr) == AGESA_SUCCESS) {
+ MemRecNSetBitFieldNb (NBPtr, BFODCControl, NBPtr->ChannelPtr->DctOdcCtl);
+ MemRecNSetBitFieldNb (NBPtr, BFAddrTmgControl, NBPtr->ChannelPtr->DctAddrTmg);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function reads MemClkFreqVal bit to see if the DIMMs are present in this node.
+ * If the DIMMs are present then set the DRAM Enable bit for this node.
+ *
+ * Setting dram init starts up the DCT state machine, initializes the
+ * dram devices with MRS commands, and kicks off any
+ * HW memory clear process that the chip is capable of. The sooner
+ * that dram init is set for all nodes, the faster the memory system
+ * initialization can complete. Thus, the init loop is unrolled into
+ * two loops so as to start the processes for non BSP nodes sooner.
+ * This procedure will not wait for the process to finish. Synchronization is
+ * handled elsewhere.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNStartupDCTNb (
+ 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.
+ // ------- Done in InitPhyComp_Nb -------
+ //
+ MemRecNSetBitFieldNb (NBPtr, BFDisAutoComp, 1);
+ MemRecUWait10ns (500, NBPtr->MemPtr);
+
+ //MemRecNSetBitFieldNb (NBPtr, BFInitDram, 1); // HW Dram init
+ AGESA_TESTPOINT (TpProcMemDramInit, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->TechPtr->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.
+ //
+ MemRecNSetBitFieldNb (NBPtr, BFDisAutoComp, 0);
+ MemRecUWait10ns (75000, NBPtr->MemPtr);
+
+ while (MemRecNGetBitFieldNb (NBPtr, BFDramEnabled) == 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes the DRAM devices on all DCTs at the same time
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNStartupDCTClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", NBPtr->Dct);
+
+ // Program D18F2x[1,0]9C_x0000_000B = 80000000h. #109999.
+ MemRecNSetBitFieldNb (NBPtr, BFDramPhyStatusReg, 0x80000000);
+
+ // Program D18F2x[1,0]9C_x0D0F_E013[PllRegWaitTime] = 0118h. #193770.
+ MemRecNSetBitFieldNb (NBPtr, BFPllRegWaitTime, 0x118);
+
+ // Phy Voltage Level Programming
+ MemRecNPhyVoltageLevelNb (NBPtr);
+
+ // Run frequency change sequence
+ MemRecNSetBitFieldNb (NBPtr, BFPllLockTime, NBPtr->FreqChangeParam->PllLockTimeDefault);
+ MemRecNSetBitFieldNb (NBPtr, BFMemClkFreq, 6);
+ MemRecNProgNbPstateDependentRegClientNb (NBPtr);
+ MemRecNSetBitFieldNb (NBPtr, BFMemClkFreqVal, 1);
+ MemRecNSetBitFieldNb (NBPtr, BFPllLockTime, 0x000F);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClkAlign=0\n");
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tEnDramInit = 1 for DCT%d\n", NBPtr->Dct);
+ MemRecNSetBitFieldNb (NBPtr, BFDbeGskMemClkAlignMode, 0);
+ MemRecNSetBitFieldNb (NBPtr, BFEnDramInit, 1);
+
+ // Run DramInit sequence
+ AGESA_TESTPOINT (TpProcMemDramInit, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->TechPtr->DramInit (NBPtr->TechPtr);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nMemClkFreq: %d MHz\n", DDR800_FREQUENCY);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNSetMaxLatencyNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT16 MaxRcvEnDly
+ )
+{
+ UINT16 SubTotal;
+
+ AGESA_TESTPOINT (TpProcMemRcvrCalcLatency, &(NBPtr->MemPtr->StdHeader));
+
+ // Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs UINTs.
+ SubTotal = 6 * 2;
+
+ // If registered DIMMs are being used then add 1 MEMCLK to the sub-total.
+ if (MemRecNGetBitFieldNb (NBPtr, BFUnBuffDimm) == 0) {
+ SubTotal += 2;
+ }
+
+ // if (AddrCmdSetup || CsOdtSetup || CkeSetup) then K := K + 2;
+ 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 += 8 - 5;
+
+ // Add the maximum (worst case) delay value of DqsRcvEnGrossDelay
+ // that exists across all DIMMs and byte lanes.
+ //
+ SubTotal += MaxRcvEnDly >> 5;
+
+ // Add 5.5 to the sub-total. 5.5 represents part of the processor
+ // specific constant delay value in the DRAM clock domain.
+ //
+ SubTotal += 5; // add 5.5 1/2MemClk
+
+ // 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).
+ //
+ // Simplified formula:
+ // SubTotal *= (Fn2xD4[NBFid]+4)/4
+ //
+ SubTotal = SubTotal * ((UINT16) MemRecNGetBitFieldNb (NBPtr, BFNbFid) + 4);
+ SubTotal /= 4;
+
+ // Add 5 NCLKs to the sub-total. 5 represents part of the processor
+ // specific constant value in the northbridge clock domain.
+ //
+ SubTotal += 5;
+
+ // Program the F2x[1, 0]78[MaxRdLatency] register with the total delay value
+ MemRecNSetBitFieldNb (NBPtr, BFMaxLatency, SubTotal);
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Set Dram ODT for mission mode and write leveling mode.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] OdtMode - Mission mode or write leveling mode
+ * @param[in] ChipSelect - Chip select number
+ * @param[in] TargetCS - Chip select number that is being trained
+ *
+ */
+
+VOID
+MemRecNSetDramOdtNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN ODT_MODE OdtMode,
+ IN UINT8 ChipSelect,
+ IN UINT8 TargetCS
+ )
+{
+ UINT8 DramTerm;
+ UINT8 DramTermDyn;
+
+ DramTerm = NBPtr->ChannelPtr->Reserved[0];
+ DramTermDyn = NBPtr->ChannelPtr->Reserved[1];
+
+ if (OdtMode == WRITE_LEVELING_MODE) {
+ if (ChipSelect == TargetCS) {
+ DramTerm = DramTermDyn;
+ MemRecNSetBitFieldNb (NBPtr, BFWrLvOdt, NBPtr->ChannelPtr->PhyWLODT[TargetCS >> 1]);
+ }
+ }
+ MemRecNSetBitFieldNb (NBPtr, BFDramTerm, DramTerm);
+ MemRecNSetBitFieldNb (NBPtr, BFDramTermDyn, DramTermDyn);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sends an MRS command
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNSendMrsCmdNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ BOOLEAN ClearODM;
+ ClearODM = FALSE;
+ if (NBPtr->IsSupported[CheckClearOnDimmMirror]) {
+ ClearODM = FALSE;
+ if ((NBPtr->MCTPtr->LogicalCpuid.Revision & AMD_F10_C0) != 0) {
+ if (NBPtr->IsSupported[CheckClearOnDimmMirror]) {
+ if (MemRecNGetBitFieldNb (NBPtr, BFEnDramInit) == 0) {
+ // For C0, if EnDramInit bit is cleared, ODM needs to be cleared before sending MRS
+ MemRecTCtlOnDimmMirrorNb (NBPtr, FALSE);
+ ClearODM = TRUE;
+ }
+ }
+ }
+ }
+
+ MemRecNSwapBitsNb (NBPtr);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tCS%d MR%d %04x\n",
+ MemRecNGetBitFieldNb (NBPtr, BFMrsChipSel),
+ MemRecNGetBitFieldNb (NBPtr, BFMrsBank),
+ MemRecNGetBitFieldNb (NBPtr, BFMrsAddress));
+
+ // 1.Set SendMrsCmd=1
+ MemRecNSetBitFieldNb (NBPtr, BFSendMrsCmd, 1);
+
+ // 2.Wait for SendMrsCmd=0
+ while (MemRecNGetBitFieldNb (NBPtr, BFSendMrsCmd)) {}
+
+ if (NBPtr->IsSupported[CheckClearOnDimmMirror]) {
+ if (ClearODM) {
+ // Restore ODM if necessary
+ MemRecTCtlOnDimmMirrorNb (NBPtr, TRUE);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sends the ZQCL command
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+MemRecNSendZQCmdNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ // 1.Program MrsAddress[10]=1
+ MemRecNSetBitFieldNb (NBPtr, BFMrsAddress, (UINT32) 1 << 10);
+
+ // 2.Set SendZQCmd=1
+ MemRecNSetBitFieldNb (NBPtr, BFSendZQCmd, 1);
+
+ // 3.Wait for SendZQCmd=0
+ while (MemRecNGetBitFieldNb (NBPtr, BFSendZQCmd)) {}
+
+ // 4.Wait 512 MEMCLKs
+ MemRecUWait10ns (128, NBPtr->MemPtr); // 512*2.5ns=1280, wait 1280ns
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function disables/enables F2x[1, 0][5C:40][OnDimmMirror]
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] SetFlag - Enable or disable flag - TRUE - Enable, FALSE - DISABLE
+ *
+ */
+
+VOID
+STATIC
+MemRecTCtlOnDimmMirrorNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN BOOLEAN SetFlag
+ )
+{
+ UINT8 Chipsel;
+ UINT32 CSBaseAddrReg;
+
+ for (Chipsel = 0; Chipsel < MAX_CS_PER_CHANNEL; Chipsel += 2) {
+ CSBaseAddrReg = MemRecNGetBitFieldNb (NBPtr, BFCSBaseAddr1Reg + Chipsel);
+ if ((CSBaseAddrReg & 1) == 1) {
+ if (SetFlag && ((NBPtr->ChannelPtr->DimmMirrorPresent & ((UINT8) 1 << (Chipsel >> 1))) != 0)) {
+ CSBaseAddrReg |= ((UINT32) 1 << BFOnDimmMirror);
+ } else {
+ CSBaseAddrReg &= ~((UINT32) 1 << BFOnDimmMirror);
+ }
+ MemRecNSetBitFieldNb (NBPtr, BFCSBaseAddr1Reg + Chipsel, CSBaseAddrReg);
+ }
+ }
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function swaps bits for OnDimmMirror support
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+STATIC
+MemRecNSwapBitsNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 ChipSel;
+ UINT32 MRSReg;
+
+ ChipSel = (UINT8) MemRecNGetBitFieldNb (NBPtr, BFMrsChipSel);
+ if ((ChipSel & 1) != 0) {
+ MRSReg = MemRecNGetBitFieldNb (NBPtr, BFDramInitRegReg);
+ if ((NBPtr->ChannelPtr->DimmMirrorPresent & (UINT8) 1 << (ChipSel >> 1)) != 0) {
+ MRSReg = (MRSReg & 0xFFFCFE07) | ((MRSReg&0x100A8) << 1) | ((MRSReg&0x20150) >> 1);
+ MemRecNSetBitFieldNb (NBPtr, BFDramInitRegReg, MRSReg);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * 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
+ */
+
+UINT32
+MemRecNTotalSyncComponentsClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT32 T;
+ UINT32 P;
+ UINT32 AddrTmgCtl;
+ UINT32 MemClkPeriod;
+
+ AGESA_TESTPOINT (TpProcMemRcvrCalcLatency , &(NBPtr->MemPtr->StdHeader));
+
+ // P = P + ((16 + RdPtrInitMin - D18F2x[1,0]78[RdPtrInit]) MOD 16) where RdPtrInitMin = RdPtrInit
+ P = 0;
+
+ AddrTmgCtl = MemRecNGetBitFieldNb (NBPtr, BFAddrTmgControl);
+ if (((AddrTmgCtl >> 16) & 0x20) != (AddrTmgCtl & 0x20)) {
+ P += 1;
+ }
+
+ // IF (DbeGskMemClkAlignMode==01b || (DbeGskMemClkAlignMode==00b && !(AddrCmdSetup==CsOdtSetup==CkeSetup)))
+ // THEN P = P + 1
+
+ // IF (SlowAccessMode==1) THEN P = P + 2
+
+ // T = T + (0.5 * MemClkPeriod) - 786 ps
+ MemClkPeriod = 1000000 / DDR800_FREQUENCY;
+ T = MemClkPeriod / 2 - 768;
+
+ // 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 * 5; // Tcl = 6 clocks
+
+ // (DisCutThroughMode = 0), so P = P + 3
+ P += 3;
+
+ return ((P * MemClkPeriod + 1) / 2) + T;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNPhyVoltageLevelNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ BIT_FIELD_NAME BitField;
+ UINT16 Value;
+ UINT16 Mask;
+
+ Mask = 0xFFE7;
+ Value = (UINT16) CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage) << 3;
+
+ for (BitField = BFDataRxVioLvl; BitField <= BFCmpVioLvl; BitField++) {
+ if (BitField == BFCmpVioLvl) {
+ Mask = 0x3FFF;
+ Value <<= (14 - 3);
+ }
+ MemRecNSetBitFieldNb (NBPtr, BitField, ((MemRecNGetBitFieldNb (NBPtr, BitField) & Mask)) | Value);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function executes Phy fence training
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+STATIC
+MemRecNTrainPhyFenceNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Byte;
+ UINT16 Avg;
+ UINT8 PREvalue;
+
+ if (MemRecNGetBitFieldNb (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 < 9; Byte++) {
+ // This includes ECC as byte 8
+ MemRecNSetTrainDlyNb (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.
+ MemRecNSetBitFieldNb (NBPtr, BFPhyFenceTrEn, 1);
+
+ MemRecUWait10ns (5000, NBPtr->MemPtr);
+
+ // 4. Clear F2x[1, 0]9C_x08[PhyFenceTrEn]=0.
+ MemRecNSetBitFieldNb (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;
+ for (Byte = 0; Byte < 9; Byte++) {
+ // This includes ECC as byte 8
+ PREvalue = (UINT8) (0x1F & MemRecNGetTrainDlyNb (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (0, Byte)));
+ Avg = Avg + ((UINT16) PREvalue);
+ }
+ Avg = ((Avg + 8) / 9); // round up
+ Avg -= 6;
+
+ // 7. Write the value to F2x[1, 0]9C_x0C[PhyFence].
+ MemRecNSetBitFieldNb (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.
+ //
+ MemRecNSetBitFieldNb (NBPtr, BFAddrTmgControl, MemRecNGetBitFieldNb (NBPtr, BFAddrTmgControl));
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates and programs NB P-state dependent registers
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ */
+
+VOID
+STATIC
+MemRecNProgNbPstateDependentRegClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 i;
+ UINT8 NclkFid;
+ UINT16 MemClkDid;
+ UINT8 PllMult;
+ UINT8 NclkDiv;
+ UINT8 RdPtrInit;
+ UINT32 NclkPeriod;
+ UINT32 MemClkPeriod;
+ INT32 PartialSum2x;
+ INT32 PartialSumSlotI2x;
+ INT32 RdPtrInitRmdr2x;
+
+ NclkFid = (UINT8) (MemRecNGetBitFieldNb (NBPtr, BFMainPllOpFreqId) + 0x10);
+ MemClkDid = 2; //BKDG recommended value for DDR800
+ PllMult = 16; //BKDG recommended value for DDR800
+ NclkDiv = (UINT8) MemRecNGetBitFieldNb (NBPtr, BFNbPs0NclkDiv);
+
+ NclkPeriod = (2500 * NclkDiv) / NclkFid;
+ MemClkPeriod = 1000000 / DDR800_FREQUENCY;
+ NBPtr->NBClkFreq = ((UINT32) NclkFid * 400) / NclkDiv;
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\tNB P%d Freq: %dMHz\n", 0, NBPtr->NBClkFreq);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClk Freq: %dMHz\n", DDR800_FREQUENCY);
+
+ // 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 = NBPtr->FreqChangeParam->RdPtrInitLower667;
+ MemRecNSetBitFieldNb (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].
+ MemRecNSetBitFieldNb (NBPtr, BFDbeGskFifoNumerator, NclkFid * MemClkDid * 16);
+ MemRecNSetBitFieldNb (NBPtr, BFDbeGskFifoDenominator, PllMult * NclkDiv);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDbeGskFifoNumerator: %d\n", NclkFid * MemClkDid * 16);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDbeGskFifoDenominator: %d\n", PllMult * NclkDiv);
+
+ // 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)
+ 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
+ // RdPtrInitRmdr = (((2.25 * MemClkPeriod) - 1520ps) MOD MemClkPeriod)/MemClkPeriod
+ RdPtrInitRmdr2x = ((NBPtr->FreqChangeParam->SyncTimeMul4x * MemClkPeriod) / 2) - 2 * (NBPtr->FreqChangeParam->TDataPropLower800 + 520);
+ RdPtrInitRmdr2x %= MemClkPeriod;
+ PartialSum2x -= RdPtrInitRmdr2x;
+ PartialSum2x = (PartialSum2x + MemClkPeriod - 1) / MemClkPeriod; // round-up here
+ PartialSum2x -= 2 * 5; //Tcwl + 5
+
+ if ((MemRecNGetBitFieldNb (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;
+ if (i == 0) {
+ PartialSumSlotI2x += 2;
+ }
+ if (PartialSumSlotI2x > 0) {
+ MemRecNSetBitFieldNb (NBPtr, BFDataTxFifoSchedDlyNegSlot0 + i, 0);
+ MemRecNSetBitFieldNb (NBPtr, BFDataTxFifoSchedDlySlot0 + i, (PartialSumSlotI2x + 1) / 2);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDataTxFifoSchedDlySlot%d: %d\n", i, (PartialSumSlotI2x + 1) / 2);
+ } else {
+ MemRecNSetBitFieldNb (NBPtr, BFDataTxFifoSchedDlyNegSlot0 + i, 1);
+ PartialSumSlotI2x = ((-PartialSumSlotI2x) * MemClkPeriod) / (2 * NclkPeriod);
+ MemRecNSetBitFieldNb (NBPtr, BFDataTxFifoSchedDlySlot0 + i, PartialSumSlotI2x);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tDataTxFifoSchedDlySlot%d: -%d\n", i, PartialSumSlotI2x);
+ }
+ }
+ // Program ProcOdtAdv
+ MemRecNSetBitFieldNb (NBPtr, BFProcOdtAdv, 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
+MemRecNContReadPatternClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ )
+{
+ // 1. Program D18F2x1C0[RdDramTrainMode]=1.
+ MemRecNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 1);
+
+ // 2. Program D18F2x1C0[TrainLength] to the appropriate number of cache lines.
+ MemRecNSetBitFieldNb (NBPtr, BFTrainLength, ClCount);
+
+ // 3. Program the DRAM training address as follows:
+ MemRecNSetBitFieldNb (NBPtr, BFWrTrainAdrPtrLo, (Address >> 6));
+
+ // 4. Program D18F2x1D0[WrTrainBufAddr]=000h
+ MemRecNSetBitFieldNb (NBPtr, BFWrTrainBufAddr, 0);
+
+ // 5. Program D18F2x1C0[RdTrainGo]=1.
+ MemRecNSetBitFieldNb (NBPtr, BFRdTrainGo, 1);
+
+ // 6. Wait for D18F2x1C0[RdTrainGo]=0.
+ while (MemRecNGetBitFieldNb (NBPtr, BFRdTrainGo) != 0) {}
+
+ // 7. Read D18F2x1E8[TrainCmpSts] and D18F2x1E8[TrainCmpSts2].
+
+ // 8. Program D18F2x1C0[RdDramTrainMode]=0.
+ MemRecNSetBitFieldNb (NBPtr, BFRdDramTrainMode, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This is function sets the platform specific settings for the systems with UDIMMs configuration
+ *
+ * @param[in,out] *MemData Pointer to MEM_DATA_STRUCTURE
+ * @param[in] SocketID Socket number
+ * @param[in] *CurrentChannel Pointer to CH_DEF_STRUCT
+ *
+ * @return AGESA_SUCCESS
+ * @return CurrentChannel->DctAddrTmg Address Command Timing Settings for specified channel
+ * @return CurrentChannel->DctOdcCtl Drive Strength settings for specified channel
+ * @return CurrentChannel->Reserved[0] Dram Term for specified channel
+ * @return CurrentChannel->Reserved[1] Dynamic Dram Term for specified channel
+ * @return CurrentChannel->PhyWLODT[0] WL ODT for DIMM0
+ * @return CurrentChannel->PhyWLODT[1] WL ODT for DIMM1
+ * @return CurrentChannel->PhyWLODT[2] WL ODT for DIMM2
+ * @return CurrentChannel->PhyWLODT[3] WL ODT for DIMM3
+ *
+ */
+AGESA_STATUS
+MemRecNGetPsCfgUDIMM3Nb (
+ IN OUT MEM_DATA_STRUCT *MemData,
+ IN UINT8 SocketID,
+ IN OUT CH_DEF_STRUCT *CurrentChannel
+ )
+{
+ UINT32 AddrTmgCTL;
+ UINT32 DctOdcCtl;
+ UINT8 Dimms;
+ UINT8 MaxDimmPerCH;
+ UINT8 DramTerm;
+ UINT8 DramTermDyn;
+
+ if ((CurrentChannel->RegDimmPresent != 0) || (CurrentChannel->SODimmPresent != 0)) {
+ return AGESA_UNSUPPORTED;
+ }
+
+ Dimms = CurrentChannel->Dimms;
+ MaxDimmPerCH = RecGetMaxDimmsPerChannel (MemData->ParameterListPtr->PlatformMemoryConfiguration, 0, CurrentChannel->ChannelID);
+
+ if (MaxDimmPerCH == 1) {
+ return AGESA_UNSUPPORTED;
+ } else {
+ DctOdcCtl = 0x20223323;
+ AddrTmgCTL = 0x00390039;
+ if (Dimms == 1) {
+ DctOdcCtl = 0x20113222;
+ AddrTmgCTL = 0x00390039;
+ if (CurrentChannel->Loads == 16) {
+ AddrTmgCTL = 0x003B0000;
+ }
+ }
+ }
+ CurrentChannel->DctAddrTmg = AddrTmgCTL;
+ CurrentChannel->DctOdcCtl = DctOdcCtl;
+
+ // ODT
+ if (Dimms == 1) {
+ DramTerm = 1; // 60 ohms
+ DramTermDyn = 0; // Disable
+ if ((MaxDimmPerCH == 3) && (CurrentChannel->DimmDrPresent != 0)) {
+ DramTermDyn = 1; // 60 ohms
+ }
+ } else {
+ DramTerm = 3; // 40 ohms
+ DramTermDyn = 2; // 120 ohms
+ }
+ CurrentChannel->Reserved[0] = DramTerm;
+ CurrentChannel->Reserved[1] = DramTermDyn;
+
+ // WL ODT
+ if (Dimms == 1) {
+ CurrentChannel->PhyWLODT[0] = 0;
+ CurrentChannel->PhyWLODT[1] = (CurrentChannel->DimmDrPresent != 0) ? 8 : 2;
+ } else {
+ CurrentChannel->PhyWLODT[0] = 3;
+ CurrentChannel->PhyWLODT[1] = 3;
+ }
+ CurrentChannel->PhyWLODT[2] = 0;
+ CurrentChannel->PhyWLODT[3] = 0;
+
+ return AGESA_SUCCESS;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This is function sets the platform specific settings for the systems with SODIMMs configuration
+ *
+ * @param[in,out] *MemData Pointer to MEM_DATA_STRUCTURE
+ * @param[in] SocketID Socket number
+ * @param[in] *CurrentChannel Pointer to CH_DEF_STRUCT
+ *
+ * @return AGESA_SUCCESS
+ * @return CurrentChannel->DctAddrTmg Address Command Timing Settings for specified channel
+ * @return CurrentChannel->DctOdcCtl Drive Strength settings for specified channel
+ * @return CurrentChannel->Reserved[0] Dram Term for specified channel
+ * @return CurrentChannel->Reserved[1] Dynamic Dram Term for specified channel
+ * @return CurrentChannel->PhyWLODT[0] WL ODT for DIMM0
+ * @return CurrentChannel->PhyWLODT[1] WL ODT for DIMM1
+ * @return CurrentChannel->PhyWLODT[2] WL ODT for DIMM2
+ * @return CurrentChannel->PhyWLODT[3] WL ODT for DIMM3
+ *
+ */
+AGESA_STATUS
+MemRecNGetPsCfgSODIMM3Nb (
+ IN OUT MEM_DATA_STRUCT *MemData,
+ IN UINT8 SocketID,
+ IN OUT CH_DEF_STRUCT *CurrentChannel
+ )
+{
+ UINT32 AddrTmgCTL;
+ UINT32 DctOdcCtl;
+ UINT8 MaxDimmPerCH;
+ UINT8 Dimms;
+ UINT8 DramTerm;
+ UINT8 DramTermDyn;
+
+ if (CurrentChannel->SODimmPresent != CurrentChannel->ChDimmValid) {
+ return AGESA_UNSUPPORTED;
+ }
+
+ Dimms = CurrentChannel->Dimms;
+ MaxDimmPerCH = RecGetMaxDimmsPerChannel (MemData->ParameterListPtr->PlatformMemoryConfiguration, 0, CurrentChannel->ChannelID);
+
+ if (MaxDimmPerCH == 1) {
+ DctOdcCtl = 0x00113222;
+ AddrTmgCTL = 0;
+ } else {
+ DctOdcCtl = 0x00223323;
+ AddrTmgCTL = 0x00000039;
+ if (Dimms == 1) {
+ DctOdcCtl = 0x00113222;
+ AddrTmgCTL = 0;
+ }
+ }
+ CurrentChannel->DctAddrTmg = AddrTmgCTL;
+ CurrentChannel->DctOdcCtl = DctOdcCtl;
+
+ // ODT
+ if (Dimms == 1) {
+ DramTerm = 2; // 120 ohms
+ DramTermDyn = 0; // Disable
+ if (MaxDimmPerCH == 2) {
+ DramTerm = 1; // 60 ohms
+ }
+ } else {
+ DramTerm = 3; // 40 ohms
+ DramTermDyn = 2; // 120 ohms
+ }
+ CurrentChannel->Reserved[0] = DramTerm;
+ CurrentChannel->Reserved[1] = DramTermDyn;
+
+ // WL ODT
+ if (Dimms == 1) {
+ if (MaxDimmPerCH == 1) {
+ CurrentChannel->PhyWLODT[0] = (CurrentChannel->DimmDrPresent != 0) ? 4 : 1;
+ CurrentChannel->PhyWLODT[1] = 0;
+ } else {
+ CurrentChannel->PhyWLODT[0] = 0;
+ CurrentChannel->PhyWLODT[1] = (CurrentChannel->DimmDrPresent != 0) ? 8 : 2;
+ }
+ } else {
+ CurrentChannel->PhyWLODT[0] = 3;
+ CurrentChannel->PhyWLODT[1] = 3;
+ }
+ CurrentChannel->PhyWLODT[2] = 0;
+ CurrentChannel->PhyWLODT[3] = 0;
+
+ return AGESA_SUCCESS;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This is function sets the platform specific settings for the systems with RDIMMs configuration
+ *
+ * @param[in,out] *MemData Pointer to MEM_DATA_STRUCTURE
+ * @param[in] SocketID Socket number
+ * @param[in] *CurrentChannel Pointer to CH_DEF_STRUCT
+ *
+ * @return AGESA_SUCCESS
+ * @return CurrentChannel->DctAddrTmg Address Command Timing Settings for specified channel
+ * @return CurrentChannel->DctOdcCtl Drive Strength settings for specified channel
+ * @return CurrentChannel->Reserved[0] Dram Term for specified channel
+ * @return CurrentChannel->Reserved[1] Dynamic Dram Term for specified channel
+ * @return CurrentChannel->PhyWLODT[0] WL ODT for DIMM0
+ * @return CurrentChannel->PhyWLODT[1] WL ODT for DIMM1
+ * @return CurrentChannel->PhyWLODT[2] WL ODT for DIMM2
+ * @return CurrentChannel->PhyWLODT[3] WL ODT for DIMM3
+ *
+ */
+
+AGESA_STATUS
+MemRecNGetPsCfgRDIMM3Nb (
+ IN OUT MEM_DATA_STRUCT *MemData,
+ IN UINT8 SocketID,
+ IN OUT CH_DEF_STRUCT *CurrentChannel
+ )
+{
+ STATIC CONST ADV_R_PSCFG_WL_ODT_ENTRY RecPSCfg2DIMMsWlODT[] = {
+ {SR_DIMM0, {0x01, 0x00, 0x00, 0x00}, 1},
+ {DR_DIMM0, {0x04, 0x00, 0x00, 0x00}, 1},
+ {QR_DIMM0, {0x05, 0x00, 0x00, 0x00}, 1},
+ {SR_DIMM1, {0x00, 0x02, 0x00, 0x00}, 1},
+ {DR_DIMM1, {0x00, 0x08, 0x00, 0x00}, 1},
+ {QR_DIMM1, {0x00, 0x0A, 0x00, 0x00}, 1},
+ {SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1, {0x03, 0x03, 0x00, 0x00}, 2},
+ {SR_DIMM0 + QR_DIMM1, {0x0B, 0x03, 0x00, 0x09}, 2},
+ {DR_DIMM0 + QR_DIMM1, {0x0B, 0x03, 0x00, 0x09}, 2},
+ {QR_DIMM0 + SR_DIMM1, {0x03, 0x07, 0x06, 0x00}, 2},
+ {QR_DIMM0 + DR_DIMM1, {0x03, 0x07, 0x06, 0x00}, 2},
+ {QR_DIMM0 + QR_DIMM1, {0x0B, 0x07, 0x0E, 0x0D}, 2}
+ };
+ STATIC CONST ADV_R_PSCFG_WL_ODT_ENTRY RecPSCfg3DIMMsWlODT[] = {
+ {SR_DIMM2 + DR_DIMM2, {0x00, 0x00, 0x04, 0x00}, 1},
+ {SR_DIMM0 + DR_DIMM0, {0x01, 0x02, 0x00, 0x00}, 1},
+ {SR_DIMM0 + DR_DIMM0 + SR_DIMM2 + DR_DIMM2, {0x05, 0x00, 0x05, 0x00}, 2},
+ {SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1 + SR_DIMM2 + DR_DIMM2, {0x07, 0x07, 0x07, 0x00}, 3},
+ {QR_DIMM1, {0x00, 0x0A, 0x00, 0x0A}, 1},
+ {QR_DIMM1 + SR_DIMM2 + DR_DIMM2, {0x00, 0x06, 0x0E, 0x0C}, 2},
+ {SR_DIMM0 + DR_DIMM0 + QR_DIMM1, {0x0B, 0x03, 0x00, 0x09}, 2},
+ {SR_DIMM0 + DR_DIMM0 + QR_DIMM1 + SR_DIMM2 + DR_DIMM2, {0x0F, 0x07, 0x0F, 0x0D}, 3}
+ };
+ STATIC CONST ADV_R_PSCFG_WL_ODT_ENTRY RecPSCfg4DIMMsWlODT[] = {
+ {ANY_DIMM3, {0x00, 0x00, 0x00, 0x08}, 1},
+ {ANY_DIMM2 + ANY_DIMM3, {0x00, 0x00, 0x0C, 0x0C}, 2},
+ {ANY_DIMM1 + ANY_DIMM2 + ANY_DIMM3, {0x00, 0x0E, 0x0E, 0x0E}, 3},
+ {ANY_DIMM0 + ANY_DIMM1 + ANY_DIMM2 + ANY_DIMM3, {0x0F, 0x0F, 0x0F, 0x0F}, 4}
+ };
+
+ UINT8 i;
+ UINT8 j;
+ UINT8 Dimms;
+ UINT8 DimmQrPresent;
+ UINT32 AddrTmgCTL;
+ UINT32 DctOdcCtl;
+ UINT8 PhyWLODT[4];
+ UINT8 DramTerm;
+ UINT8 DramTermDyn;
+ UINT16 DIMMRankType;
+ UINT16 _DIMMRankType_;
+ UINT8 DimmTpMatch;
+ UINT8 MaxDimmPerCH;
+ UINT8 PSCfgWlODTSize;
+ CONST ADV_R_PSCFG_WL_ODT_ENTRY *PSCfgWlODTPtr;
+
+ if (CurrentChannel->RegDimmPresent != CurrentChannel->ChDimmValid) {
+ return AGESA_UNSUPPORTED;
+ }
+
+ DIMMRankType = MemRecNGetPsRankType (CurrentChannel);
+ MaxDimmPerCH = RecGetMaxDimmsPerChannel (MemData->ParameterListPtr->PlatformMemoryConfiguration, 0, CurrentChannel->ChannelID);
+ Dimms = CurrentChannel->Dimms;
+ PSCfgWlODTPtr = RecPSCfg2DIMMsWlODT;
+ PSCfgWlODTSize = GET_SIZE_OF (RecPSCfg2DIMMsWlODT);
+ PhyWLODT[0] = PhyWLODT[1] = PhyWLODT[2] = PhyWLODT[3] = 0xFF;
+ DimmQrPresent = CurrentChannel->DimmQrPresent;
+
+ if (MaxDimmPerCH == 4) {
+ AddrTmgCTL = (Dimms > 2) ? 0x002F0000 : 0;
+ DctOdcCtl = (Dimms == 1) ? 0x20113222 : 0x20223222;
+ PSCfgWlODTPtr = RecPSCfg4DIMMsWlODT;
+ PSCfgWlODTSize = GET_SIZE_OF (RecPSCfg4DIMMsWlODT);
+ } else if (MaxDimmPerCH == 3) {
+ AddrTmgCTL = 0;
+ DctOdcCtl = 0x20223222;
+ if (Dimms == 3) {
+ AddrTmgCTL = 0x00380038;
+ DctOdcCtl = 0x20113222;
+ }
+ if (Dimms == 1) {
+ DctOdcCtl = 0x20113222;
+ }
+ PSCfgWlODTPtr = RecPSCfg3DIMMsWlODT;
+ PSCfgWlODTSize = GET_SIZE_OF (RecPSCfg3DIMMsWlODT);
+ } else if (MaxDimmPerCH == 2) {
+ AddrTmgCTL = 0;
+ DctOdcCtl = 0x20223222;
+ if ((Dimms == 1) && (DimmQrPresent == 0)) {
+ DctOdcCtl = 0x20113222;
+ }
+ } else {
+ AddrTmgCTL = 0;
+ DctOdcCtl = (DimmQrPresent == 0) ? 0x20113222 : 0x20223222;
+ }
+ CurrentChannel->DctAddrTmg = AddrTmgCTL;
+ CurrentChannel->DctOdcCtl = DctOdcCtl;
+
+ // ODT
+ if (Dimms == 1) {
+ DramTerm = 1; // 60 ohms
+ DramTermDyn = 0; // Disable
+ if (DimmQrPresent != 0) {
+ DramTermDyn = 2; // 120 ohms
+ }
+ } else {
+ DramTerm = 3; // 40 ohms
+ DramTermDyn = 2; // 120 ohms
+ if (DimmQrPresent != 0) {
+ DramTerm = 1; // 60 ohms
+ }
+ }
+ CurrentChannel->Reserved[0] = DramTerm;
+ CurrentChannel->Reserved[1] = DramTermDyn;
+
+ // WL ODT
+ for (i = 0; i < PSCfgWlODTSize; i++, PSCfgWlODTPtr++) {
+ if (Dimms != PSCfgWlODTPtr->Dimms) {
+ continue;
+ }
+ DimmTpMatch = 0;
+ _DIMMRankType_ = DIMMRankType & PSCfgWlODTPtr->DIMMRankType;
+ for (j = 0; j < MAX_DIMMS_PER_CHANNEL; j++) {
+ if ((_DIMMRankType_ & (UINT16) 0x0F << (j << 2)) != 0) {
+ DimmTpMatch++;
+ }
+ }
+ if (DimmTpMatch == PSCfgWlODTPtr->Dimms) {
+ PhyWLODT[0] = PSCfgWlODTPtr->PhyWrLvOdt[0];
+ PhyWLODT[1] = PSCfgWlODTPtr->PhyWrLvOdt[1];
+ PhyWLODT[2] = PSCfgWlODTPtr->PhyWrLvOdt[2];
+ PhyWLODT[3] = PSCfgWlODTPtr->PhyWrLvOdt[3];
+ break;
+ }
+ }
+ CurrentChannel->PhyWLODT[0] = PhyWLODT[0];
+ CurrentChannel->PhyWLODT[1] = PhyWLODT[1];
+ CurrentChannel->PhyWLODT[2] = PhyWLODT[2];
+ CurrentChannel->PhyWLODT[3] = PhyWLODT[3];
+
+ return AGESA_SUCCESS;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function returns the max dimms for a given memory channel on a given
+ * processor. It first searches the platform override table for the max dimms
+ * value. If it is not provided, the AGESA default value is returned. The target
+ * socket must be a valid present socket.
+ *
+ * @param[in] PlatformMemoryConfiguration - Platform config table
+ * @param[in] SocketID - ID of the processor that owns the channel
+ * @param[in] ChannelID - Channel to get max dimms for
+ *
+ *
+ * @return UINT8 - Max Number of Dimms for that channel
+ */
+UINT8
+RecGetMaxDimmsPerChannel (
+ IN PSO_TABLE *PlatformMemoryConfiguration,
+ IN UINT8 SocketID,
+ IN UINT8 ChannelID
+ )
+{
+ UINT8 *DimmsPerChPtr;
+ UINT8 MaxDimmPerCH;
+
+ DimmsPerChPtr = MemRecFindPSOverrideEntry (PlatformMemoryConfiguration, PSO_MAX_DIMMS, SocketID, ChannelID, 0);
+ if (DimmsPerChPtr != NULL) {
+ MaxDimmPerCH = *DimmsPerChPtr;
+ } else {
+ MaxDimmPerCH = 2;
+ }
+
+ return MaxDimmPerCH;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This is the default return function of the ARDK block. The function always
+ * returns AGESA_UNSUPPORTED
+ *
+ * @param[in,out] *MemData Pointer to MEM_DATA_STRUCTURE
+ * @param[in] SocketID Socket number
+ * @param[in] *CurrentChannel Pointer to CH_DEF_STRUCT
+ *
+ * @return AGESA_UNSUPPORTED AGESA status indicating that default is unsupported
+ *
+ */
+
+AGESA_STATUS
+MemRecNGetPsCfgDef (
+ IN OUT MEM_DATA_STRUCT *MemData,
+ IN UINT8 SocketID,
+ IN OUT CH_DEF_STRUCT *CurrentChannel
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function returns the rank type map of a channel.
+ *
+ * @param[in] *CurrentChannel Pointer to CH_DEF_STRUCT
+ *
+ * @return UINT16 - The map of rank type.
+ *
+ */
+UINT16
+MemRecNGetPsRankType (
+ IN CH_DEF_STRUCT *CurrentChannel
+ )
+{
+ UINT8 i;
+ UINT16 DIMMRankType;
+
+ DIMMRankType = 0;
+ for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
+ if ((CurrentChannel->DimmQrPresent & (UINT8) 1 << i) != 0) {
+ if (i < 2) {
+ DIMMRankType |= (UINT16) 4 << (i << 2);
+ }
+ } else if ((CurrentChannel->DimmDrPresent & (UINT8) 1 << i) != 0) {
+ DIMMRankType |= (UINT16) 2 << (i << 2);
+ } else if ((CurrentChannel->DimmSRPresent & (UINT8) 1 << i) != 0) {
+ DIMMRankType |= (UINT16) 1 << (i << 2);
+ }
+ }
+ return DIMMRankType;
+}
+
+UINT32
+MemRecNcmnGetSetTrainDlyClientNb (
+ 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)) {
+ // LN and ON do 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;
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlOffsetReg, Address);
+ Value = MemRecNGetBitFieldNb (NBPtr, BFDctAddlDataReg);
+
+ if (IsSet) {
+ if (TrnDly == AccessPhRecDly) {
+ Value = NBPtr->DctCachePtr->PhRecReg[Index & 0x03];
+ }
+
+ Value = ((UINT32)Field << Offset) | (Value & (~((UINT32) ((TrnDly == AccessRcvEnDly) ? 0x1FF : 0xFF) << Offset)));
+ MemRecNSetBitFieldNb (NBPtr, BFDctAddlDataReg, Value);
+ Address |= DCT_ACCESS_WRITE;
+ MemRecNSetBitFieldNb (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 reads cache lines continuously using PRBS 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
+MemRecNContReadPatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT32 Address,
+ IN UINT16 ClCount
+ )
+{
+ MemRecNCommonReadWritePatternUnb (NBPtr, CMD_TYPE_READ, ClCount);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNContWritePatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT32 Address,
+ IN UINT8 Pattern[],
+ IN UINT16 ClCount
+ )
+{
+ MemRecNCommonReadWritePatternUnb (NBPtr, CMD_TYPE_WRITE, ClCount);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function generates either read or write DRAM cycles for training
+ * using PRBS engine
+ *
+ * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] CmdType - Read/Write
+ * @param[in] ClCount - Number of cache lines to write
+ *
+ */
+
+VOID
+STATIC
+MemRecNCommonReadWritePatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 CmdType,
+ IN UINT16 ClCount
+ )
+{
+ MEM_TECH_BLOCK *TechPtr;
+
+ TechPtr = NBPtr->TechPtr;
+
+ // Enable PRBS, also set ResetAllErr
+ MemRecNSetBitFieldNb (NBPtr, BFCmdTestEnable, 3);
+
+ // Send activate command
+ MemRecNSetBitFieldNb (NBPtr, BFDramCmd2Reg, (UINT32) 1 << (TechPtr->ChipSel + 22) | ((UINT32) 1 << 31));
+ MemRecUWait10ns (750, NBPtr->MemPtr);
+
+ // Setup test address
+ MemRecNSetBitFieldNb (NBPtr, BFTgtChipSelectA, TechPtr->ChipSel);
+ MemRecNSetBitFieldNb (NBPtr, BFDataPrbsSeed, PRBS_SEED_256);
+ MemRecNSetBitFieldNb (NBPtr, BFCmdCount, ClCount);
+
+ // Select read or write command
+ MemRecNSetBitFieldNb (NBPtr, BFCmdType, CmdType);
+
+ // Send command and wait for completion
+ MemRecNSetBitFieldNb (NBPtr, BFSendCmd, 1);
+ while (MemRecNGetBitFieldNb (NBPtr, BFTestStatus) == 0) {}
+ while (MemRecNGetBitFieldNb (NBPtr, BFCmdSendInProg) != 0) {}
+ MemRecNSetBitFieldNb (NBPtr, BFSendCmd, 0);
+
+ // Send precharge all command
+ MemRecNSetBitFieldNb (NBPtr, BFDramCmd2Reg, (UINT32) 1 << (TechPtr->ChipSel + 22) | ((UINT32) 1 << 30));
+ MemRecUWait10ns (750, NBPtr->MemPtr);
+
+ // Disable PRBS
+ MemRecNSetBitFieldNb (NBPtr, BFCmdTestEnable, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function checks the Error status bits for comparison results using PRBS
+ *
+ * @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
+MemRecNCompareTestPatternUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN UINT16 ByteCount
+ )
+{
+ UINT16 i;
+ UINT16 Pass;
+ UINT32 NibbleErrSts;
+
+ NibbleErrSts = MemRecNGetBitFieldNb (NBPtr, BFNibbleErrSts);
+
+ Pass = 0;
+ for (i = 0; i < 8; i++) {
+ Pass |= ((NibbleErrSts & 0x03) > 0 ) ? (1 << i) : 0;
+ NibbleErrSts >>= 2;
+ }
+ Pass = ~Pass;
+ return Pass;
+}
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrnmct.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrnmct.c
new file mode 100644
index 0000000000..314c7f468b
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrnmct.c
@@ -0,0 +1,296 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrnmct.c
+ *
+ * Northbridge Common MCT supporting functions Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/NB)
+ * @e \$Revision: 56555 $ @e \$Date: 2011-07-15 06:18:49 -0600 (Fri, 15 Jul 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuCacheInit.h"
+#include "Filecode.h"
+#define FILECODE PROC_RECOVERY_MEM_NB_MRNMCT_FILECODE
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function is the Recovery memory configuration function for Nb DDR3
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ *
+ * @return AGESA_STATUS
+ * - AGESA_ALERT
+ * - AGESA_FATAL
+ * - AGESA_SUCCESS
+ * - AGESA_WARNING
+ */
+
+AGESA_STATUS
+MemRecNMemInitNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ AGESA_STATUS Status;
+ MEM_TECH_BLOCK *TechPtr;
+
+ TechPtr = NBPtr->TechPtr;
+
+ NBPtr->MemRecNInitializeMctNb (NBPtr);
+
+ if (NBPtr->IsSupported[DramModeBeforeDimmPres]) {
+ TechPtr->SetDramMode (TechPtr);
+ }
+
+ Status = AGESA_FATAL;
+ if (TechPtr->DimmPresence (TechPtr)) {
+
+ if (NBPtr->IsSupported[DramModeAfterDimmPres]) {
+ TechPtr->SetDramMode (TechPtr);
+ }
+
+ if (MemRecNAutoConfigNb (NBPtr)) {
+
+ AGESA_TESTPOINT (TpProcMemPlatformSpecificConfig, &(NBPtr->MemPtr->StdHeader));
+ if (MemRecNPlatformSpecNb (NBPtr)) {
+ AgesaHookBeforeDramInitRecovery (0, NBPtr->MemPtr);
+ AGESA_TESTPOINT (TpProcMemStartDcts, &(NBPtr->MemPtr->StdHeader));
+ MemRecNStartupDCTNb (NBPtr);
+
+ AGESA_TESTPOINT (TpProcMemMtrrConfiguration, &(NBPtr->MemPtr->StdHeader));
+ MemRecNCPUMemRecTypingNb (NBPtr);
+
+ AGESA_TESTPOINT (TpProcMemDramTraining, &(NBPtr->MemPtr->StdHeader));
+ NBPtr->TrainingFlow (NBPtr);
+
+ Status = AGESA_SUCCESS;
+ }
+ }
+ }
+
+ NBPtr->MemRecNFinalizeMctNb (NBPtr);
+
+ return Status;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function returns a physical address of a corresponding Chip select
+ *
+ * @return Addr - System Address
+ */
+
+UINT32
+MemRecNGetMCTSysAddrNb ( VOID )
+{
+ UINT32 CSBase;
+
+ CSBase = (UINT32) 1 << 21; // 1MB offset to avoid compat area from the base address.
+ if ((CSBase >= (MCT_TRNG_KEEPOUT_START << 8)) && (CSBase <= (MCT_TRNG_KEEPOUT_END << 8))) {
+ CSBase += (((MCT_TRNG_KEEPOUT_END << 8) - CSBase) + 0x0FFFFF) & 0xFFF00000;
+ }
+
+ return CSBase;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+MemRecNCPUMemRecTypingNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ S_UINT64 SMsr;
+
+ MEM_DATA_STRUCT *MemPtr;
+ MemPtr = NBPtr->MemPtr;
+
+ //
+ //======================================================================
+ // 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
+
+ LibAmdMsrRead (SYS_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.lo &= 0xFFF7FFFF; // turn off modification enable bit
+ LibAmdMsrWrite (SYS_CFG, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ //
+ //======================================================================
+ // Set TOP_MEM and TOM2 CPU registers
+ //======================================================================
+ //
+ SMsr.hi = 0;
+ SMsr.lo = 0x08000000;
+ LibAmdMsrWrite (TOP_MEM, (UINT64 *)&SMsr, &MemPtr->StdHeader); // TOP_MEM
+
+ // Set FS Base address for later memory accesses
+ SMsr.lo = 0;
+ LibAmdMsrWrite (FS_BASE, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+
+ //
+ //======================================================================
+ // Set variable MTRR values
+ //======================================================================
+ //
+ SMsr.lo = 0x00000006;
+ LibAmdMsrWrite (0x200, (UINT64 *)&SMsr, &MemPtr->StdHeader); // MTRRPhysBase0
+
+ SMsr.hi = NBPtr->VarMtrrHiMsk;
+ SMsr.lo = 0xF8000800;
+ LibAmdMsrWrite (0x201, (UINT64 *)&SMsr, &MemPtr->StdHeader); // MTRRPhysMask0
+
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ *
+ * This function returns the upper 32 bits mask for variable MTRR based on
+ * the CPU_LOGICAL_ID.
+ * @param[in] *LogicalIdPtr - Pointer to the CPU_LOGICAL_ID
+ * @param[in] StdHeader - Header for library and services
+ *
+ * @return UINT32 - MTRR mask for upper 32 bits
+ *
+ */
+UINT32
+MemRecGetVarMtrrHiMsk (
+ IN CPU_LOGICAL_ID *LogicalIdPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 TempNotCare;
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+ CACHE_INFO *CacheInfoPtr;
+
+ GetCpuServicesFromLogicalId (LogicalIdPtr, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
+ FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &TempNotCare, StdHeader);
+ return (UINT32) (CacheInfoPtr->VariableMtrrMask >> 32);
+}
+
+/*-----------------------------------------------------------------------------
+ *
+ *
+ * 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
+MemRecNReEnablePhyCompNb (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN OUT VOID *OptParam
+ )
+{
+ UINT8 Dct;
+
+ Dct = NBPtr->Dct;
+
+ NBPtr->SwitchDCT (NBPtr, 0);
+ // Clear DisableCal and set DisablePredriverCal
+ MemRecNSetBitFieldNb (NBPtr, BFDisablePredriverCal, 0x2000);
+ NBPtr->SwitchDCT (NBPtr, Dct);
+
+ return TRUE;
+}
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrntrain3.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrntrain3.c
new file mode 100644
index 0000000000..e102af4cf7
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/NB/mrntrain3.c
@@ -0,0 +1,158 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrntrain3.c
+ *
+ * Common Recovery Northbridge function for training flow for DDR3
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Mem/NB)
+ * @e \$Revision: 49896 $ @e \$Date: 2011-03-30 02:18:18 -0600 (Wed, 30 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mrt3.h"
+#include "Filecode.h"
+#define FILECODE PROC_RECOVERY_MEM_NB_MRNTRAIN3_FILECODE
+/* features */
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * 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
+ */
+VOID
+MemNRecTrainingFlowNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MemRecTTrainDQSWriteHw3 (NBPtr->TechPtr);
+
+ MemRecTTrainRcvrEnSw (NBPtr->TechPtr);
+
+ MemRecTTrainDQSPosSw (NBPtr->TechPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets the client training control flow
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ */
+VOID
+MemNRecTrainingFlowClientNb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ IDS_HDT_CONSOLE (MEM_STATUS, "\nStart serial training\n");
+ IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", NBPtr->MCTPtr->DieId);
+
+ MemRecTTrainDQSWriteHw3 (NBPtr->TechPtr);
+
+ MemRecTTrainRcvrEnHw (NBPtr->TechPtr);
+
+ // Clear DisableCal and set DisablePredriverCal
+ NBPtr->FamilySpecificHook[ReEnablePhyComp] (NBPtr, NBPtr);
+ NBPtr->SetBitField (NBPtr, BFRxPtrInitReq, 1);
+ while (NBPtr->GetBitField (NBPtr, BFRxPtrInitReq) != 0) {}
+ NBPtr->SetBitField (NBPtr, BFDisDllShutdownSR, 1);
+ NBPtr->SetBitField (NBPtr, BFEnterSelfRef, 1);
+ while (NBPtr->GetBitField (NBPtr, BFEnterSelfRef) != 0) {}
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClkAlign = 2\n");
+ NBPtr->SetBitField (NBPtr, BFDbeGskMemClkAlignMode, 2);
+ NBPtr->SetBitField (NBPtr, BFExitSelfRef, 1);
+ while (NBPtr->GetBitField (NBPtr, BFExitSelfRef) != 0) {}
+ NBPtr->SetBitField (NBPtr, BFDisDllShutdownSR, 0);
+
+ MemRecTTrainDQSPosSw (NBPtr->TechPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ *
+ * This function sets the Unb training control flow
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ */
+VOID
+MemNRecTrainingFlowUnb (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ MemRecTTrainDQSWriteHw3 (NBPtr->TechPtr);
+
+ MemRecTTrainDQSPosSw (NBPtr->TechPtr);
+
+ MemRecTTrainRcvrEnHwSeedless (NBPtr->TechPtr);
+}
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrp.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrp.c
new file mode 100644
index 0000000000..fe6006857b
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrp.c
@@ -0,0 +1,258 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrp.c
+ *
+ * Common platform specific configuration.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "OptionMemory.h"
+#include "ma.h"
+#include "mp.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_PS_MRP_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern MEM_PSC_FLOW_BLOCK* memRecPlatSpecFlowArray[];
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function gets platform specific configuration such as Max Freq., Slow Mode, Dram Term,
+ * and so on.
+ *
+ * @param[in] *NBPtr Pointer to MEM_NB_BLOCK
+ * @return TRUE - Successfully execute platform specific configuration flow.
+ * @return FALSE - Fail to execute platform specific configuration flow.
+ *
+ */
+BOOLEAN
+MemPRecPSCFlow (
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 i;
+
+ i = 0;
+ while (memRecPlatSpecFlowArray[i] != NULL) {
+ if ((memRecPlatSpecFlowArray[i])->DramTerm (NBPtr, (memRecPlatSpecFlowArray[i])->EntryOfTables)) {
+ if ((memRecPlatSpecFlowArray[i])->ODTPattern (NBPtr, (memRecPlatSpecFlowArray[i])->EntryOfTables)) {
+ if ((memRecPlatSpecFlowArray[i])->SAO (NBPtr, (memRecPlatSpecFlowArray[i])->EntryOfTables)) {
+ if ((memRecPlatSpecFlowArray[i])->MR0WrCL (NBPtr, (memRecPlatSpecFlowArray[i])->EntryOfTables)) {
+ if ((memRecPlatSpecFlowArray[i])->RC2IBT (NBPtr, (memRecPlatSpecFlowArray[i])->EntryOfTables)) {
+ if ((memRecPlatSpecFlowArray[i])->RC10OpSpeed (NBPtr, (memRecPlatSpecFlowArray[i])->EntryOfTables)) {
+ if ((memRecPlatSpecFlowArray[i])->LRIBT (NBPtr, (memRecPlatSpecFlowArray[i])->EntryOfTables)) {
+ if ((memRecPlatSpecFlowArray[i])->LRNPR (NBPtr, (memRecPlatSpecFlowArray[i])->EntryOfTables)) {
+ if ((memRecPlatSpecFlowArray[i])->LRNLR (NBPtr, (memRecPlatSpecFlowArray[i])->EntryOfTables)) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ i++;
+ }
+ return FALSE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function constructs the rank type map of Dimm0, Dimm1, Dimm2. Also it counts the number
+ * of dimm in the table.
+ *
+ * @param[in] Dimm0 Rank type of Dimm0
+ * @param[in] Dimm1 Rank type of Dimm1
+ * @param[in] Dimm2 Rank type of Dimm2
+ * @param[in, out] *RankTypeInTable Pointer to RankTypeInTable variable
+ *
+ *
+ */
+VOID
+MemPRecConstructRankTypeMap (
+ IN UINT16 Dimm0,
+ IN UINT16 Dimm1,
+ IN UINT16 Dimm2,
+ IN OUT UINT16 *RankTypeInTable
+ )
+{
+ UINT8 i;
+ UINT16 RT;
+ UINT8 BitShift;
+
+ *RankTypeInTable = 0;
+ RT = 0;
+ BitShift = 0;
+
+ for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
+ switch (i) {
+ case 0:
+ RT = (Dimm0 == 0) ? NP : Dimm0;
+ BitShift = 0;
+ break;
+ case 1:
+ RT = (Dimm1 == 0) ? NP : Dimm1;
+ BitShift = 4;
+ break;
+ case 2:
+ RT = (Dimm2 == 0) ? NP : Dimm2;
+ BitShift = 8;
+ break;
+ default:
+ // dimm3 is not used, fills nibble3 with "NP"
+ RT = NP;
+ BitShift = 12;
+ }
+ *RankTypeInTable |= RT << BitShift;
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/**
+ * MemPIsIdSupported
+ * This function matches the CPU_LOGICAL_ID and PackageType with certain criteria to
+ * determine if it is supported by this NB type.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] LogicalId - CPU_LOGICAL_ID
+ * @param[in] PackageType - Package Type
+ *
+ * @return TRUE - NB type is matched !
+ * @return FALSE - NB type is not matched !
+ *
+ */
+BOOLEAN
+MemPRecIsIdSupported (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN CPU_LOGICAL_ID LogicalId,
+ IN UINT8 PackageType
+ )
+{
+ CPUID_DATA CpuId;
+ UINT8 PkgType;
+
+ LibAmdCpuidRead (AMD_CPUID_FMF, &CpuId, &(NBPtr->MemPtr->StdHeader));
+ PkgType = (UINT8) (CpuId.EBX_Reg >> 28) & 0xF; // bit 31:28
+
+ if (((NBPtr->MCTPtr->LogicalCpuid.Family & LogicalId.Family) != 0)
+ && ((NBPtr->MCTPtr->LogicalCpuid.Revision & LogicalId.Revision) != 0)) {
+ if ((PackageType == PT_DONT_CARE) || (PackageType == PkgType)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function returns the rank type map of a channel.
+ *
+ * @param[in] *CurrentChannel Pointer to CH_DEF_STRUCT
+ *
+ * @return UINT16 - The map of rank type.
+ *
+ */
+UINT16
+MemPRecGetPsRankType (
+ IN CH_DEF_STRUCT *CurrentChannel
+ )
+{
+ UINT8 i;
+ UINT16 DIMMRankType;
+
+ DIMMRankType = 0;
+ for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
+ if ((CurrentChannel->DimmQrPresent & (UINT8) 1 << i) != 0) {
+ if (i < 2) {
+ DIMMRankType |= (UINT16) 8 << (i << 2);
+ }
+ } else if ((CurrentChannel->DimmDrPresent & (UINT8) 1 << i) != 0) {
+ DIMMRankType |= (UINT16) 4 << (i << 2);
+ } else if ((CurrentChannel->DimmSRPresent & (UINT8) 1 << i) != 0) {
+ DIMMRankType |= (UINT16) 2 << (i << 2);
+ } else {
+ DIMMRankType |= (UINT16) 1 << (i << 2);
+ }
+ }
+ return DIMMRankType;
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplribt.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplribt.c
new file mode 100644
index 0000000000..eb930ffec7
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplribt.c
@@ -0,0 +1,182 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrplribt.c
+ *
+ * A sub-engine which extracts F0RC8, F1RC0, F1RC1 and F1RC2 value for LRDIMM configuration.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "mru.h"
+#include "ma.h"
+#include "mp.h"
+#include "cpuFamRegisters.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+#define FILECODE PROC_RECOVERY_MEM_PS_MRPLRIBT_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * A sub-function which extracts LRDIMM F0RC8, F1RC0, F1RC1 and F1RC2 value from a input
+ * table and stores extracted value to a specific address.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *EntryOfTables - Pointer to MEM_PSC_TABLE_BLOCK
+ *
+ * @return TRUE - Succeed in extracting the table value
+ * @return FALSE - Fail to extract the table value
+ *
+ */
+BOOLEAN
+MemPRecGetLRIBT (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN MEM_PSC_TABLE_BLOCK *EntryOfTables
+ )
+{
+ UINT8 i;
+ UINT8 MaxDimmPerCh;
+ UINT8 NOD;
+ UINT8 TableSize;
+ UINT8 DDR3Voltage;
+ UINT16 RankTypeOfPopulatedDimm;
+ UINT16 RankTypeInTable;
+ CPU_LOGICAL_ID LogicalCpuid;
+ UINT8 PackageType;
+ PSCFG_L_IBT_ENTRY *TblPtr;
+ CH_DEF_STRUCT *CurrentChannel;
+
+ CurrentChannel = NBPtr->ChannelPtr;
+
+ //@todo LRDIMM
+ //if (CurrentChannel->LrDimmPresent == 0) {
+ // return TRUE;
+ //}
+
+ TblPtr = NULL;
+ TableSize = 0;
+ PackageType = 0;
+ LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;
+ MaxDimmPerCh = RecGetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
+ NOD = (UINT8) 1 << (MaxDimmPerCh - 1);
+
+ i = 0;
+ // Obtain table pointer, table size, Logical Cpuid and PSC type according to NB type and package type.
+ while (EntryOfTables->TblEntryOfLRIBT[i] != NULL) {
+ if (((EntryOfTables->TblEntryOfLRIBT[i])->Header.NumOfDimm & NOD) != 0) {
+ LogicalCpuid = (EntryOfTables->TblEntryOfLRIBT[i])->Header.LogicalCpuid;
+ PackageType = (EntryOfTables->TblEntryOfLRIBT[i])->Header.PackageType;
+ //
+ // Determine if this is the expected NB Type
+ //
+ if (MemPRecIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
+ TblPtr = (PSCFG_L_IBT_ENTRY *) ((EntryOfTables->TblEntryOfLRIBT[i])->TBLPtr);
+ TableSize = (EntryOfTables->TblEntryOfLRIBT[i])->TableSize;
+ break;
+ }
+ }
+ i++;
+ }
+
+ // Check whether no table entry is found.
+ if (EntryOfTables->TblEntryOfLRIBT[i] == NULL) {
+ return FALSE;
+ }
+
+ DDR3Voltage = (UINT8) (1 << CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage));
+ RankTypeOfPopulatedDimm = MemPRecGetPsRankType (CurrentChannel);
+
+ for (i = 0; i < TableSize; i++) {
+ MemPRecConstructRankTypeMap ((UINT16) TblPtr->Dimm0, (UINT16) TblPtr->Dimm1, (UINT16) TblPtr->Dimm2, &RankTypeInTable);
+ if (TblPtr->DimmPerCh == MaxDimmPerCh) {
+ if ((TblPtr->VDDIO & DDR3Voltage) != 0) {
+ if ((RankTypeInTable & RankTypeOfPopulatedDimm) == RankTypeOfPopulatedDimm) {
+ NBPtr->PsPtr->F0RC8 = (UINT8) TblPtr->F0RC8;
+ NBPtr->PsPtr->F1RC0 = (UINT8) TblPtr->F1RC0;
+ NBPtr->PsPtr->F1RC1 = (UINT8) TblPtr->F1RC1;
+ NBPtr->PsPtr->F1RC2 = (UINT8) TblPtr->F1RC2;
+ break;
+ }
+ }
+ }
+ TblPtr++;
+ }
+ if (i == TableSize) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplrnlr.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplrnlr.c
new file mode 100644
index 0000000000..da478396ae
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplrnlr.c
@@ -0,0 +1,110 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrplrnlr.c
+ *
+ * A sub-engine which extracts F0RC13[NumLogicalRanks] value for LRDIMM configuration.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "mru.h"
+#include "ma.h"
+#include "mp.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+#define FILECODE PROC_RECOVERY_MEM_PS_MRPLRNLR_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * A sub-function which extracts LRDIMM F0RC13[NumLogicalRanks] value from a input
+ * table and stores extracted value to a specific address.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *EntryOfTables - Pointer to MEM_PSC_TABLE_BLOCK
+ *
+ * @return TRUE - Succeed in extracting the table value
+ * @return FALSE - Fail to extract the table value
+ *
+ */
+BOOLEAN
+MemPRecGetLRNLR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN MEM_PSC_TABLE_BLOCK *EntryOfTables
+ )
+{
+ return TRUE;
+} \ No newline at end of file
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplrnpr.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplrnpr.c
new file mode 100644
index 0000000000..10d4b4f5d9
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrplrnpr.c
@@ -0,0 +1,110 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrplrnpr.c
+ *
+ * A sub-engine which extracts F0RC13[NumPhysicalRanks] value for LRDIMM configuration.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "mru.h"
+#include "ma.h"
+#include "mp.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+#define FILECODE PROC_RECOVERY_MEM_PS_MRPLRNPR_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * A sub-function which extracts LRDIMM F0RC13[NumPhysicalRanks] value from a input
+ * table and stores extracted value to a specific address.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *EntryOfTables - Pointer to MEM_PSC_TABLE_BLOCK
+ *
+ * @return TRUE - Succeed in extracting the table value
+ * @return FALSE - Fail to extract the table value
+ *
+ */
+BOOLEAN
+MemPRecGetLRNPR (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN MEM_PSC_TABLE_BLOCK *EntryOfTables
+ )
+{
+ return TRUE;
+} \ No newline at end of file
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpmr0.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpmr0.c
new file mode 100644
index 0000000000..4f851581ac
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpmr0.c
@@ -0,0 +1,177 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mpmr0.c
+ *
+ * A sub-engine which extracts MR0[WR] and MR0[CL] value.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "mu.h"
+#include "ma.h"
+#include "mp.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_PS_MRPMR0_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * A sub-function which extracts MR0[WR] or MR0[CL] value from a input table and store the
+ * value to a specific address.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *EntryOfTables - Pointer to MEM_PSC_TABLE_BLOCK
+ *
+ * @return TRUE - Succeed in extracting the table value
+ * @return FALSE - Fail to extract the table value
+ *
+ */
+BOOLEAN
+MemPRecGetMR0WrCL (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN MEM_PSC_TABLE_BLOCK *EntryOfTables
+ )
+{
+ UINT8 i;
+ UINT8 j;
+ UINT8 p;
+ UINT32 Value32;
+ UINT8 TableSize;
+ PSCFG_TYPE Type;
+ CPU_LOGICAL_ID LogicalCpuid;
+ UINT8 PackageType;
+ PSCFG_MR0CL_ENTRY *TblPtr;
+ PSC_TBL_ENTRY **ptr;
+ CH_DEF_STRUCT *CurrentChannel;
+
+ CurrentChannel = NBPtr->ChannelPtr;
+ TblPtr = NULL;
+ TableSize = 0;
+
+ // Extract MR0[WR] value, then MR0[CL] value
+ for (i = 0; i < 2; i++) {
+ if (i == 0) {
+ ptr = EntryOfTables->TblEntryOfMR0WR;
+ Type = PSCFG_MR0WR;
+ } else {
+ ptr = EntryOfTables->TblEntryOfMR0CL;
+ Type = PSCFG_MR0CL;
+ }
+
+ p = 0;
+ // Obtain table pointer, table size, Logical Cpuid and PSC type according to Dimm, NB and package type.
+ while (ptr[p] != NULL) {
+ //
+ // Determine if this is the expected NB Type
+ //
+ LogicalCpuid = (ptr[p])->Header.LogicalCpuid;
+ PackageType = (ptr[p])->Header.PackageType;
+ if (MemPRecIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
+ TblPtr = (PSCFG_MR0CL_ENTRY *) ((ptr[p])->TBLPtr);
+ TableSize = (ptr[p])->TableSize;
+ break;
+ }
+ p++;
+ }
+
+ // Check whether no table entry is found.
+ if (ptr[p] == NULL) {
+ return FALSE;
+ }
+
+ Value32 = (Type == PSCFG_MR0WR) ? NBPtr->GetBitField (NBPtr, BFTwrDDR3) : NBPtr->GetBitField (NBPtr, BFTcl);
+
+ for (j = 0; j < TableSize; j++, TblPtr++) {
+ if (Value32 == (UINT32) TblPtr->Timing) {
+ if (Type == PSCFG_MR0WR) {
+ NBPtr->PsPtr->MR0WR = (UINT8) TblPtr->Value;
+ break;
+ } else {
+ NBPtr->PsPtr->MR0CL31 = (UINT8) TblPtr->Value;
+ NBPtr->PsPtr->MR0CL0 = (UINT8) TblPtr->Value1;
+ break;
+ }
+ }
+ }
+ if (j == TableSize) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpodtpat.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpodtpat.c
new file mode 100644
index 0000000000..9b6b2f66cd
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpodtpat.c
@@ -0,0 +1,182 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrpodtpat.c
+ *
+ * A sub-engine which extracts ODT pattern value.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "mru.h"
+#include "ma.h"
+#include "mp.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+#define FILECODE PROC_RECOVERY_MEM_PS_MRPODTPAT_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * A sub-function which extracts ODT Pattern value from a input table and stores extracted
+ * value to a specific address.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *EntryOfTables - Pointer to MEM_PSC_TABLE_BLOCK
+ *
+ * @return TRUE - Table values can be extracted per dimm population and ranks type.
+ * @return FALSE - Table values cannot be extracted per dimm population and ranks type.
+ *
+ */
+BOOLEAN
+MemPRecGetODTPattern (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN MEM_PSC_TABLE_BLOCK *EntryOfTables
+ )
+{
+ UINT8 i;
+ UINT16 RankTypeInTable;
+ UINT16 RankTypeOfPopulatedDimm;
+ UINT8 MaxDimmPerCh;
+ UINT8 NOD;
+ UINT8 TableSize;
+ DIMM_TYPE DimmType;
+ CPU_LOGICAL_ID LogicalCpuid;
+ UINT8 PackageType;
+ PSCFG_3D_ODTPAT_ENTRY *TblPtr;
+ CH_DEF_STRUCT *CurrentChannel;
+
+ CurrentChannel = NBPtr->ChannelPtr;
+
+ TblPtr = NULL;
+ TableSize = 0;
+ PackageType = 0;
+ LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;
+ MaxDimmPerCh = RecGetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
+ NOD = (UINT8) 1 << (MaxDimmPerCh - 1);
+
+ if (CurrentChannel->RegDimmPresent != 0) {
+ DimmType = RDIMM_TYPE;
+ } else if (CurrentChannel->SODimmPresent != 0) {
+ DimmType = SODIMM_TYPE;
+ //@todo LRDIMM
+ //} else if (CurrentChannel->LrDimmPresent) {
+ // DimmType = LRDIMM_TYPE;
+ } else {
+ DimmType = UDIMM_TYPE;
+ }
+
+ i = 0;
+ // Obtain table pointer, table size, Logical Cpuid and PSC type according to Dimm, NB and package type.
+ while (EntryOfTables->TblEntryOfODTPattern[i] != NULL) {
+ if (((EntryOfTables->TblEntryOfODTPattern[i])->Header.DimmType & DimmType) != 0) {
+ if (((EntryOfTables->TblEntryOfODTPattern[i])->Header.NumOfDimm & NOD) != 0) {
+ //
+ // Determine if this is the expected NB Type
+ //
+ LogicalCpuid = (EntryOfTables->TblEntryOfODTPattern[i])->Header.LogicalCpuid;
+ PackageType = (EntryOfTables->TblEntryOfODTPattern[i])->Header.PackageType;
+ if (MemPRecIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
+ TblPtr = (PSCFG_3D_ODTPAT_ENTRY *) ((EntryOfTables->TblEntryOfODTPattern[i])->TBLPtr);
+ TableSize = (EntryOfTables->TblEntryOfODTPattern[i])->TableSize;
+ break;
+ }
+ }
+ }
+ i++;
+ }
+
+ // Check whether no table entry is found.
+ if (EntryOfTables->TblEntryOfODTPattern[i] == NULL) {
+ return FALSE;
+ }
+
+ RankTypeOfPopulatedDimm = MemPRecGetPsRankType (CurrentChannel); //@todo - LRDIMM ?
+
+ for (i = 0; i < TableSize; i++) {
+ MemPRecConstructRankTypeMap ((UINT16) TblPtr->Dimm0, (UINT16) TblPtr->Dimm1, (UINT16) TblPtr->Dimm2, &RankTypeInTable);
+ if ((RankTypeInTable & RankTypeOfPopulatedDimm) == RankTypeOfPopulatedDimm) {
+ CurrentChannel->PhyRODTCSHigh = TblPtr->RdODTCSHigh;
+ CurrentChannel->PhyRODTCSLow = TblPtr->RdODTCSLow;
+ CurrentChannel->PhyWODTCSHigh = TblPtr->WrODTCSHigh;
+ CurrentChannel->PhyWODTCSLow = TblPtr->WrODTCSLow;
+ return TRUE;
+ }
+ TblPtr++;
+ }
+ return FALSE;
+} \ No newline at end of file
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprc10opspd.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprc10opspd.c
new file mode 100644
index 0000000000..a9f254017a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprc10opspd.c
@@ -0,0 +1,92 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrprc10opspd.c
+ *
+ * A sub-engine which extracts RC10 operating speed value for RDIMM configuration.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "mru.h"
+#include "ma.h"
+#include "mp.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_PS_MRPRC10OPSPD_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprc2ibt.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprc2ibt.c
new file mode 100644
index 0000000000..3206a057cb
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprc2ibt.c
@@ -0,0 +1,198 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrprc2ibt.c
+ *
+ * A sub-engine which extracts RC2[IBT] value for RDIMM configuration.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "mru.h"
+#include "ma.h"
+#include "mp.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+#define FILECODE PROC_RECOVERY_MEM_PS_MRPRC2IBT_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * A sub-function which extracts RC2[IBT] value from a input table and stores extracted
+ * value to a specific address.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *EntryOfTables - Pointer to MEM_PSC_TABLE_BLOCK
+ *
+ * @return TRUE - Table values can be extracted for all present dimms/ranks
+ * @return FALSE - Table values cannot be extracted for all present dimms/ranks
+ *
+ */
+BOOLEAN
+MemPRecGetRC2IBT (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN MEM_PSC_TABLE_BLOCK *EntryOfTables
+ )
+{
+ UINT8 i;
+ UINT8 MaxDimmPerCh;
+ UINT8 NOD;
+ UINT8 DimmIndex;
+ UINT8 TableSize;
+ UINT8 DDR3Voltage;
+ UINT16 RankTypeOfPopulatedDimm;
+ UINT16 RankTypeInTable;
+ CPU_LOGICAL_ID LogicalCpuid;
+ UINT8 PackageType;
+ UINT8 TgtDimmType;
+ UINT8 NumOfReg;
+ PSCFG_MR2IBT_ENTRY *TblPtr;
+ PSCFG_MR2IBT_ENTRY *OrgTblPtr;
+ CH_DEF_STRUCT *CurrentChannel;
+
+ CurrentChannel = NBPtr->ChannelPtr;
+
+ if (CurrentChannel->RegDimmPresent == 0) {
+ return TRUE;
+ }
+
+ TblPtr = NULL;
+ TableSize = 0;
+ PackageType = 0;
+ MaxDimmPerCh = RecGetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
+ NOD = (UINT8) 1 << (MaxDimmPerCh - 1);
+
+ i = 0;
+ // Obtain table pointer, table size, Logical Cpuid and PSC type according to NB type and package type.
+ while (EntryOfTables->TblEntryOfRC2IBT[i] != NULL) {
+ if (((EntryOfTables->TblEntryOfRC2IBT[i])->Header.NumOfDimm & NOD) != 0) {
+ LogicalCpuid = (EntryOfTables->TblEntryOfRC2IBT[i])->Header.LogicalCpuid;
+ PackageType = (EntryOfTables->TblEntryOfRC2IBT[i])->Header.PackageType;
+ //
+ // Determine if this is the expected NB Type
+ //
+ if (MemPRecIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
+ TblPtr = (PSCFG_MR2IBT_ENTRY *) ((EntryOfTables->TblEntryOfRC2IBT[i])->TBLPtr);
+ TableSize = (EntryOfTables->TblEntryOfRC2IBT[i])->TableSize;
+ break;
+ }
+ }
+ i++;
+ }
+
+ // Check whether no table entry is found.
+ if (EntryOfTables->TblEntryOfRC2IBT[i] == NULL) {
+ return FALSE;
+ }
+
+ DDR3Voltage = (UINT8) (1 << CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage));
+ RankTypeOfPopulatedDimm = MemPRecGetPsRankType (CurrentChannel);
+
+ OrgTblPtr = TblPtr;
+ for (DimmIndex = 0; DimmIndex < MAX_DIMMS_PER_CHANNEL; DimmIndex++) {
+ TblPtr = OrgTblPtr;
+ if ((CurrentChannel->ChDimmValid& (UINT8) (1 << DimmIndex)) != 0) {
+ NumOfReg = CurrentChannel->CtrlWrd02[DimmIndex];
+ if ((CurrentChannel->DimmQrPresent & (UINT8) (1 << DimmIndex)) != 0) {
+ TgtDimmType = DIMM_QR;
+ } else if ((CurrentChannel->DimmDrPresent & (UINT8) (1 << DimmIndex)) != 0) {
+ TgtDimmType = DIMM_DR;
+ } else {
+ TgtDimmType = DIMM_SR;
+ }
+
+ for (i = 0; i < TableSize; i++) {
+ MemPRecConstructRankTypeMap ((UINT16) TblPtr->Dimm0, (UINT16) TblPtr->Dimm1, (UINT16) TblPtr->Dimm2, &RankTypeInTable);
+ if (TblPtr->DimmPerCh == MaxDimmPerCh) {
+ if ((TblPtr->VDDIO & DDR3Voltage) != 0) {
+ if ((RankTypeInTable & RankTypeOfPopulatedDimm) == RankTypeOfPopulatedDimm) {
+ if ((TblPtr->Dimm & TgtDimmType) != 0) {
+ // If TblPtr->NumOfReg == 0x0F, that means the condition will be TRUE regardless of NumRegisters in DIMM
+ if ((TblPtr->NumOfReg == 0xF) || (TblPtr->NumOfReg == NumOfReg)) {
+ CurrentChannel->CtrlWrd02[DimmIndex] = (UINT8) ((TblPtr->IBT & 0x1) << 2);
+ CurrentChannel->CtrlWrd08[DimmIndex] = (UINT8) ((TblPtr->IBT & 0xE) >> 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+ TblPtr++;
+ }
+ }
+ }
+ return TRUE;
+} \ No newline at end of file
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprtt.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprtt.c
new file mode 100644
index 0000000000..6417debb8a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrprtt.c
@@ -0,0 +1,217 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrprtt.c
+ *
+ * A sub-engine which extracts RttNom and RttWr (Dram Term and Dynamic Dram Term) value.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 50607 $ @e \$Date: 2011-04-12 13:49:12 -0600 (Tue, 12 Apr 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "mru.h"
+#include "ma.h"
+#include "mp.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_PS_MRPRTT_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * A sub-function which extracts RttNom and RttWr value from a input table and stores extracted
+ * value to a specific address.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *EntryOfTables - Pointer to MEM_PSC_TABLE_BLOCK
+ *
+ * @return TRUE - Table values can be extracted for all present dimms/ranks
+ * @return FALSE - Table values cannot be extracted for all present dimms/ranks
+ *
+ */
+BOOLEAN
+MemPRecGetRttNomWr (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN MEM_PSC_TABLE_BLOCK *EntryOfTables
+ )
+{
+ UINT8 i;
+ UINT8 MaxDimmPerCh;
+ UINT8 NOD;
+ UINT8 TableSize;
+ UINT8 DDR3Voltage;
+ UINT16 RankTypeOfPopulatedDimm;
+ UINT16 RankTypeInTable;
+ DIMM_TYPE DimmType;
+ CPU_LOGICAL_ID LogicalCpuid;
+ UINT8 PackageType;
+ UINT8 TgtDimmType;
+ UINT8 TgtRank;
+ UINT8 Chipsel;
+ PSCFG_RTT_ENTRY *TblPtr;
+ PSCFG_RTT_ENTRY *OrgTblPtr;
+ CH_DEF_STRUCT *CurrentChannel;
+
+ CurrentChannel = NBPtr->ChannelPtr;
+
+ TblPtr = NULL;
+ TableSize = 0;
+ PackageType = 0;
+ LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;
+ MaxDimmPerCh = RecGetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
+ NOD = (UINT8) 1 << (MaxDimmPerCh - 1);
+
+ if (CurrentChannel->RegDimmPresent != 0) {
+ DimmType = RDIMM_TYPE;
+ } else if (CurrentChannel->SODimmPresent != 0) {
+ DimmType = SODIMM_TYPE;
+ //@todo LRDIMM
+ //} else if (CurrentChannel->LrDimmPresent) {
+ // DimmType = LRDIMM_TYPE;
+ } else {
+ DimmType = UDIMM_TYPE;
+ }
+
+ i = 0;
+ // Obtain table pointer, table size, Logical Cpuid and PSC type according to Dimm, NB and package type.
+ while (EntryOfTables->TblEntryOfDramTerm[i] != NULL) {
+ if (((EntryOfTables->TblEntryOfDramTerm[i])->Header.DimmType & DimmType) != 0) {
+ if (((EntryOfTables->TblEntryOfDramTerm[i])->Header.NumOfDimm & NOD) != 0) {
+ //
+ // Determine if this is the expected NB Type
+ //
+ LogicalCpuid = (EntryOfTables->TblEntryOfDramTerm[i])->Header.LogicalCpuid;
+ PackageType = (EntryOfTables->TblEntryOfDramTerm[i])->Header.PackageType;
+ if (MemPRecIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
+ TblPtr = (PSCFG_RTT_ENTRY *) ((EntryOfTables->TblEntryOfDramTerm[i])->TBLPtr);
+ TableSize = (EntryOfTables->TblEntryOfDramTerm[i])->TableSize;
+ break;
+ }
+ }
+ }
+ i++;
+ }
+
+ // Check whether no table entry is found.
+ if (EntryOfTables->TblEntryOfDramTerm[i] == NULL) {
+ return FALSE;
+ }
+
+ DDR3Voltage = (UINT8) (1 << CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage));
+ RankTypeOfPopulatedDimm = MemPRecGetPsRankType (CurrentChannel); //@todo - LRDIMM ?
+
+ OrgTblPtr = TblPtr;
+ for (Chipsel = 0; Chipsel < MAX_CS_PER_CHANNEL; Chipsel++) {
+ TblPtr = OrgTblPtr;
+ if ((NBPtr->DCTPtr->Timings.CsPresent & (UINT16) (1 << Chipsel)) != 0) {
+ if ((CurrentChannel->DimmQrPresent & (UINT8) (1 << (Chipsel >> 1))) != 0) {
+ TgtDimmType = DIMM_QR;
+ TgtRank = (UINT8) ((Chipsel < 4) ? 1 << (Chipsel & 1) : 4 << (Chipsel & 1));
+ } else if ((CurrentChannel->DimmDrPresent & (UINT8) (1 << (Chipsel >> 1))) != 0) {
+ TgtDimmType = DIMM_DR;
+ TgtRank = (UINT8) 1 << (Chipsel & 1);
+ } else {
+ TgtDimmType = DIMM_SR;
+ TgtRank = (UINT8) 1 << (Chipsel & 1);
+ }
+
+ for (i = 0; i < TableSize; i++) {
+ MemPRecConstructRankTypeMap ((UINT16) TblPtr->Dimm0, (UINT16) TblPtr->Dimm1, (UINT16) TblPtr->Dimm2, &RankTypeInTable);
+ if (TblPtr->DimmPerCh == MaxDimmPerCh) {
+ if ((TblPtr->VDDIO & DDR3Voltage) != 0) {
+ if ((RankTypeInTable & RankTypeOfPopulatedDimm) == RankTypeOfPopulatedDimm) {
+ if ((TblPtr->Dimm & TgtDimmType) != 0) {
+ if ((TblPtr->Rank & TgtRank) != 0) {
+ NBPtr->PsPtr->RttNom[Chipsel] = (UINT8) TblPtr->RttNom;
+ NBPtr->PsPtr->RttWr[Chipsel] = (UINT8) TblPtr->RttWr;
+ break;
+ }
+ }
+ }
+ }
+ }
+ TblPtr++;
+ }
+ if (i == TableSize) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpsao.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpsao.c
new file mode 100644
index 0000000000..0f4c77adfc
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Ps/mrpsao.c
@@ -0,0 +1,187 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrpsao.c
+ *
+ * A sub-engine which extracts Slow access mode, Address timing and Output driver compensation value.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem/Ps)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "AdvancedApi.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuFamRegisters.h"
+#include "cpuRegisters.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "mru.h"
+#include "ma.h"
+#include "mp.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+#define FILECODE PROC_RECOVERY_MEM_PS_MRPSAO_FILECODE
+
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * A sub-function which extracts Slow mode, Address timing and Output driver compensation value
+ * from a input table and store those value to a specific address.
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in] *EntryOfTables - Pointer to MEM_PSC_TABLE_BLOCK
+ *
+ * @return TRUE - Table values can be extracted per dimm population and ranks type.
+ * @return FALSE - Table values cannot be extracted per dimm population and ranks type.
+ *
+ */
+BOOLEAN
+MemPRecGetSAO (
+ IN OUT MEM_NB_BLOCK *NBPtr,
+ IN MEM_PSC_TABLE_BLOCK *EntryOfTables
+ )
+{
+ UINT8 i;
+ UINT8 MaxDimmPerCh;
+ UINT8 NOD;
+ UINT8 TableSize;
+ UINT8 DDR3Voltage;
+ UINT16 RankTypeOfPopulatedDimm;
+ UINT16 RankTypeInTable;
+ DIMM_TYPE DimmType;
+ CPU_LOGICAL_ID LogicalCpuid;
+ UINT8 PackageType;
+ PSCFG_SAO_ENTRY *TblPtr;
+ CH_DEF_STRUCT *CurrentChannel;
+
+ CurrentChannel = NBPtr->ChannelPtr;
+
+ TblPtr = NULL;
+ TableSize = 0;
+ PackageType = 0;
+ LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;
+ MaxDimmPerCh = RecGetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
+ NOD = (UINT8) 1 << (MaxDimmPerCh - 1);
+
+ if (CurrentChannel->RegDimmPresent != 0) {
+ DimmType = RDIMM_TYPE;
+ } else if (CurrentChannel->SODimmPresent != 0) {
+ DimmType = SODIMM_TYPE;
+ //@todo LRDIMM
+ //} else if (CurrentChannel->LrDimmPresent) {
+ // DimmType = LRDIMM_TYPE;
+ } else {
+ DimmType = UDIMM_TYPE;
+ }
+
+ i = 0;
+ // Obtain table pointer, table size, Logical Cpuid and PSC type according to Dimm, NB and package type.
+ while (EntryOfTables->TblEntryOfSAO[i] != NULL) {
+ if (((EntryOfTables->TblEntryOfSAO[i])->Header.DimmType & DimmType) != 0) {
+ if (((EntryOfTables->TblEntryOfSAO[i])->Header.NumOfDimm & NOD) != 0) {
+ //
+ // Determine if this is the expected NB Type
+ //
+ LogicalCpuid = (EntryOfTables->TblEntryOfSAO[i])->Header.LogicalCpuid;
+ PackageType = (EntryOfTables->TblEntryOfSAO[i])->Header.PackageType;
+ if (MemPRecIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
+ TblPtr = (PSCFG_SAO_ENTRY *) ((EntryOfTables->TblEntryOfSAO[i])->TBLPtr);
+ TableSize = (EntryOfTables->TblEntryOfSAO[i])->TableSize;
+ break;
+ }
+ }
+ }
+ i++;
+ }
+
+ // Check whether no table entry is found.
+ if (EntryOfTables->TblEntryOfSAO[i] == NULL) {
+ return FALSE;
+ }
+
+ DDR3Voltage = (UINT8) (1 << CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage));
+ RankTypeOfPopulatedDimm = MemPRecGetPsRankType (CurrentChannel); //@todo - LRDIMM ?
+
+ for (i = 0; i < TableSize; i++) {
+ MemPRecConstructRankTypeMap ((UINT16) TblPtr->Dimm0, (UINT16) TblPtr->Dimm1, (UINT16) TblPtr->Dimm2, &RankTypeInTable);
+ if (TblPtr->DimmPerCh == MaxDimmPerCh) {
+ if ((TblPtr->VDDIO & DDR3Voltage) != 0) {
+ if ((RankTypeInTable & RankTypeOfPopulatedDimm) == RankTypeOfPopulatedDimm) {
+ CurrentChannel->DctAddrTmg = TblPtr->AddTmgCtl;
+ CurrentChannel->DctOdcCtl = TblPtr->ODC;
+ CurrentChannel->SlowMode = (TblPtr->SlowMode == 1) ? TRUE : FALSE;
+ return TRUE;
+ }
+ }
+ }
+ TblPtr++;
+ }
+ return FALSE;
+} \ No newline at end of file
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrt3.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrt3.c
new file mode 100644
index 0000000000..756b7be556
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrt3.c
@@ -0,0 +1,188 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrt3.c
+ *
+ * Common Technology functions for DDR3 Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "mrport.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mrt3.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_TECH_DDR3_MRT3_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function Constructs the technology block
+ *
+ * @param[in,out] *NBPtr - Pointer to the MEM_NB_BLOCK
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecConstructTechBlock3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN OUT MEM_NB_BLOCK *NBPtr
+ )
+{
+ UINT8 Dct;
+ UINT8 Channel;
+ for (Dct = 0; Dct < NBPtr->MCTPtr->DctCount; Dct++) {
+ NBPtr->SwitchDCT (NBPtr, Dct);
+ for (Channel = 0; Channel < NBPtr->DCTPtr->ChannelCount; Channel++) {
+ NBPtr->SwitchChannel (NBPtr, Channel);
+ NBPtr->ChannelPtr->TechType = DDR3_TECHNOLOGY;
+ }
+ }
+
+ TechPtr->NBPtr = NBPtr;
+ TechPtr->RefPtr = NBPtr->RefPtr;
+
+ TechPtr->DramInit = MemRecTDramInitSw3;
+ TechPtr->SetDramMode = MemRecTSetDramMode3;
+ TechPtr->DimmPresence = MemRecTDIMMPresence3;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets the initial controller environment before training.
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTBeginTraining (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ S_UINT64 SMsr;
+ MEM_DATA_STRUCT *MemPtr;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+ MemPtr = NBPtr->MemPtr;
+
+ LibAmdReadCpuReg (CR4_REG, &TechPtr->CR4reg);
+ LibAmdWriteCpuReg (CR4_REG, TechPtr->CR4reg | ((UINT32) 1 << 9)); // enable SSE2
+
+ LibAmdMsrRead (HWCR, (UINT64 *) (&SMsr), &MemPtr->StdHeader); // HWCR
+ TechPtr->HwcrLo = SMsr.lo;
+ SMsr.lo |= 0x00020000; // turn on HWCR.wrap32dis
+ SMsr.lo &= 0xFFFF7FFF; // turn off HWCR.SSEDIS
+ LibAmdMsrWrite (HWCR, (UINT64 *) (&SMsr), &MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets the final controller environment after training.
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTEndTraining (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ S_UINT64 SMsr;
+ MEM_DATA_STRUCT *MemPtr;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+ MemPtr = NBPtr->MemPtr;
+
+ LibAmdWriteCpuReg (CR4_REG, TechPtr->CR4reg);
+
+ LibAmdMsrRead (HWCR, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ SMsr.lo = TechPtr->HwcrLo;
+ LibAmdMsrWrite (HWCR, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+}
+
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtrci3.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtrci3.c
new file mode 100644
index 0000000000..ba5b4944ea
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtrci3.c
@@ -0,0 +1,243 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrtrci3.c
+ *
+ * Technology Control word initialization for DDR3 Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "mru.h"
+#include "mt.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_TECH_DDR3_MRTRCI3_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+UINT8
+STATIC
+MemRecTGetCtlWord3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 CtrlWordNum
+ );
+
+VOID
+STATIC
+MemRecTSendCtlWord3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 CmdNum,
+ IN UINT8 Value
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sends control words
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ * @return pDCT->Timings.TrwtTO updated
+ */
+
+VOID
+MemRecTDramControlRegInit3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ UINT8 RCNum;
+ UINT8 Data;
+
+ MEM_DATA_STRUCT *MemPtr;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+ MemPtr = NBPtr->MemPtr;
+
+ // wait 8us TACT must be changed to optimize to 8 MEM CLKs
+ // and wait 6us for PLL LOCK
+ MemRecUWait10ns (80 + 60, MemPtr);
+
+ // 2. Program F2x[1, 0]A8[CtrlWordCS]=bit mask for target chip selects.
+ NBPtr->SetBitField (NBPtr, BFCtrlWordCS, 3 << (NBPtr->DimmToBeUsed << 1));
+
+ for (RCNum = 0; RCNum <= 15; RCNum++) {
+ // wait 8us for TMRD, must be changed to optimize to 8 MEM CLKs
+ MemRecUWait10ns (80, MemPtr);
+
+ if ((RCNum != 6) && (RCNum != 7)) {
+ Data = MemRecTGetCtlWord3 (TechPtr, RCNum);
+ MemRecTSendCtlWord3 (TechPtr, RCNum, Data);
+ }
+ }
+
+ MemRecUWait10ns (60, MemPtr); // wait 6us for TSTAB
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates the ControlRC value
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] CtrlWordNum - control Word number.
+ *
+ * @return Control Word value
+ */
+
+UINT8
+STATIC
+MemRecTGetCtlWord3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 CtrlWordNum
+ )
+{
+ UINT8 Data;
+
+ CH_DEF_STRUCT *ChannelPtr;
+
+ ChannelPtr = TechPtr->NBPtr->ChannelPtr;
+
+ Data = 0; //Default value for all control words is 0
+ switch (CtrlWordNum) {
+ case 0:
+ Data = 0x02; // DA4=1
+ break;
+ case 1:
+ Data = 0x0C; // if single rank, set DBA1 and DBA0
+ break;
+ case 3:
+ Data = ChannelPtr->CtrlWrd03[TechPtr->NBPtr->DimmToBeUsed];
+ break;
+ case 4:
+ Data = ChannelPtr->CtrlWrd04[TechPtr->NBPtr->DimmToBeUsed];
+ break;
+ case 5:
+ Data = ChannelPtr->CtrlWrd05[TechPtr->NBPtr->DimmToBeUsed];
+ break;
+ case 9:
+ Data = 0x0D;
+ break;
+ default:;
+ }
+
+ return (Data&0x0F);
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sends control word command
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] CmdNum - control number.
+ * @param[in] Value - value to send
+ *
+ */
+
+VOID
+STATIC
+MemRecTSendCtlWord3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 CmdNum,
+ IN UINT8 Value
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+
+ ASSERT (CmdNum < 16);
+ ASSERT (Value < 16);
+
+ NBPtr = TechPtr->NBPtr;
+
+ // 1. Program MrsBank and MrsAddress.
+ // n = [BA2, A2, A1, A0].
+ // data = [BA1, BA0, A4, A3].
+ // Set all other bits in MrsAddress to zero.
+ //
+ NBPtr->SetBitField (NBPtr, BFMrsBank, ((CmdNum&8) >> 1) | (Value >> 2));
+ NBPtr->SetBitField (NBPtr, BFMrsAddress, ((Value&3) << 3) | (CmdNum&7));
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCS%d RC%02d %04x\n",
+ (NBPtr->GetBitField (NBPtr, BFDramInitRegReg) >> 20) & 0xF,
+ ((NBPtr->GetBitField (NBPtr, BFDramInitRegReg) >> 15) & 8) |
+ (NBPtr->GetBitField (NBPtr, BFDramInitRegReg) & 7),
+ ((NBPtr->GetBitField (NBPtr, BFDramInitRegReg) >> 14) & 0xC) |
+ ((NBPtr->GetBitField (NBPtr, BFDramInitRegReg) >> 3) & 3));
+
+ // 2.Set SendCtrlWord=1
+ NBPtr->SetBitField (NBPtr, BFSendCtrlWord, 1);
+ // 3.Wait for BFSendCtrlWord=0
+ while (NBPtr->GetBitField (NBPtr, BFSendCtrlWord) != 0) {}
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtsdi3.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtsdi3.c
new file mode 100644
index 0000000000..9224d18d4d
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtsdi3.c
@@ -0,0 +1,361 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrtsdi3.c
+ *
+ * Technology Software DRAM Init for DDR3 Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 49896 $ @e \$Date: 2011-03-30 02:18:18 -0600 (Wed, 30 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "mru.h"
+#include "mt.h"
+#include "mrt3.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_TECH_DDR3_MRTSDI3_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initiates software DRAM init
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTDramInitSw3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ UINT8 ChipSel;
+ MEM_DATA_STRUCT *MemPtr;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+ MemPtr = NBPtr->MemPtr;
+
+ IDS_HDT_CONSOLE (MEM_STATUS, "\nStart Dram Init\n");
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tEnDramInit = 1 for DCT%d\n", NBPtr->Dct);
+ // 3.Program F2x[1,0]7C[EnDramInit]=1
+ NBPtr->SetBitField (NBPtr, BFEnDramInit, 1);
+
+ // 4.wait 200us
+ MemRecUWait10ns (20000, MemPtr);
+
+ NBPtr->SetBitField (NBPtr, BFDeassertMemRstX, 1);
+
+ // 6.wait 500us
+ MemRecUWait10ns (50000, MemPtr);
+
+ // 7.NOP or deselect & take CKE high
+ NBPtr->SetBitField (NBPtr, BFAssertCke, 1);
+
+ // 8.wait 360ns
+ MemRecUWait10ns (36, MemPtr);
+
+ // The following steps are performed with registered DIMMs only and
+ // must be done for each chip select pair:
+ //
+ if (NBPtr->ChannelPtr->RegDimmPresent != 0) {
+ MemRecTDramControlRegInit3 (TechPtr);
+ }
+
+ for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel++) {
+ if ((NBPtr->DCTPtr->Timings.CsPresent & (UINT16) 1 << ChipSel) != 0) {
+
+ // Set Dram ODT per ChipSel
+ NBPtr->SetDramOdtRec (NBPtr, MISSION_MODE, ChipSel, (NBPtr->DimmToBeUsed << 1));
+
+ NBPtr->SetBitField (NBPtr, BFMrsChipSel, ChipSel);
+ // 13.Send EMRS(2)
+ MemRecTEMRS23 (TechPtr);
+ NBPtr->SendMrsCmd (NBPtr);
+
+ // 14.Send EMRS(3). Ordinarily at this time, MrsAddress[2:0]=000b
+ MemRecTEMRS33 (TechPtr);
+ NBPtr->SendMrsCmd (NBPtr);
+
+ // 15.Send EMRS(1).
+ MemRecTEMRS13 (TechPtr);
+ NBPtr->SendMrsCmd (NBPtr);
+
+ // 16.Send MRS with MrsAddress[8]=1(reset the DLL)
+ MemRecTMRS3 (TechPtr);
+ NBPtr->SendMrsCmd (NBPtr);
+
+ //wait 500us
+ MemRecUWait10ns (50000, MemPtr);
+
+ if (NBPtr->ChannelPtr->RegDimmPresent == 0) {
+ break;
+ }
+ }
+ }
+
+ // 17.Send two ZQCL commands (to even then odd chip select)
+ NBPtr->sendZQCmd (NBPtr);
+ NBPtr->sendZQCmd (NBPtr);
+
+ // 18.Program F2x[1,0]7C[EnDramInit]=0
+ NBPtr->SetBitField (NBPtr, BFEnDramInit, 0);
+ IDS_HDT_CONSOLE (MEM_FLOW, "End Dram Init\n\n");
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates the EMRS1 value
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTEMRS13 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ UINT16 MrsAddress;
+ UINT8 DramTerm;
+
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+
+ // BA2=0,BA1=0,BA0=1
+ NBPtr->SetBitField (NBPtr, BFMrsBank, 1);
+
+ MrsAddress = 0;
+
+ // program MrsAddress[5,1]=output driver impedance control (DIC):
+ // based on F2x[1,0]84[DrvImpCtrl], which is 2'b01
+ MrsAddress |= ((UINT16) 1 << 1);
+
+ // program MrsAddress[9,6,2]=nominal termination resistance of ODT (RTT):
+ // based on F2x[1,0]84[DramTerm], which is 3'b001 (60 Ohms)
+ if (!(NBPtr->IsSupported[CheckDramTerm])) {
+ DramTerm = (UINT8) NBPtr->GetBitField (NBPtr, BFDramTerm);
+ } else {
+ DramTerm = NBPtr->PsPtr->DramTerm;
+ }
+ if ((DramTerm & 1) != 0) {
+ MrsAddress |= ((UINT16) 1 << 2);
+ }
+ if ((DramTerm & 2) != 0) {
+ MrsAddress |= ((UINT16) 1 << 6);
+ }
+ if ((DramTerm & 4) != 0) {
+ MrsAddress |= ((UINT16) 1 << 9);
+ }
+
+ // program MrsAddress[12]=output disable (QOFF):
+ // based on F2x[1,0]84[Qoff], which is 1'b0
+
+ // program MrsAddress[11]=TDQS:
+ // based on F2x[1,0]94[RDqsEn], which is 1'b0
+
+ NBPtr->SetBitField (NBPtr, BFMrsAddress, MrsAddress);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates the EMRS2 value
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTEMRS23 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ UINT16 MrsAddress;
+ UINT8 DramTermDyn;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+
+ // BA2=0,BA1=1,BA0=0
+ NBPtr->SetBitField (NBPtr, BFMrsBank, 2);
+
+ // program MrsAddress[5:3]=CAS write latency (CWL):
+ // based on F2x[1,0]84[Tcwl], which is 3'b000
+ //
+ MrsAddress = 0;
+
+ // program MrsAddress[6]=auto self refresh method (ASR):
+ // based on F2x[1,0]84[ASR], which is 1'b1
+ // program MrsAddress[7]=self refresh temperature range (SRT):
+ // based on F2x[1,0]84[SRT], which is also 1'b0
+ //
+ MrsAddress |= (UINT16) 1 << 6;
+
+ // program MrsAddress[10:9]=dynamic termination during writes (RTT_WR):
+ // based on F2x[1,0]84[DramTermDyn]
+ //
+ if (!(NBPtr->IsSupported[CheckDramTermDyn])) {
+ DramTermDyn = (UINT8) NBPtr->GetBitField (NBPtr, BFDramTermDyn);
+ } else {
+ DramTermDyn = NBPtr->PsPtr->DynamicDramTerm;
+ }
+ MrsAddress |= (UINT16) DramTermDyn << 9;
+ NBPtr->SetBitField (NBPtr, BFMrsAddress, MrsAddress);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates the EMRS3 value
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTEMRS33 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+
+ // BA2=0,BA1=1,BA0=1
+ NBPtr->SetBitField (NBPtr, BFMrsBank, 3);
+
+ // program MrsAddress[1:0]=multi purpose register address location
+ // (MPR Location):based on F2x[1,0]84[MprLoc], which is 0
+ // program MrsAddress[2]=multi purpose register
+ // (MPR):based on F2x[1,0]84[MprEn], which is also 0
+ //
+ NBPtr->SetBitField (NBPtr, BFMrsAddress, 0);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This sets MSS value
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTMRS3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ UINT16 MrsAddress;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+
+ // BA2=0,BA1=0,BA0=0
+ NBPtr->SetBitField (NBPtr, BFMrsBank, 0);
+
+ // program MrsAddress[1:0]=burst length and control method
+ // (BL):based on F2x[1,0]84[BurstCtrl], which is 1'b0
+ //
+ MrsAddress = 0;
+
+ // program MrsAddress[3]=1 (BT):interleaved
+ MrsAddress |= (UINT16) 1 << 3;
+
+ // program MrsAddress[6:4,2]=read CAS latency
+ // (CL):based on F2x[1,0]88[Tcl], which is 4'b0010
+ MrsAddress |= (UINT16) 2 << 4;
+
+ // program MrsAddress[11:9]=write recovery for auto-precharge
+ // (WR):based on F2x[1,0]84[Twr], which is 3'b010
+ //
+ MrsAddress |= (UINT16) 2 << 9;
+
+ // program MrsAddress[12]=0 (PPD):slow exit
+
+ // program MrsAddress[8]=1 (DLL):DLL reset
+ MrsAddress |= (UINT16) 1 << 8; // just issue DLL reset at first time
+
+ NBPtr->SetBitField (NBPtr, BFMrsAddress, MrsAddress);
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtspd3.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtspd3.c
new file mode 100644
index 0000000000..f656a530bb
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtspd3.c
@@ -0,0 +1,325 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrtspd3.c
+ *
+ * Technology SPD supporting functions for DDR3 Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "mrtspd3.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_TECH_DDR3_MRTSPD3_FILECODE
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define _UNDEF_ 0xFF
+#define MAX_DIES_PER_SOCKET 2 ///< Set to largest of any CPU
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets the DRAM mode
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ * @return TRUE - indicates that the DRAM mode is set to DDR2
+ */
+
+BOOLEAN
+MemRecTSetDramMode3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ TechPtr->NBPtr->SetBitField (TechPtr->NBPtr, BFLegacyBiosMode, 0);
+ TechPtr->NBPtr->SetBitField (TechPtr->NBPtr, BFDdr3Mode, 1);
+ return TRUE;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function determines if DIMMs are present. It checks checksum and interrogates the SPDs
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ * @return TRUE - indicates that a FATAL error has not occurred
+ * @return FALL - indicates that a FATAL error has not occurred
+ */
+
+BOOLEAN
+MemRecTDIMMPresence3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ UINT8 Node;
+ UINT8 Dct;
+ UINT8 Channel;
+ UINT8 i;
+ SPD_DEF_STRUCT *SPDPtr;
+ UINT8 *SpdBufferPtr;
+ DIE_STRUCT *MCTPtr;
+ DCT_STRUCT *DCTPtr;
+ CH_DEF_STRUCT *ChannelPtr;
+ MEM_NB_BLOCK *NBPtr;
+ UINT16 MaxDimms;
+ UINT16 Value16;
+ UINT8 Devwidth;
+ UINT8 Value8;
+ UINT16 DimmMask;
+ UINT8 VoltageMap;
+ UINT8 VDDByte;
+ UINT32 V1_2XDimmMap;
+ UINT32 V1_35DimmMap;
+ UINT32 V1_5DimmMap;
+
+ NBPtr = TechPtr->NBPtr;
+ MCTPtr = NBPtr->MCTPtr;
+ VoltageMap = 0xFF;
+ V1_2XDimmMap = 0;
+ V1_35DimmMap = 0;
+ V1_5DimmMap = 0;
+
+ NBPtr->DimmToBeUsed = _UNDEF_;
+ for (Node = 0; Node < NBPtr->MemPtr->DieCount; Node++) {
+ NBPtr->SwitchNodeRec (NBPtr, Node);
+ for (Dct = 0; Dct < NBPtr->MCTPtr->DctCount; Dct++) {
+ NBPtr->SwitchDCT (NBPtr, Dct);
+ DCTPtr = NBPtr->DCTPtr;
+ for (Channel = 0; Channel < DCTPtr->ChannelCount; Channel++) {
+ NBPtr->SwitchChannel (NBPtr, Channel);
+ ChannelPtr = NBPtr->ChannelPtr;
+ SPDPtr = NBPtr->SPDPtr;
+
+ // Get the maximum number of DIMMs
+ MaxDimms = MAX_DIMMS_PER_CHANNEL;
+ for (i = 0; i < MaxDimms; i++) {
+ // Bitmask representing dimm #i.
+ DimmMask = (UINT16) 1 << i;
+
+ if (SPDPtr[i].DimmPresent) {
+ SpdBufferPtr = (UINT8 *)&(SPDPtr[i].Data);
+
+ MCTPtr->DimmPresent |= DimmMask;
+ if (SpdBufferPtr[SPD_TYPE] == JED_DDR3SDRAM) {
+ ChannelPtr->ChDimmValid |= DimmMask;
+ }
+
+ // Check module type information.
+ if (SpdBufferPtr[SPD_DIMM_TYPE] == JED_RDIMM || SpdBufferPtr[SPD_DIMM_TYPE] == JED_MINIRDIMM) {
+ ChannelPtr->RegDimmPresent |= DimmMask;
+ }
+
+ if (SpdBufferPtr[SPD_DIMM_TYPE] == JED_SODIMM) {
+ ChannelPtr->SODimmPresent |= DimmMask;
+ }
+
+ // Get the Dimm width data
+ Devwidth = SpdBufferPtr[SPD_DEV_WIDTH] & 0x7;
+ switch (Devwidth) {
+ case 0:
+ ChannelPtr->Dimmx4Present |= DimmMask;
+ Devwidth = 4;
+ break;
+ case 1:
+ ChannelPtr->Dimmx8Present |= DimmMask;
+ Devwidth = 8;
+ break;
+ case 2:
+ ChannelPtr->Dimmx16Present |= DimmMask;
+ Devwidth = 16;
+ break;
+ default:
+ IDS_ERROR_TRAP;
+ }
+
+ // Determine the page size.
+ // page_size = 2^COLBITS * Devwidth/8
+ //
+ Value16 = (((UINT16) 1 << (SpdBufferPtr[SPD_COL_SZ]&7)) * Devwidth) / 8;
+ if ((Value16 >> 11) == 0) {
+ DCTPtr->Timings.DIMM1KPage |= DimmMask;
+ }
+
+ // Calculate bus loading per Channel
+ if (Devwidth == 16) {
+ Devwidth = 4;
+ } else if (Devwidth == 4) {
+ Devwidth = 16;
+ }
+
+ // specify the number of ranks
+ Value8 = ((SpdBufferPtr[SPD_RANKS] >> 3) & 0x07) + 1;
+ if (Value8 > 2) {
+ ChannelPtr->DimmQrPresent |= DimmMask;
+ Devwidth = Devwidth << 2;
+ } else if (Value8 == 2) {
+ ChannelPtr->DimmDrPresent |= DimmMask; // Dual rank dimms
+ Devwidth = Devwidth << 1;
+ } else {
+ ChannelPtr->DimmSRPresent |= DimmMask;
+ }
+
+ ChannelPtr->Ranks = ChannelPtr->Ranks + Value8;
+ ChannelPtr->Loads = ChannelPtr->Loads + Devwidth;
+ ChannelPtr->Dimms++;
+
+ // Check address mirror support for Unbuffered Dimms only
+ if ((ChannelPtr->RegDimmPresent & DimmMask) == 0) {
+ if ((SpdBufferPtr[SPD_ADDRMAP] & 1) != 0) {
+ ChannelPtr->DimmMirrorPresent |= DimmMask;
+ }
+ }
+
+ // Get control word values for RC3, RC4 and RC5
+ ChannelPtr->CtrlWrd03[i] = SpdBufferPtr[SPD_CTLWRD03] >> 4;
+ ChannelPtr->CtrlWrd04[i] = SpdBufferPtr[SPD_CTLWRD04] & 0x0F;
+ ChannelPtr->CtrlWrd05[i] = SpdBufferPtr[SPD_CTLWRD05] >> 4;
+ //
+ // Temporarily store info. of SPD byte 63 into CtrlWrd02(s),
+ // and they will be used late to calculate real RC2 and RC8 value
+ //
+ ChannelPtr->CtrlWrd02[i] = SpdBufferPtr[SPD_ADDRMAP] & 0x03;
+
+ // Get the common voltage if possible and create the individual Dimm maps per voltage
+ VDDByte = SpdBufferPtr[SPD_MNVVDD];
+ VDDByte ^= 1;
+ VoltageMap &= VDDByte;
+ //
+ // Create the Dimms map
+ //
+ // Node: 1 0
+ // Dct: 1 0 1 0
+ // Dimm: 3210 3210 3210 3210
+ // Dimmbitmap: xxxx xxxx xxxx xxxx
+ // Ex. 0000 0001 0010 0000 (V1_2XDimmMap)
+ // This indicates Node0/Dct1/Dimm1 and Node1/Dct0/Dimm0 are 1.2XV supported.
+ if ((VDDByte & (UINT8) (1 << VOLT1_25)) != 0) {
+ V1_2XDimmMap |= (UINT32) DimmMask << ((Node * NBPtr->MCTPtr->DctCount + Dct) * MAX_DIMMS_PER_CHANNEL);
+ } else if ((VDDByte & (UINT8) (1 << VOLT1_35)) != 0) {
+ V1_35DimmMap |= (UINT32) DimmMask << ((Node * NBPtr->MCTPtr->DctCount + Dct) * MAX_DIMMS_PER_CHANNEL);
+ } else {
+ V1_5DimmMap |= (UINT32) DimmMask << ((Node * NBPtr->MCTPtr->DctCount + Dct) * MAX_DIMMS_PER_CHANNEL);
+ }
+ } // if DIMM present
+ } // Dimm loop
+ } // Channel loop
+ } // DCT loop
+ }
+
+ if (VoltageMap != 0xFF) {
+ if (VoltageMap == 0) {
+ NBPtr->RefPtr->DDR3Voltage = VOLT1_35;
+ if (V1_35DimmMap != 0) {
+ i = (UINT8) LibAmdBitScanForward (V1_35DimmMap);
+ } else {
+ i = (UINT8) LibAmdBitScanForward (V1_2XDimmMap);
+ }
+ } else {
+ NBPtr->RefPtr->DDR3Voltage = CONVERT_ENCODED_TO_VDDIO (LibAmdBitScanReverse (VoltageMap));
+ i = (UINT8) LibAmdBitScanForward (V1_2XDimmMap | V1_35DimmMap | V1_5DimmMap);
+ // In case of 1.35V Dimms and 1.5V Dimms mixture, we initialize the 1.35V Dimm.
+ if ((V1_35DimmMap != 0) && (V1_5DimmMap != 0)) {
+ NBPtr->RefPtr->DDR3Voltage = VOLT1_35;
+ i = (UINT8) LibAmdBitScanForward (V1_35DimmMap);
+ }
+ }
+ // Find out which Dimm we are going to initialize and which Node/Dct it belongs to
+ NBPtr->DimmToBeUsed = i % MAX_DIMMS_PER_CHANNEL;
+ Node = i / (NBPtr->MCTPtr->DctCount * MAX_DIMMS_PER_CHANNEL);
+ Dct = (i / MAX_DIMMS_PER_CHANNEL) & (NBPtr->MCTPtr->DctCount - 1);
+ NBPtr->SwitchNodeRec (NBPtr, Node);
+ NBPtr->SwitchDCT (NBPtr, Dct);
+ }
+
+ // If we have DIMMs, some further general characteristics checking
+ if (NBPtr->DimmToBeUsed == _UNDEF_) {
+ // Leave with an error - no dimms on this DCT
+ // LibAmdEventLog (AGESA_FATAL, MEM_ERROR_NO_DIMM_FOUND, 0, NBPtr->Dct, NBPtr->Channel, 0); //@attention commented out since it is not defined in recovery code
+ SetMemRecError (AGESA_FATAL, MCTPtr);
+ }
+
+ return (BOOLEAN) (MCTPtr->ErrCode < AGESA_FATAL);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtspd3.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtspd3.h
new file mode 100644
index 0000000000..24dccee13b
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrtspd3.h
@@ -0,0 +1,131 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrtspd3.h
+ *
+ * Technology SPD support for DDR3 Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MTSPD3_H_
+#define _MTSPD3_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*===============================================================================
+ * Jedec DDR III
+ *===============================================================================
+ */
+#define SPD_BYTE_USED 0
+#define SPD_TYPE 2 /* SPD byte read location */
+#define JED_DDR_SDRAM 7 /* Jedec defined bit field */
+#define JED_DDR2_SDRAM 8 /* Jedec defined bit field */
+#define JED_DDR3SDRAM 0xB /* Jedec defined bit field */
+
+#define SPD_DIMM_TYPE 3
+#define SPD_ATTRIB 21
+#define JED_DIF_CK_MSK 0x20 /* Differential Clock Input */
+#define JED_RDIMM 1
+#define JED_MINIRDIMM 5
+#define JED_UDIMM 2
+#define JED_SODIMM 3
+
+#define SPD_L_BANKS 4 /* [7:4] number of [logical] banks on each device */
+#define SPD_DENSITY 4 /* bit 3:0 */
+#define SPD_ROW_SZ 5 /* bit 5:3 */
+#define SPD_COL_SZ 5 /* bit 2:0 */
+#define SPD_MNVVDD 6
+#define SPD_RANKS 7 /* bit 5:3 */
+#define SPD_DEV_WIDTH 7 /* bit 2:0 */
+#define SPD_ECCBITS 8 /* bit 4:3 */
+#define JED_ECC 8
+#define SPD_RAWCARD 62 /* bit 2:0 */
+#define SPD_ADDRMAP 63 /* bit 0 */
+
+#define SPD_CTLWRD03 70 /* bit 7:4 */
+#define SPD_CTLWRD04 71 /* bit 3:0 */
+#define SPD_CTLWRD05 71 /* bit 7:4 */
+
+#define SPD_DIVIDENT 10
+#define SPD_DIVISOR 11
+
+#define SPD_TCK 12
+#define SPD_CASLO 14
+#define SPD_CASHI 15
+#define SPD_TAA 16
+
+#define SPD_TRP 20
+#define SPD_TRRD 19
+#define SPD_TRCD 18
+#define SPD_TRAS 22
+#define SPD_TWR 17
+#define SPD_TWTR 26
+#define SPD_TRTP 27
+#define SPD_TRC 23
+#define SPD_UPPER_TRC 21 /* bit 7:4 */
+#define SPD_UPPER_TRAS 21 /* bit 3:0 */
+#define SPD_TFAW 29
+#define SPD_UPPER_TFAW 28 /* bit 3:0 */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+#endif /* _MTSPD3_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrttwl3.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrttwl3.c
new file mode 100644
index 0000000000..f2ceb2cbb6
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/DDR3/mrttwl3.c
@@ -0,0 +1,369 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrttwl3.c
+ *
+ * Technology Phy assisted write levelization for recovery DDR3
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 50454 $ @e \$Date: 2011-04-10 21:20:37 -0600 (Sun, 10 Apr 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "mru.h"
+#include "mt.h"
+#include "mrt3.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_TECH_DDR3_MRTTWL3_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_BYTELANES 8 /* Max Bytelanes per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecTPrepareDIMMs3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN BOOLEAN Wl
+ );
+
+VOID
+STATIC
+MemRecTProcConfig3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+VOID
+STATIC
+MemRecTBeginWLTrain3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function executed hardware based write levelization for a specific die
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTTrainDQSWriteHw3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+
+ IDS_HDT_CONSOLE (MEM_STATUS, "\nStart write leveling\n");
+ // Disable auto refresh by configuring F2x[1, 0]8C[DisAutoRefresh] = 1.
+ NBPtr->SetBitField (NBPtr, BFDisAutoRefresh, 1);
+ // Disable ZQ calibration short command by configuring F2x[1, 0]94[ZqcsInterval] = 00b.
+ NBPtr->SetBitField (NBPtr, BFZqcsInterval, 0);
+
+ // 1. Specify the target Dimm that is to be trained by programming
+ // F2x[1, 0]9C_x08[TrDimmSel].
+ IDS_HDT_CONSOLE (MEM_STATUS, "\t\tCS %d\n", NBPtr->DimmToBeUsed << 1);
+ NBPtr->SetBitField (NBPtr, BFTrDimmSel, NBPtr->DimmToBeUsed);
+
+ // 2. Prepare the DIMMs for write levelization using DDR3-defined
+ // MR commands.
+ MemRecTPrepareDIMMs3 (TechPtr, TRUE);
+
+ // 3. After the DIMMs are configured, BIOS waits 40 MEMCLKs to
+ // satisfy DDR3-defined internal DRAM timing.
+ MemRecUWait10ns (10, NBPtr->MemPtr);
+
+ // 4. Configure the processor's DDR phy for write levelization training:
+ MemRecTProcConfig3 (TechPtr);
+
+ // 5. Begin write levelization training
+ MemRecTBeginWLTrain3 (TechPtr);
+
+ // 6. Configure DRAM Phy Control Register so that the phy stops driving write levelization ODT.
+ // Program WrLvOdtEn=0
+ NBPtr->SetBitField (NBPtr, BFWrLvOdtEn, 0);
+
+ // Wait 10 MEMCLKs to allow for ODT signal settling.
+ MemRecUWait10ns (3, NBPtr->MemPtr);
+
+ // 7. Program the target Dimm back to normal operation
+ MemRecTPrepareDIMMs3 (TechPtr, FALSE);
+
+ // 13.Program F2x[1, 0]8C[DisAutoRefresh] = 0.
+ NBPtr->SetBitField (NBPtr, BFDisAutoRefresh, 0);
+ // 14.Program F2x[1, 0]94[ZqcsInterval] to the proper interval for the current memory configuration.
+ NBPtr->SetBitField (NBPtr, BFZqcsInterval, 2);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "End write leveling\n\n");
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function prepares the DIMMS for Write Levelization
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] Wl - Indicates if WL mode should be enabled
+ *
+ */
+
+VOID
+STATIC
+MemRecTPrepareDIMMs3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN BOOLEAN Wl
+ )
+{
+ UINT8 ChipSel;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+
+ AGESA_TESTPOINT (TpProcMemWlPrepDimms, &(NBPtr->MemPtr->StdHeader));
+
+ for (ChipSel = 0; ChipSel < MAX_CS_PER_CHANNEL; ChipSel++) {
+ // Set Dram ODT based on current mode.
+ if ((NBPtr->DCTPtr->Timings.CsPresent & (UINT16) 1 << ChipSel) != 0) {
+ if (Wl) {
+ NBPtr->SetDramOdtRec (NBPtr, WRITE_LEVELING_MODE, ChipSel, (NBPtr->DimmToBeUsed << 1));
+ } else {
+ NBPtr->SetDramOdtRec (NBPtr, MISSION_MODE, ChipSel, (NBPtr->DimmToBeUsed << 1));
+ }
+
+ NBPtr->SetBitField (NBPtr, BFMrsChipSel, ChipSel);
+
+ // Set MR1 to F2x7C[MrsAddress], F2x7C[MrsBank]=1
+ MemRecTEMRS13 (TechPtr);
+ // Program Level
+ if (Wl) {
+ if ((ChipSel >> 1) == NBPtr->DimmToBeUsed) {
+ NBPtr->SetBitField (NBPtr, BFLevel, 1);
+ if (ChipSel & 1) {
+ NBPtr->SetBitField (NBPtr, BFMrsQoff, 1);
+ }
+ }
+ }
+ // Send command
+ NBPtr->SendMrsCmd (NBPtr);
+
+ // Set MR2 to F2x7C[MrsAddress], F2x7C[MrsBank]=1
+ MemRecTEMRS23 (TechPtr);
+ // Send command
+ NBPtr->SendMrsCmd (NBPtr);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function configures the DIMMS for Write Levelization
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+STATIC
+MemRecTProcConfig3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ CH_DEF_STRUCT *ChannelPtr;
+ UINT8 ByteLane;
+ UINT8 *Seed;
+ UINT8 DefaultSeed;
+ UINT8 CurrentSeed;
+ UINT8 Dimm;
+
+ NBPtr = TechPtr->NBPtr;
+ ChannelPtr = TechPtr->NBPtr->ChannelPtr;
+
+ Dimm = NBPtr->DimmToBeUsed;
+
+ // Program WrLvOdtEn=1
+ NBPtr->SetBitField (NBPtr, BFWrLvOdtEn, 1);
+
+ // Wait 10 MEMCLKs to allow for ODT signal settling.
+ MemRecUWait10ns (3, NBPtr->MemPtr);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t Byte: 00 01 02 03 04 05 06 07 ECC\n");
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeeds: ");
+ // Program an initialization Value to registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 to set
+ // the gross and fine delay for all the byte lane fields. If the target frequency is different than 400MHz,
+ // BIOS must execute two training passes for each Dimm. For pass 1 at a 400MHz MEMCLK frequency,
+ // use an initial total delay Value of 01Fh. This represents a 1UI (UI=.5MEMCLK) delay and is determined
+ // by design.
+
+ // Get default seed
+ if (ChannelPtr->RegDimmPresent != 0) {
+ DefaultSeed = 0x41;
+ } else if (ChannelPtr->SODimmPresent != 0) {
+ DefaultSeed = 0x12;
+ } else {
+ DefaultSeed = 0x1A;
+ }
+
+ // Get platform override seed
+ Seed = (UINT8 *) MemRecFindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_WL_SEED, NBPtr->MCTPtr->SocketId, ChannelPtr->ChannelID, Dimm);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "Seeds: ");
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ // This includes ECC as byte 8
+ CurrentSeed = ((Seed != NULL) ? Seed[ByteLane] : DefaultSeed);
+ NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), CurrentSeed);
+ ChannelPtr->WrDqsDlys[Dimm * MAX_BYTELANES + ByteLane] = CurrentSeed;
+ IDS_HDT_CONSOLE (MEM_FLOW, "%02x ", CurrentSeed);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n");
+
+ // Program F2x[1, 0]9C_x08[WrtLvTrMode]=0 for phy assisted training.
+
+ // Program F2x[1, 0]9C_x08[TrNibbleSel]=0
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n");
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function begins WL training for a specific DIMM
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+STATIC
+MemRecTBeginWLTrain3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ UINT8 ByteLane;
+ UINT8 Seed;
+ UINT8 Delay;
+ UINT8 Dimm;
+
+ NBPtr = TechPtr->NBPtr;
+
+ Dimm = NBPtr->DimmToBeUsed;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tWrtLvTrEn = 1\n");
+ // Program F2x[1, 0]9C_x08[WrtLlTrEn]=1.
+ NBPtr->SetBitField (NBPtr, BFWrtLvTrEn, 1);
+
+ // Wait 200 MEMCLKs. If executing pass 2, wait 32 MEMCLKs.
+ MemRecUWait10ns (50, NBPtr->MemPtr);
+
+ // Program F2x[1, 0]9C_x08[WrtLlTrEn]=0.
+ NBPtr->SetBitField (NBPtr, BFWrtLvTrEn, 0);
+
+ // Read from registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 to get the gross and fine Delay settings
+ // for the target Dimm and save these values.
+ IDS_HDT_CONSOLE (MEM_FLOW, " PRE WrDqs\n");
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ // This includes ECC as byte 8
+ Seed = NBPtr->ChannelPtr->WrDqsDlys[(Dimm * MAX_BYTELANES) + ByteLane];
+ Delay = (UINT8)NBPtr->GetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (Dimm, ByteLane));
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x ", Delay);
+ if (((Seed >> 5) == 0) && ((Delay >> 5) == 3)) {
+
+ // If seed has gross delay of 0 and PRE has gross delay of 3,
+ // then round the total delay of TxDqs to 0.
+ Delay = 0;
+ }
+
+ NBPtr->SetTrainDly (NBPtr, AccessWrDqsDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), Delay);
+ NBPtr->ChannelPtr->WrDqsDlys[(Dimm * MAX_BYTELANES) + ByteLane] = Delay;
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x\n", Delay);
+ }
+
+ IDS_HDT_CONSOLE_DEBUG_CODE (
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\tWrDqs: ");
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "%02x ", NBPtr->ChannelPtr->WrDqsDlys[ByteLane]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\n");
+ );
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrtthrc.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrtthrc.c
new file mode 100644
index 0000000000..84e7ab6f46
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrtthrc.c
@@ -0,0 +1,329 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrtthrc.c
+ *
+ * Phy assisted DQS receiver enable training
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 50454 $ @e \$Date: 2011-04-10 21:20:37 -0600 (Sun, 10 Apr 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "mru.h"
+#include "mt.h"
+#include "PlatformMemoryConfiguration.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_TECH_MRTTHRC_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_BYTELANES 8 /* Max Bytelanes per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecTPrepareRcvrEnDlySeed (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 ChipSel
+ );
+
+UINT16
+STATIC
+MemRecTProgramRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 ChipSel
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function executes Phy assisted receiver enable training for current node.
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ * @pre Auto refresh and ZQCL must be disabled
+ *
+ */
+VOID
+MemRecTTrainRcvrEnHw (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ UINT8 TempBuffer[64];
+ UINT8 Count;
+ UINT32 TestAddr;
+ UINT8 ChipSel;
+ UINT16 MaxRcvrDly;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+
+ AGESA_TESTPOINT (TpProcMemReceiverEnableTraining , &(NBPtr->MemPtr->StdHeader));
+ IDS_HDT_CONSOLE (MEM_STATUS, "\nStart HW RxEn training\n");
+
+ // Set environment settings before training
+ MemRecTBeginTraining (TechPtr);
+
+ ChipSel = NBPtr->DimmToBeUsed << 1;
+ TestAddr = 1 << 21;
+
+ IDS_HDT_CONSOLE (MEM_STATUS, "\tDct %d\n", TechPtr->NBPtr->Dct);
+ IDS_HDT_CONSOLE (MEM_STATUS, "\t\tCS %d\n", ChipSel);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tTestAddr %x\n", TestAddr);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t Byte: 00 01 02 03 04 05 06 07 ECC\n");
+
+ // 1.Prepare the DIMMs for training
+ NBPtr->SetBitField (NBPtr, BFTrDimmSel, ChipSel >> 1);
+
+ // 2.Prepare the phy for DQS receiver enable training.
+ MemRecTPrepareRcvrEnDlySeed (TechPtr, ChipSel);
+
+ // 3.BIOS initiates the phy assisted receiver enable training
+ NBPtr->SetBitField (NBPtr, BFDqsRcvTrEn, 1);
+
+ // 4.BIOS begins sending out of back-to-back reads to create
+ // a continuous stream of DQS edges on the DDR interface.
+ for (Count = 0; Count < 3; Count++) {
+ NBPtr->ReadPattern (NBPtr, TempBuffer, TestAddr, 64);
+ }
+
+ // 6.Wait 200 MEMCLKs.
+ MemRecUWait10ns (200, NBPtr->MemPtr);
+
+ // 7.Program [DqsRcvTrEn]=0 to stop the DQS receive enable training.
+ NBPtr->SetBitField (NBPtr, BFDqsRcvTrEn, 0);
+
+ // 8.Get the gross and fine delay values.
+ // 9.Calculate the corresponding final delay values
+ MaxRcvrDly = MemRecTProgramRcvrEnDly (TechPtr, ChipSel);
+
+ // Set Max Latency for both channels
+ NBPtr->SetMaxLatency (NBPtr, MaxRcvrDly);
+
+ // Restore environment settings after training
+ MemRecTEndTraining (TechPtr);
+ IDS_HDT_CONSOLE (MEM_FLOW, "End HW RxEn training\n\n");
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates RcvEn seed value for each rank
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] ChipSel - rank to be trained
+ *
+ */
+VOID
+STATIC
+MemRecTPrepareRcvrEnDlySeed (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 ChipSel
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ CH_DEF_STRUCT *ChannelPtr;
+ UINT16 SeedTotal;
+ UINT16 SeedFine;
+ UINT16 SeedGross;
+ UINT16 SeedPreGross;
+ UINT16 DiffSeedGrossSeedPreGross;
+ UINT8 ByteLane;
+ UINT16 PlatEst;
+ UINT16 *PlatEstSeed;
+ UINT16 SeedValue[8];
+ UINT16 SeedTtl[8];
+ UINT16 SeedPre[8];
+
+ NBPtr = TechPtr->NBPtr;
+ ChannelPtr = TechPtr->NBPtr->ChannelPtr;
+
+ // Get platform override seed
+ PlatEstSeed = (UINT16 *) MemRecFindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_RXEN_SEED, NBPtr->MCTPtr->SocketId, ChannelPtr->ChannelID, ChipSel >> 1);
+
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ // 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 >> 1) * MAX_BYTELANES) + ByteLane] + PlatEst;
+ SeedValue[ByteLane] = PlatEst;
+ 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)
+ DiffSeedGrossSeedPreGross = SeedGross - SeedPreGross;
+
+ ChannelPtr->RcvEnDlys[(ChipSel * MAX_BYTELANES) + ByteLane] = DiffSeedGrossSeedPreGross << 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 >> 1, ByteLane), (SeedPreGross << 5) | SeedFine);
+ SeedPre[ByteLane] = (SeedPreGross << 5) | SeedFine;
+
+ // 202688: Program seed value to RcvEnDly also.
+ NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), SeedGross << 5);
+ }
+ IDS_HDT_CONSOLE_DEBUG_CODE (
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tSeedValue: ");
+ for (ByteLane = 0; ByteLane < 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 < 8; ByteLane++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedTtl[ByteLane]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t SeedPRE: ");
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", SeedPre[ByteLane]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n");
+ );
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates final RcvrEnDly for each rank
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] ChipSel - Rank to be trained
+ *
+ * @return MaxDly - The largest delay value
+ *
+ */
+UINT16
+STATIC
+MemRecTProgramRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 ChipSel
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ CH_DEF_STRUCT *ChannelPtr;
+ UINT16 DiffSeedGrossSeedPreGross;
+ UINT8 ByteLane;
+ UINT16 RcvEnDly;
+ UINT16 MaxDly;
+ UINT16 RankRcvEnDly[8];
+ NBPtr = TechPtr->NBPtr;
+ ChannelPtr = TechPtr->NBPtr->ChannelPtr;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\t PRE: ");
+ MaxDly = 0;
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ DiffSeedGrossSeedPreGross = (ChannelPtr->RcvEnDlys[(ChipSel * MAX_BYTELANES) + ByteLane]) & 0x1E0;
+ RcvEnDly = (UINT8) NBPtr->GetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane));
+ IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", RcvEnDly);
+
+ RcvEnDly = RcvEnDly + DiffSeedGrossSeedPreGross;
+
+ // Add 1 UI to get to the midpoint of preamble
+ RcvEnDly += 0x20;
+ RankRcvEnDly[ByteLane] = RcvEnDly;
+
+ if (RcvEnDly > MaxDly) {
+ MaxDly = RcvEnDly;
+ }
+
+ NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS ((ChipSel >> 1), ByteLane), RcvEnDly);
+ }
+ IDS_HDT_CONSOLE_DEBUG_CODE (
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t RxEn: ");
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, "%03x ", RankRcvEnDly[ByteLane]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\n");
+ );
+ return MaxDly;
+}
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrtthrcSeedTrain.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrtthrcSeedTrain.c
new file mode 100644
index 0000000000..2e0f1a475d
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrtthrcSeedTrain.c
@@ -0,0 +1,315 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrtthrcSeedTrain.c
+ *
+ * Phy assisted DQS receiver enable training
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 03:16:51 -0600 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "mru.h"
+#include "mt.h"
+#include "PlatformMemoryConfiguration.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_TECH_MRTTHRCSEEDTRAIN_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_BYTELANES 8 /* Max Bytelanes per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecTPrepareRcvrEnDlySeed (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 ChipSel
+ );
+
+UINT16
+STATIC
+MemRecTProgramRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 ChipSel
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function executes Phy assisted receiver enable training without
+ * needing a correct seed.
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ * @pre Auto refresh and ZQCL must be disabled
+ *
+ */
+VOID
+MemRecTTrainRcvrEnHwSeedless (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ UINT8 TempBuffer[64];
+ UINT8 Count;
+ UINT32 TestAddrRJ16;
+ UINT8 ChipSel;
+ UINT16 MaxRcvrDly;
+ UINT8 PassMask;
+ UINT8 PrevTest;
+ UINT8 CurTest;
+ UINT8 ByteLane;
+ UINT32 OrgReg;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+
+ IDS_HDT_CONSOLE (MEM_STATUS, "\nStart HW RxEn training\n");
+ AGESA_TESTPOINT (TpProcMemReceiverEnableTraining , &(NBPtr->MemPtr->StdHeader));
+
+ // Disable auto refresh by configuring F2x[1, 0]8C[DisAutoRefresh] = 1.
+ NBPtr->SetBitField (NBPtr, BFDisAutoRefresh, 1);
+ // Disable ZQ calibration short command by configuring F2x[1, 0]94[ZqcsInterval] = 00b.
+ NBPtr->SetBitField (NBPtr, BFZqcsInterval, 0);
+
+ // Set environment settings before training
+ MemRecTBeginTraining (TechPtr);
+
+ ChipSel = NBPtr->DimmToBeUsed << 1;
+ TechPtr->ChipSel = ChipSel;
+ TestAddrRJ16 = 1 << 21;
+
+ // 1.Prepare the DIMMs for training
+ NBPtr->SetBitField (NBPtr, BFTrDimmSel, ChipSel >> 1);
+
+ // 2.Prepare the phy for DQS receiver enable training.
+ MemRecTPrepareRcvrEnDlySeed (TechPtr, ChipSel);
+
+ // 3.BIOS initiates the phy assisted receiver enable training
+ NBPtr->SetBitField (NBPtr, BFDqsRcvTrEn, 1);
+
+ // 4.BIOS begins sending out of back-to-back reads to create
+ // a continuous stream of DQS edges on the DDR interface.
+ for (Count = 0; Count < 3; Count++) {
+ NBPtr->ReadPattern (NBPtr, TempBuffer, TestAddrRJ16, 64);
+ }
+
+ // 6.Wait 200 MEMCLKs.
+ MemRecUWait10ns (200, NBPtr->MemPtr);
+
+ // 7.Program [DqsRcvTrEn]=0 to stop the DQS receive enable training.
+ NBPtr->SetBitField (NBPtr, BFDqsRcvTrEn, 0);
+
+ // 8.Get the gross and fine delay values.
+ // 9.Calculate the corresponding final delay values
+ MaxRcvrDly = MemRecTProgramRcvrEnDly (TechPtr, ChipSel);
+
+ //
+ // SEEDLESS TRAINING
+ // Sweep RxEn even gross delays to find the correct RxEn delays
+ //
+ OrgReg = MemRecNGetBitFieldNb (NBPtr, BFBlockRxDqsLock);
+ NBPtr->SetBitField (NBPtr, BFBlockRxDqsLock, OrgReg | 0x0100);
+ PassMask = 0;
+ PrevTest = 0;
+
+ // Use 3 CL pattern since recovery mode uses conservative settings and is not expected to work with long burst
+ NBPtr->WritePattern (NBPtr, TestAddrRJ16, TempBuffer, 3);
+
+ while (PassMask != 0xFF) {
+ NBPtr->SetMaxLatency (NBPtr, MaxRcvrDly);
+ NBPtr->ReadPattern (NBPtr, TempBuffer, TestAddrRJ16, 3);
+ CurTest = (UINT8) NBPtr->CompareTestPattern (NBPtr, TempBuffer, TempBuffer, 3);
+
+ // Mark pass when transition from P to F
+ PassMask |= (PrevTest & (~CurTest));
+
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x", TechPtr->RcvrEnDlyOpt[ByteLane]);
+ if ((CurTest & (1 << ByteLane)) == 0) {
+ IDS_HDT_CONSOLE (MEM_FLOW, " .\n");
+ } else {
+ IDS_HDT_CONSOLE (MEM_FLOW, " P\n");
+ }
+ if ((PassMask & (1 << ByteLane)) == 0) {
+ // For byte lanes that has not passed, increase by 2 UIs
+ TechPtr->RcvrEnDlyOpt[ByteLane] += 0x40;
+ NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS ((ChipSel >> 1), ByteLane), TechPtr->RcvrEnDlyOpt[ByteLane]);
+ if (TechPtr->RcvrEnDlyOpt[ByteLane] > MaxRcvrDly) {
+ MaxRcvrDly = TechPtr->RcvrEnDlyOpt[ByteLane];
+ }
+ } else {
+ // For byte lanes that has passed, decrease 5/2 UI to get back to the middle of preamble
+ NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS ((ChipSel >> 1), ByteLane), TechPtr->RcvrEnDlyOpt[ByteLane] - 0x50);
+ }
+ }
+ PrevTest = CurTest;
+ }
+ NBPtr->SetBitField (NBPtr, BFBlockRxDqsLock, OrgReg);
+
+ // Set final MaxRdLat
+ NBPtr->SetMaxLatency (NBPtr, MaxRcvrDly - 0x50);
+
+ // Restore environment settings after training
+ MemRecTEndTraining (TechPtr);
+ // 13.Program F2x[1, 0]8C[DisAutoRefresh] = 0.
+ NBPtr->SetBitField (NBPtr, BFDisAutoRefresh, 0);
+ // 14.Program F2x[1, 0]94[ZqcsInterval] to the proper interval for the current memory configuration.
+ NBPtr->SetBitField (NBPtr, BFZqcsInterval, 2);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "End HW RxEn training\n\n");
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates RcvEn seed value for each rank
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] ChipSel - rank to be trained
+ *
+ */
+VOID
+STATIC
+MemRecTPrepareRcvrEnDlySeed (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 ChipSel
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ UINT8 ByteLane;
+
+ NBPtr = TechPtr->NBPtr;
+
+ // Program a seed of 0x20 to make the result falls in (0,40) range
+ IDS_HDT_CONSOLE (MEM_FLOW, "Seeds: 20\n");
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ NBPtr->SetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane), 0x20);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function calculates final RcvrEnDly for each rank
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] ChipSel - Rank to be trained
+ *
+ * @return MaxDly - The largest delay value
+ *
+ */
+UINT16
+STATIC
+MemRecTProgramRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 ChipSel
+ )
+{
+ MEM_NB_BLOCK *NBPtr;
+ CH_DEF_STRUCT *ChannelPtr;
+ UINT8 ByteLane;
+ UINT16 RcvEnDly;
+ UINT16 MaxDly;
+
+ NBPtr = TechPtr->NBPtr;
+ ChannelPtr = TechPtr->NBPtr->ChannelPtr;
+ MaxDly = 0;
+ IDS_HDT_CONSOLE (MEM_FLOW, " PRE RxEn\n");
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ // Read PRE
+ RcvEnDly = (UINT8) NBPtr->GetTrainDly (NBPtr, AccessPhRecDly, DIMM_BYTE_ACCESS (ChipSel >> 1, ByteLane));
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x ", RcvEnDly);
+
+ // Add 1 UI to get to the midpoint of preamble
+ RcvEnDly += 0x20;
+
+ // And add 1/2 UI to start seedless training
+ RcvEnDly += 0x10;
+
+ // Record Max RxEn for MaxRdLat calculation
+ if (RcvEnDly > MaxDly) {
+ MaxDly = RcvEnDly;
+ }
+
+ // Write RxEn delays
+ NBPtr->SetTrainDly (NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS ((ChipSel >> 1), ByteLane), RcvEnDly);
+ TechPtr->RcvrEnDlyOpt[ByteLane] = RcvEnDly;
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x\n", RcvEnDly);
+ }
+
+ return MaxDly;
+}
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrttpos.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrttpos.c
new file mode 100644
index 0000000000..7f53991b49
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrttpos.c
@@ -0,0 +1,114 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mttpos.c
+ *
+ * Technology DQS R/W position training. Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_TECH_MRTTPOS_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function hard-codes DQS position delays for all bytes
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTTrainDQSPosSw (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ //Hard Code Settings
+ MemRecTSetWrDatRdDqs (TechPtr, 0x0F);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrttsrc.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrttsrc.c
new file mode 100644
index 0000000000..2594ecbec9
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/Tech/mrttsrc.c
@@ -0,0 +1,437 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrttsrc.c
+ *
+ * Technology Software based DQS receiver enable training Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 52180 $ @e \$Date: 2011-05-03 05:17:25 -0600 (Tue, 03 May 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mm.h"
+#include "mn.h"
+#include "mru.h"
+#include "mt.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_TECH_MRTTSRC_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_BYTELANES 8 /* Max Bytelanes per channel */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+VOID
+STATIC
+MemRecTSetRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 Receiver,
+ IN UINT16 RcvEnDly
+ );
+
+VOID
+STATIC
+MemRecTLoadRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 Receiver
+ );
+
+BOOLEAN
+STATIC
+MemRecTSaveRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 Receiver,
+ IN UINT16 RcvEnDly,
+ IN UINT8 CmpResult
+ );
+
+UINT8
+STATIC
+MemRecTCompare1ClPattern (
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function executes receiver enable training for BSP
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ *
+ */
+
+VOID
+MemRecTTrainRcvrEnSw (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ )
+{
+ _16BYTE_ALIGN UINT8 PatternBuffer[3 * 64];
+ UINT8 TestBuffer[120];
+ UINT8 *PatternBufPtr[2];
+ UINT32 TestAddr[4];
+ UINT8 TestResult;
+ UINT8 Receiver;
+ UINT8 i;
+ UINT8 j;
+ UINT16 RcvrEnDly;
+
+ MEM_DATA_STRUCT *MemPtr;
+ DIE_STRUCT *MCTPtr;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+ MemPtr = NBPtr->MemPtr;
+ MCTPtr = NBPtr->MCTPtr;
+
+ AGESA_TESTPOINT (TpProcMemReceiverEnableTraining, &(MemPtr->StdHeader));
+
+ // Set environment settings before training
+ MemRecTBeginTraining (TechPtr);
+
+ PatternBufPtr[0] = PatternBuffer;
+ MemRecUFillTrainPattern (TestPattern0, PatternBufPtr[0], 64, &(MemPtr->StdHeader));
+ PatternBufPtr[1] = PatternBufPtr[0] + 128;
+ MemRecUFillTrainPattern (TestPattern1, PatternBufPtr[1], 64, &(MemPtr->StdHeader));
+
+ // Begin receiver enable training
+ MemRecTSetWrDatRdDqs (TechPtr, 0);
+
+ // there are four receiver pairs, loosely associated with chipselects.
+ Receiver = NBPtr->DimmToBeUsed << 1;
+ TechPtr->DqsRcvEnSaved = 0;
+
+ TestAddr[0] = NBPtr->GetSysAddrRec ();
+ TestAddr[1] = TestAddr[0] + BIGPAGE_X8;
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\tDct %d\n", NBPtr->Dct);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tCS %d\n", Receiver);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tWrite to addresses: %04x0000\n", TestAddr[0]);
+
+ // Sweep receiver enable delays
+ AGESA_TESTPOINT (TpProcMemRcvrStartSweep, &(MemPtr->StdHeader));
+ for (RcvrEnDly = 0; RcvrEnDly < 0xFF; RcvrEnDly++) {
+
+ TestResult = 0xFF;
+ for (i = 0; i < 2; i++) {
+
+ // Set RcvrEn delay for all byte lanes
+ AGESA_TESTPOINT (TpProcMemRcvrSetDelay, &(MemPtr->StdHeader));
+ MemRecTSetRcvrEnDly (TechPtr, Receiver, RcvrEnDly);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tDly %3x", RcvrEnDly);
+
+ // Swap the test pointers such that even and odd steps alternate.
+ j = ((RcvrEnDly & 1) != 0) ? (i ^ 1) : i;
+
+ // Write, read and compare the first beat of data
+ AGESA_TESTPOINT (TpProcMemRcvrWritePattern, &(MemPtr->StdHeader));
+ MemRecUWrite1CL (TestAddr[j], PatternBufPtr[j]);
+ AGESA_TESTPOINT (TpProcMemRcvrReadPattern, &(MemPtr->StdHeader));
+ MemRecURead1CL (TestBuffer, TestAddr[j]);
+ AGESA_TESTPOINT (TpProcMemRcvrTestPattern, &(MemPtr->StdHeader));
+ TestResult &= MemRecTCompare1ClPattern (TestBuffer, PatternBufPtr[j], &(MemPtr->StdHeader));
+ MemRecUProcIOClFlush (TestAddr[j], MemPtr);
+ }
+
+ if (MemRecTSaveRcvrEnDly (TechPtr, Receiver, RcvrEnDly, TestResult)) {
+ // if all bytelanes pass
+ break;
+ }
+ } // End of delay sweep
+
+ if (RcvrEnDly == 0xFF) {
+ // no passing window
+ // LibAmdEventLog (AGESA_ERROR, MEM_ERROR_RCVR_EN_NO_PASSING_WINDOW, 0, NBPtr->Dct, NBPtr->Channel, 0); //@attention commented out since it is not defined in recovery code
+ SetMemRecError (AGESA_ERROR, MCTPtr);
+ }
+
+ // set final delays
+ MemRecTLoadRcvrEnDly (TechPtr, Receiver);
+
+ // Clear training bit when done
+ NBPtr->SetBitField (NBPtr, BFDqsRcvEnTrain, 0);
+
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\tMaxRcvrEnDly: %03x\n", RcvrEnDly + 0x20);
+
+ // Set Max Latency for both channels
+ NBPtr->SetMaxLatency (NBPtr, RcvrEnDly + 0x20);
+
+ // Restore environment settings after training
+ MemRecTEndTraining (TechPtr);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * If WrDatDly is 0, this function sets the DQS Positions in preparation
+ * for Receiver Enable Training. (Write Position is no delay, Read Position is 1.5 Memclock delay).
+ * Otherwise it will set WrDat and RdDqs to center of data eye.
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] WrDatDly - either 0 or 0x0F
+ *
+ */
+
+VOID
+MemRecTSetWrDatRdDqs (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 WrDatDly
+ )
+{
+ UINT8 ByteLane;
+ UINT8 Dimm;
+ UINT8 WrDqs;
+ UINT8 RdDqs;
+ MEM_NB_BLOCK *NBPtr;
+
+ NBPtr = TechPtr->NBPtr;
+
+ Dimm = NBPtr->DimmToBeUsed;
+ IDS_HDT_CONSOLE (MEM_FLOW, "\nWrDat RdDqs\n");
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ WrDqs = NBPtr->ChannelPtr->WrDqsDlys[(Dimm * MAX_BYTELANES) + ByteLane];
+ NBPtr->SetTrainDly (NBPtr, AccessWrDatDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), WrDqs + WrDatDly);
+ RdDqs = (WrDatDly == 0) ? 0x2F : 0x012;
+ NBPtr->SetTrainDly (NBPtr, AccessRdDqsDly, DIMM_BYTE_ACCESS (Dimm, ByteLane), RdDqs);
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x %02x\n\n", WrDqs + WrDatDly, RdDqs);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function programs DqsRcvEnDly to additional index for DQS receiver enabled training
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] Receiver - Current Chip select value
+ * @param[in] RcvEnDly - receiver enable delay to be saved
+ *
+ */
+
+VOID
+STATIC
+MemRecTSetRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 Receiver,
+ IN UINT16 RcvEnDly
+ )
+{
+ UINT8 ByteLane;
+
+ ASSERT (Receiver <= MAX_CS_PER_CHANNEL);
+ for (ByteLane = 0; ByteLane < 8; ByteLane++) {
+ TechPtr->NBPtr->SetTrainDly (TechPtr->NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (Receiver >> 1, ByteLane), RcvEnDly);
+ }
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function compares test pattern with data in buffer and return a pass/fail bitmap
+ * for 8 Bytes
+ *
+ * @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,out] StdHeader - The Pointer of AGESA Header.
+ *
+ * @return PASS - Bit map of results of comparison
+ */
+
+UINT8
+STATIC
+MemRecTCompare1ClPattern (
+ IN UINT8 Buffer[],
+ IN UINT8 Pattern[],
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 i;
+ UINT8 Pass;
+
+ Pass = 0xFF;
+ IDS_HDT_CONSOLE (MEM_FLOW, " -");
+ for (i = 0; i < 8; i++) {
+ if (Buffer[i] != Pattern[i]) {
+ // if bytelane n fails
+ Pass &= ~((UINT16) 1 << (i % 8)); // clear bit n
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, " %c", (Buffer[i] == Pattern[i]) ? 'P' : '.');
+ }
+
+ IDS_HDT_CONSOLE_DEBUG_CODE (
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t -");
+ for (i = 0; i < 8; i++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x", Buffer[i]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\t\t -");
+ for (i = 0; i < 8; i++) {
+ IDS_HDT_CONSOLE (MEM_FLOW, " %02x", Pattern[i]);
+ }
+ IDS_HDT_CONSOLE (MEM_FLOW, "\n\n");
+ );
+
+ return Pass;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function saves passing DqsRcvEnDly values to the stack
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] Receiver - Current Chip select value
+ * @param[in] RcvEnDly - receiver enable delay to be saved
+ * @param[in] CmpResult - compare result for Rank 0
+ *
+ * @return TRUE - All bytelanes pass
+ * @return FALSE - Some bytelanes fail
+ */
+
+BOOLEAN
+STATIC
+MemRecTSaveRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 Receiver,
+ IN UINT16 RcvEnDly,
+ IN UINT8 CmpResult
+ )
+{
+ UINT8 i;
+ UINT8 Passed;
+ UINT8 Saved;
+ UINT8 Mask;
+ UINT8 Dimm;
+
+ ASSERT (Receiver <= MAX_CS_PER_CHANNEL);
+
+ Passed = CmpResult;
+ Saved = (UINT8) (TechPtr->DqsRcvEnSaved & Passed); //@todo - false passes filter (subject to be replaced with a better solution)
+ Dimm = Receiver >> 1;
+ Mask = 1;
+ for (i = 0; i < 8; i++) {
+ if ((Passed & Mask) != 0) {
+ if ((Saved & Mask) == 0) {
+ TechPtr->NBPtr->ChannelPtr->RcvEnDlys[Dimm * MAX_BYTELANES + i] = (UINT8) (RcvEnDly + 0x20);
+ IDS_HDT_CONSOLE (MEM_FLOW, "\t\t\tBL %d = %02x", i, RcvEnDly + 0x20);
+ }
+ Saved |= Mask;
+ }
+ Mask <<= 1;
+ }
+ TechPtr->DqsRcvEnSaved = Saved;
+
+ if (Saved == 0xFF) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function loads the DqsRcvEnDly from saved data and program to additional index
+ * for DQS receiver enabled training
+ *
+ * @param[in,out] *TechPtr - Pointer to the MEM_TECH_BLOCK
+ * @param[in] Receiver - Current Chip select value
+ *
+ */
+
+VOID
+STATIC
+MemRecTLoadRcvrEnDly (
+ IN OUT MEM_TECH_BLOCK *TechPtr,
+ IN UINT8 Receiver
+ )
+{
+ UINT8 i;
+ UINT8 Dimm;
+ UINT16 Saved;
+ CH_DEF_STRUCT *ChannelPtr;
+
+ ASSERT (Receiver <= MAX_CS_PER_CHANNEL);
+ ChannelPtr = TechPtr->NBPtr->ChannelPtr;
+
+ Dimm = Receiver >> 1;
+ Saved = TechPtr->DqsRcvEnSaved;
+ for (i = 0; i < 8; i++) {
+ if ((Saved & 1) != 0) {
+ TechPtr->NBPtr->SetTrainDly (TechPtr->NBPtr, AccessRcvEnDly, DIMM_BYTE_ACCESS (Receiver >> 1, i),
+ ChannelPtr->RcvEnDlys[Dimm * MAX_BYTELANES + i]);
+ }
+ Saved >>= 1;
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrdef.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrdef.c
new file mode 100644
index 0000000000..7d270ec0f9
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrdef.c
@@ -0,0 +1,128 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mdef.c
+ *
+ * Memory Controller header file
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 52180 $ @e \$Date: 2011-05-03 05:17:25 -0600 (Tue, 03 May 2011) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+#include "AGESA.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_MRDEF_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This is the default return function
+ */
+
+VOID
+MemRecDefRet ( VOID )
+{
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function is the default return function that returns TRUE
+ *
+ */
+BOOLEAN
+MemRecDefTrue ( VOID )
+{
+ return TRUE;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function programs the DCT with initial values
+ *
+ *
+ * @param[in,out] *MCTPtr - Pointer to the DIE_STRUCT
+ * @param[in] Errorval - Error value
+ */
+
+VOID
+SetMemRecError (
+ IN AGESA_STATUS Errorval,
+ IN OUT DIE_STRUCT *MCTPtr
+ )
+{
+ if (MCTPtr->ErrCode < Errorval) {
+ MCTPtr->ErrCode = Errorval;
+ }
+}
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrinit.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrinit.c
new file mode 100644
index 0000000000..d3bb5de935
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrinit.c
@@ -0,0 +1,125 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrinit.c
+ *
+ * Initializer support functions for Recovery mode
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "Ids.h"
+#include "mm.h"
+#include "ma.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_MRINIT_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern PSO_TABLE DefaultPlatformMemoryConfiguration[];
+extern MEM_PLATFORM_CFG* memRecPlatformTypeInstalled[];
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function initializes the default parameter, function pointers, build options
+ * and SPD data for memory configuration
+ *
+ * @param[in,out] *MemPtr - Pointer to the MEM_DATA_STRUCT
+ *
+ */
+
+VOID
+AmdMemInitDataStructDefRecovery (
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ )
+{
+ MEM_PARAMETER_STRUCT *RefPtr;
+ UINT8 i;
+ UINT8 p;
+
+ RefPtr = MemPtr->ParameterListPtr;
+
+ // Memory Map/Mgt.
+ // Mask Bottom IO with 0xF8 to force hole size to have granularity of 128MB
+ RefPtr->BottomIo = 0xF0;
+
+ RefPtr->PlatformMemoryConfiguration = DefaultPlatformMemoryConfiguration;
+
+ i = 0;
+ for (p = 0; p < MAX_PLATFORM_TYPES; p++) {
+ if (memRecPlatformTypeInstalled[i] != NULL) {
+ MemPtr->GetPlatformCfg[p] = memRecPlatformTypeInstalled[i];
+ i++;
+ } else {
+ MemPtr->GetPlatformCfg[p] = MemRecNGetPsCfgDef;
+ }
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrm.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrm.c
new file mode 100644
index 0000000000..9b3ac9048a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrm.c
@@ -0,0 +1,288 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrm.c
+ *
+ * Main configuration for Recovery mode
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 48317 $ @e \$Date: 2011-03-07 10:38:14 -0700 (Mon, 07 Mar 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+#include "AGESA.h"
+#include "Ids.h"
+#include "amdlib.h"
+#include "GeneralServices.h"
+#include "heapManager.h"
+#include "cpuServices.h"
+#include "OptionMemoryRecovery.h"
+#include "mm.h"
+#include "mn.h"
+#include "mt.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_MRM_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define MAX_DIES_PER_SOCKET 2
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+extern MEM_REC_NB_CONSTRUCTOR* MemRecNBInstalled[];
+extern MEM_REC_TECH_CONSTRUCTOR* MemRecTechInstalled[];
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecSPDDataProcess (
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function is the Recovery memory configuration function for HY DDR3
+ *
+ * Requirements:
+ *
+ * Run-Time Requirements:
+ * 1. Complete Hypertransport Bus Configuration
+ * 2. AmdMemInitDataStructDef must be run to set default values
+ * 3. MSR bit to allow access to high PCI regs set on all nodes
+ * 4. BSP in Big Real Mode
+ * 5. Stack available
+ * 6. MCG_CTL=-1, MC4_EN=0 for all CPUs
+ * 7. MCi_STS from shutdown/warm reset recorded (if desired) prior to entry
+ * 8. All var MTRRs reset to zero
+ * 9. State of NB_CFG.DisDatMsk set properly on all CPUs
+ *
+ * @param[in,out] *MemPtr - Pointer to the MEM_DATA_STRUCT
+ *
+ * @return AGESA_STATUS
+ * - AGESA_ALERT
+ * - AGESA_FATAL
+ * - AGESA_SUCCESS
+ * - AGESA_WARNING
+ */
+
+AGESA_STATUS
+AmdMemRecovery (
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ )
+{
+ UINT8 Socket;
+ UINT8 Module;
+ UINT8 i;
+ AGESA_STATUS AgesaStatus;
+ PCI_ADDR Address;
+ MEM_NB_BLOCK NBBlock;
+ MEM_TECH_BLOCK TechBlock;
+ LOCATE_HEAP_PTR SocketWithMem;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+
+
+ //
+ // Read SPD data
+ //
+ MemRecSPDDataProcess (MemPtr);
+
+ //
+ // Get the socket id from heap.
+ //
+ SocketWithMem.BufferHandle = AMD_REC_MEM_SOCKET_HANDLE;
+ if (HeapLocateBuffer (&SocketWithMem, &MemPtr->StdHeader) == AGESA_SUCCESS) {
+ Socket = *(UINT8 *) SocketWithMem.BufferPtr;
+ } else {
+ ASSERT(FALSE); // Socket handle not found
+ return AGESA_FATAL;
+ }
+
+ //
+ // Allocate buffer for memory init structures
+ //
+ AllocHeapParams.RequestedBufferSize = MAX_DIES_PER_SOCKET * sizeof (DIE_STRUCT);
+ AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DIE_STRUCT_HANDLE, 0, 0, 0);
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) {
+ ASSERT(FALSE); // Heap allocation failed to allocate Die struct
+ return AGESA_FATAL;
+ }
+ MemPtr->DiesPerSystem = (DIE_STRUCT *)AllocHeapParams.BufferPtr;
+
+ //
+ // Discover populated CPUs
+ //
+ for (Module = 0; Module < MAX_DIES_PER_SOCKET; Module++) {
+ if (GetPciAddress ((VOID *)MemPtr, Socket, Module, &Address, &AgesaStatus)) {
+ MemPtr->DiesPerSystem[Module].SocketId = Socket;
+ MemPtr->DiesPerSystem[Module].DieId = Module;
+ MemPtr->DiesPerSystem[Module].PciAddr.AddressValue = Address.AddressValue;
+ }
+ }
+
+ i = 0;
+ while (MemRecNBInstalled[i] != NULL) {
+ if (MemRecNBInstalled[i] (&NBBlock, MemPtr, 0) == TRUE) {
+ break;
+ }
+ i++;
+ };
+ if (MemRecNBInstalled[i] == NULL) {
+ ASSERT(FALSE); // No NB installed
+ return AGESA_FATAL;
+ }
+ MemRecTechInstalled[0] (&TechBlock, &NBBlock);
+ NBBlock.TechPtr = &TechBlock;
+
+ return NBBlock.InitRecovery (&NBBlock);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function fills a default SPD buffer with SPD values for all DIMMs installed in the system
+ *
+ * @param[in,out] *MemPtr - Pointer to the MEM_DATA_STRUCT
+ *
+ */
+
+VOID
+STATIC
+MemRecSPDDataProcess (
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ )
+{
+ BOOLEAN FindSocketWithMem;
+ UINT8 Channel;
+ UINT8 Dimm;
+ UINT8 MaxSockets;
+ UINT8 *SocketWithMem;
+ UINT8 Socket;
+ AGESA_STATUS AgesaStatus;
+ SPD_DEF_STRUCT *DimmSPDPtr;
+ ALLOCATE_HEAP_PARAMS AllocHeapParams;
+ AGESA_READ_SPD_PARAMS SpdParam;
+ ASSERT (MemPtr != NULL);
+ FindSocketWithMem = FALSE;
+ //
+ // Allocate heap to save socket number with memory on it.
+ //
+ AllocHeapParams.RequestedBufferSize = sizeof (UINT8);
+ AllocHeapParams.BufferHandle = AMD_REC_MEM_SOCKET_HANDLE;
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) == AGESA_SUCCESS) {
+ SocketWithMem = (UINT8 *) AllocHeapParams.BufferPtr;
+ *SocketWithMem = 0;
+
+ //
+ // Allocate heap for the table
+ //
+ MaxSockets = (UINT8) GetPlatformNumberOfSockets ();
+
+ AllocHeapParams.RequestedBufferSize = (MaxSockets * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL * sizeof (SPD_DEF_STRUCT));
+ AllocHeapParams.BufferHandle = AMD_MEM_SPD_HANDLE;
+ AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
+ if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) == AGESA_SUCCESS) {
+ MemPtr->SpdDataStructure = (SPD_DEF_STRUCT *) AllocHeapParams.BufferPtr;
+ //
+ // Initialize SpdParam Structure
+ //
+ LibAmdMemCopy ((VOID *)&SpdParam, (VOID *)MemPtr, (UINTN)sizeof (SpdParam.StdHeader), &MemPtr->StdHeader);
+ //
+ // Populate SPDDataBuffer
+ //
+
+ SpdParam.MemData = MemPtr;
+ for (Socket = 0; Socket < MaxSockets; Socket ++) {
+ SpdParam.SocketId = Socket;
+ for (Channel = 0; Channel < MAX_CHANNELS_PER_SOCKET; Channel++) {
+ SpdParam.MemChannelId = Channel;
+ for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) {
+ SpdParam.DimmId = Dimm;
+ DimmSPDPtr = &(MemPtr->SpdDataStructure[(Socket * MAX_CHANNELS_PER_SOCKET + Channel) * MAX_DIMMS_PER_CHANNEL + Dimm]);
+ SpdParam.Buffer = DimmSPDPtr->Data;
+ AgesaStatus = AgesaReadSpdRecovery (0, &SpdParam);
+ if (AgesaStatus == AGESA_SUCCESS) {
+ DimmSPDPtr->DimmPresent = TRUE;
+ IDS_HDT_CONSOLE (MEM_FLOW, "SPD Socket %d Channel %d Dimm %d: %08x\n", Socket, Channel, Dimm, SpdParam.Buffer);
+ if (!FindSocketWithMem) {
+ FindSocketWithMem = TRUE;
+ }
+ } else {
+ DimmSPDPtr->DimmPresent = FALSE;
+ }
+ }
+ }
+ if (FindSocketWithMem) {
+ *SocketWithMem = Socket;
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrport.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrport.h
new file mode 100644
index 0000000000..7ecb85b06b
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrport.h
@@ -0,0 +1,86 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mport.h
+ *
+ * API's to support different OS
+ *
+ * A detailed description, giving important information about this file.
+ * Omit the detailed description if none is needed. For other than the
+ * simplest files, there should be one.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: Memory
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ */
+/*
+ *****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ *===========================================================================
+ * AMD Revision History
+ * Initial Version
+ *
+ */
+#ifndef _MPORT_H_
+#define _MPORT_H_
+
+///< 64 bit data structure
+///< lo - Lower 32 bits
+///< hi - Upper 32 bits
+typedef struct _S_UINT64 {
+ UINT32 lo; ///< Lower 32 bits
+ UINT32 hi; ///< Upper 32 bits
+} S_UINT64;
+/*
+ * SBDFO - Segment Bus Device Function Offset
+ * 31:28 Segment (4-bits)
+ * 27:20 Bus (8-bits)
+ * 19:15 Device (5-bits)
+ * 14:12 Function(3-bits)
+ * 11:00 Offset (12-bits)
+ */
+typedef UINT32 SBDFO;
+
+//#define MAKE_SBDFO(seg,bus,dev,fun,off) ((((UINT32)(seg))<<28) | (((UINT32)(bus))<<20) | \
+// (((UINT32)(dev))<<15) | (((UINT32)(fun))<<12) | ((UINT32)(off)))
+//#define SBDFO_SEG(x) (((UINT32)(x)>>28) & 0x0F)
+//#define SBDFO_BUS(x) (((UINT32)(x)>>20) & 0xFF)
+//#define SBDFO_DEV(x) (((UINT32)(x)>>15) & 0x1F)
+//#define SBDFO_FUN(x) (((UINT32)(x)>>12) & 0x07)
+//#define SBDFO_OFF(x) (((UINT32)(x)) & 0xFFF)
+//#define ILLEGAL_SBDFO 0xFFFFFFFF
+
+
+#define GET_SIZE_OF(x) (sizeof (x) / sizeof (x[0]))
+
+#endif /* _MPORT_H_ */
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrt3.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrt3.h
new file mode 100644
index 0000000000..d5fe3eac8a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mrt3.h
@@ -0,0 +1,120 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mrt3.h
+ *
+ * Common Technology Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MRT3_H_
+#define _MRT3_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+MemRecTTrainDQSWriteHw3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+VOID
+MemRecTDramInitSw3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+BOOLEAN
+MemRecTSetDramMode3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+BOOLEAN
+MemRecTDIMMPresence3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+VOID
+MemRecTEMRS13 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+VOID
+MemRecTEMRS23 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+VOID
+MemRecTEMRS33 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+VOID
+MemRecTMRS3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+VOID
+MemRecTDramControlRegInit3 (
+ IN OUT MEM_TECH_BLOCK *TechPtr
+ );
+
+#endif /* _MRT3_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mru.asm b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mru.asm
new file mode 100644
index 0000000000..5520d8eafa
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mru.asm
@@ -0,0 +1,187 @@
+;*****************************************************************************
+; AMD Generic Encapsulated Software Architecture
+;
+; $Workfile:: mu.asm $ $Revision:: 443#$ $Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+; Description: Main memory controller system configuration for AGESA DDR 2
+;
+;
+;*****************************************************************************
+;
+; Copyright (C) 2012 Advanced Micro Devices, Inc.
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are met:
+; * Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; * Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+; * Neither the name of Advanced Micro Devices, Inc. nor the names of
+; its contributors may be used to endorse or promote products derived
+; from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+; DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;*****************************************************************************
+;============================================================================
+
+
+ .XLIST
+ .LIST
+ .686p
+ .MODEL FLAT
+ .CODE
+ ASSUME FS: NOTHING
+
+
+; Define the calling convention used for the C library modules
+;@attention - This should be in a central include file
+CALLCONV EQU NEAR C
+
+
+;===============================================================================
+;MemRecUOutPort:
+;
+; Do a 32 Bit IO Out operation using edx.
+; NOTE: This function will be obsolete in the future.
+;
+; In: Port - port number
+; Value - value to be written to port
+;
+; Out:
+;
+;All registers preserved except for "Out:"
+;===============================================================================
+MemRecUOutPort PROC CALLCONV PUBLIC Port:DWORD, Value:DWORD
+ pushad
+ mov edx,Port
+ mov eax,Value
+ out dx,al
+ popad
+ ret
+MemRecUOutPort ENDP
+
+
+
+;----------------------------------------------------------------------------
+; _MFENCE();
+;
+_MFENCE macro
+ db 0Fh,0AEh,0F0h
+ endm
+
+;----------------------------------------------------------------------------
+; _EXECFENCE();
+;
+_EXECFENCE macro
+ out 0EDh,al ;prevent speculative execution of following instructions
+ endm
+
+;===============================================================================
+;MemRecUWrite1CL:
+;
+; Write data from buffer to a system address
+;
+; In: Address - System address to read from
+; Pattern - pointer pattern.
+;
+; Out:
+;
+;All registers preserved except for "Out:"
+;===============================================================================
+MemRecUWrite1CL PROC CALLCONV PUBLIC Address:DWORD, Pattern:NEAR PTR DWORD
+ pushad
+ push ds
+
+ mov eax,Address
+ push ss
+ pop ds
+ xor edx,edx
+ mov edx, DWORD PTR Pattern
+ mov esi,edx
+ mov edx,16
+ _EXECFENCE
+ mov ecx,4
+ @@:
+ db 66h,0Fh,6Fh,06 ;MOVDQA xmm0,[esi]
+ db 64h,66h,0Fh,0E7h,00 ;MOVNTDQ fs:[eax],xmm0 (xmm0 is 128 bits)
+ add eax,edx
+ add esi,edx
+ loop @B
+
+ pop ds
+ popad
+ ret
+MemRecUWrite1CL ENDP
+
+;===============================================================================
+;MemRecURead1CL:
+;
+; Read one cacheline to buffer
+;
+; In: Buffer - pointer buffer.
+; : Address - System address to read from
+;
+; Out:
+;
+;All registers preserved except for "Out:"
+;===============================================================================
+MemRecURead1CL PROC CALLCONV PUBLIC Buffer:NEAR PTR DWORD, Address:DWORD
+
+ pushad
+
+ mov esi,Address
+ xor edx,edx
+ mov edx,DWORD PTR Buffer
+ mov edi,edx
+ mov ecx,64
+ @@:
+ mov al,fs:[esi]
+ mov ss:[edi],al
+ inc esi
+ inc edi
+ loop @B
+
+ popad
+ ret
+MemRecURead1CL ENDP
+
+
+;===============================================================================
+;MemRecUFlushPattern:
+;
+; Flush one cache line
+;
+; In: Address - System address [31:0]
+; Out:
+;
+;All registers preserved except for "Out:"
+;===============================================================================
+MemRecUFlushPattern PROC CALLCONV PUBLIC Address:DWORD
+ pushad
+ mov eax,Address
+ _EXECFENCE
+ ;clflush fs:[eax]
+ db 064h ;access relative to FS BASE prefix
+ db 00Fh ;opcode
+ db 0AEh ;opcode
+ db 038h ;eax indirect addressing
+ _MFENCE
+ popad
+ ret
+MemRecUFlushPattern ENDP
+
+
+
+ END
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mru.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mru.h
new file mode 100644
index 0000000000..a2cd55338b
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mru.h
@@ -0,0 +1,140 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mru.h
+ *
+ * Utility support Recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 50454 $ @e \$Date: 2011-04-10 21:20:37 -0600 (Sun, 10 Apr 2011) $
+ *
+ **/
+/*****************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _MRU_H_
+#define _MRU_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+#ifndef PSO_ENTRY
+ #define PSO_ENTRY UINT8
+#endif
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/// Test patterns for DQS training
+typedef enum {
+ TestPattern0, ///< Test pattern used in first pass of receiver enable training
+ TestPattern1, ///< Test pattern used in first pass of receiver enable training
+ TestPattern2, ///< Test pattern used in second pass of receiver enable training
+ TestPatternJD1B, ///< 72-bit test pattern used in position training (ganged mode)
+ TestPatternJD1A, ///< 72-bit test pattern used in position training
+ TestPatternML ///< Test pattern used in first pass of max latency training
+} TRAIN_PATTERN;
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+VOID
+MemRecUWrite1CL (
+ IN UINT32 Address,
+ IN UINT8 Pattern[]
+ );
+
+VOID
+MemRecURead1CL (
+ IN UINT8 Buffer[],
+ IN UINT32 Address
+ );
+
+VOID
+MemRecUFlushPattern (
+ IN UINT32 Address
+ );
+
+VOID
+MemRecUFillTrainPattern (
+ IN TRAIN_PATTERN Pattern,
+ IN UINT8 Buffer[],
+ IN UINT16 Size,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+VOID
+MemRecUProcIOClFlush (
+ IN UINT32 Address,
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ );
+
+VOID
+MemRecUWait10ns (
+ IN UINT32 Count,
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ );
+
+VOID *
+MemRecFindPSOverrideEntry (
+ IN PSO_TABLE *PlatformMemoryConfiguration,
+ IN PSO_ENTRY EntryType,
+ IN UINT8 SocketID,
+ IN UINT8 ChannelID,
+ IN UINT8 DimmID
+ );
+
+UINT8
+RecGetMaxDimmsPerChannel (
+ IN PSO_TABLE *PlatformMemoryConfiguration,
+ IN UINT8 SocketID,
+ IN UINT8 ChannelID
+ );
+
+#endif /* _MRU_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mruc.c b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mruc.c
new file mode 100644
index 0000000000..e385b26225
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/Mem/mruc.c
@@ -0,0 +1,270 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * mruc.c
+ *
+ * Utility functions recovery
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: (Proc/Recovery/Mem)
+ * @e \$Revision: 52577 $ @e \$Date: 2011-05-09 12:58:33 -0600 (Mon, 09 May 2011) $
+ *
+ **/
+/*****************************************************************************
+*
+* Copyright (C) 2012 Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* ***************************************************************************
+*
+*/
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+#include "AGESA.h"
+#include "OptionMemory.h"
+#include "PlatformMemoryConfiguration.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "mrport.h"
+#include "mru.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_RECOVERY_MEM_MRUC_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+MemRecUResetTargetWTIO (
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ );
+
+VOID
+STATIC
+MemRecUSetTargetWTIO (
+ IN UINT32 Address,
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ );
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function returns the (Index)th UINT8
+ * from an indicated test Pattern.
+ *
+ * @param[in] Pattern - encoding of test Pattern type
+ * @param[in] Buffer[] - buffer to be filled
+ * @param[in] Size - Size of the bugger
+ * @param[in] *StdHeader - pointer to AMD_CONFIG_PARAMS
+ *
+ */
+
+VOID
+MemRecUFillTrainPattern (
+ IN TRAIN_PATTERN Pattern,
+ IN UINT8 Buffer[],
+ IN UINT16 Size,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ STATIC UINT8 PatternData[2] = {0x55, 0xAA};
+
+ LibAmdMemFill (Buffer, PatternData[Pattern == TestPattern0 ? TestPattern1 : TestPattern0], Size, StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function flushes cache lines
+ *
+ * @param[in] Address - System Address [39:8]
+ * @param[in,out] *MemPtr - Pointer to MEM_DATA_STRUCT
+ *
+ */
+
+VOID
+MemRecUProcIOClFlush (
+ IN UINT32 Address,
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ )
+{
+ MemRecUSetTargetWTIO (Address, MemPtr);
+ MemRecUFlushPattern (Address);
+ MemRecUResetTargetWTIO (MemPtr);
+}
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function resets the target address space to Write Through IO by disabling IORRs
+ */
+
+VOID
+STATIC
+MemRecUResetTargetWTIO (
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ )
+{
+ S_UINT64 Smsr;
+ Smsr.hi = 0;
+ Smsr.lo = 0;
+ LibAmdMsrWrite (IORR0_MASK, (UINT64 *)&Smsr, &MemPtr->StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * This function sets the target range to WT IO (using an IORR overlapping
+ * the already existing
+ * @param[in,out] *MemPtr - pointer to MEM_DATA_STRUCTURE
+ * @param[in] Address - System Address
+ *
+ */
+
+VOID
+STATIC
+MemRecUSetTargetWTIO (
+ IN UINT32 Address,
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ )
+{
+ S_UINT64 SMsr;
+
+ SMsr.lo = Address;
+ SMsr.hi = 0;
+ LibAmdMsrWrite (IORR0_BASE,(UINT64 *)&SMsr, &MemPtr->StdHeader); // ;IORR0 Base
+ SMsr.hi = 0xFFFF;
+ SMsr.lo = 0xFC000800;
+ LibAmdMsrWrite (IORR0_MASK, (UINT64 *)&SMsr, &MemPtr->StdHeader); // ;64MB Mask
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Waits specified number of 10ns cycles
+ * @param[in,out] MemPtr - pointer to MEM_DATA_STRUCTURE
+ * @param[in] Count - Number of 10ns cycles to wait
+ *
+ */
+
+VOID
+MemRecUWait10ns (
+ IN UINT32 Count,
+ IN OUT MEM_DATA_STRUCT *MemPtr
+ )
+{
+ S_UINT64 SMsr;
+
+ LibAmdMsrRead (TSC, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ Count += SMsr.lo;
+ while (SMsr.lo < Count) {
+ LibAmdMsrRead (TSC, (UINT64 *)&SMsr, &MemPtr->StdHeader);
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * Find the entry of platform specific overriding table.
+ *
+ * @param[in] PlatformMemoryConfiguration - Platform config table
+ * @param[in] EntryType - Entry type
+ * @param[in] SocketID - Physical socket ID
+ * @param[in] ChannelID - Physical channel ID
+ * @param[in] DimmID - Physical Dimm ID
+ *
+ * @return NULL - entry could not be found.
+ * @return Pointer - points to the entry's data.
+ *
+ * ----------------------------------------------------------------------------
+ */
+VOID *
+MemRecFindPSOverrideEntry (
+ IN PSO_TABLE *PlatformMemoryConfiguration,
+ IN PSO_ENTRY EntryType,
+ IN UINT8 SocketID,
+ IN UINT8 ChannelID,
+ IN UINT8 DimmID
+ )
+{
+ UINT8 *Buffer;
+
+ Buffer = PlatformMemoryConfiguration;
+ while (Buffer[0] != PSO_END) {
+ if (Buffer[0] == EntryType) {
+ if ((Buffer[2] & ((UINT8) 1 << SocketID)) != 0 ) {
+ if ((Buffer[3] & ((UINT8) 1 << ChannelID)) != 0 ) {
+ ASSERT ((Buffer[0] == PSO_MAX_DIMMS) ? (Buffer[5] <= MAX_DIMMS_PER_CHANNEL) : TRUE);
+ ASSERT ((Buffer[0] == PSO_MAX_CHIPSELS) ? (Buffer[5] <= MAX_CS_PER_CHANNEL) : TRUE);
+ ASSERT ((Buffer[0] == PSO_MAX_CHNLS) ? (Buffer[5] <= MAX_CHANNELS_PER_SOCKET) : TRUE);
+ if ((Buffer[4] & ((UINT8) 1 << DimmID)) != 0 ) {
+ return &Buffer[5];
+ }
+ }
+ }
+ }
+ Buffer += Buffer[1] + 2;
+ }
+ return NULL;
+}
+
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Recovery/recoveryPage.h b/src/vendorcode/amd/agesa/f15/Proc/Recovery/recoveryPage.h
new file mode 100644
index 0000000000..9e6ac66d23
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15/Proc/Recovery/recoveryPage.h
@@ -0,0 +1,58 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Create outline and references for Recovery Component mainpage documentation.
+ *
+ * Design guides, maintenance guides, and general documentation, are
+ * collected using this file onto the documentation mainpage.
+ * This file contains doxygen comment blocks, only.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: Documentation
+ * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/**
+ * @page recoverymain Recovery Component Documentation
+ *
+ * Additional documentation for the Recovery component consists of
+ *
+ * - Maintenance Guides:
+ * - add here >>>
+ * - Design Guides:
+ * - add here >>>
+ *
+ */