blob: b306933824f04167462a9a74ac3a1593d646d48f [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * mmMemRestore.c
6 *
7 * Main Memory Feature implementation file for Node Interleaving
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: (Mem/Main)
12 * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
13 *
14 **/
15/*****************************************************************************
16*
Siyuan Wang641f00c2013-06-08 11:50:55 +080017 * Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc.
18 * All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * * Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
28 * its contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
zbao7d94cf92012-07-02 14:19:14 +080041* ***************************************************************************
42*
43*/
44
45/*
46 *----------------------------------------------------------------------------
47 * MODULES USED
48 *
49 *----------------------------------------------------------------------------
50 */
51
52#include "AGESA.h"
53#include "amdlib.h"
54#include "OptionMemory.h"
55#include "mm.h"
56#include "mn.h"
57#include "Ids.h"
58#include "S3.h"
59#include "mfs3.h"
60#include "heapManager.h"
61#include "Filecode.h"
62CODE_GROUP (G1_PEICC)
63RDATA_GROUP (G1_PEICC)
64
65#define FILECODE PROC_MEM_MAIN_MMMEMRESTORE_FILECODE
66
67#define ST_PRE_ESR 0
68#define ST_POST_ESR 1
69#define ST_DONE 2
70
71/*----------------------------------------------------------------------------
72 * PROTOTYPES OF LOCAL FUNCTIONS
73 *
74 *----------------------------------------------------------------------------
75 */
76BOOLEAN
77STATIC
78MemMRestoreDqsTimings (
79 IN VOID *Storage,
80 IN MEM_MAIN_DATA_BLOCK *MemMainPtr
81 );
82
83BOOLEAN
84STATIC
85MemMSetCSRNb (
86 IN OUT MEM_NB_BLOCK *NBPtr,
Arthur Heymans8d3640d2022-05-16 12:27:36 +020087 CONST IN PCI_SPECIAL_CASE *SpecialCases,
zbao7d94cf92012-07-02 14:19:14 +080088 IN PCI_ADDR PciAddr,
89 IN UINT32 Value
90 );
91
92VOID
93STATIC
94MemMCreateS3NbBlock (
95 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr,
96 OUT S3_MEM_NB_BLOCK **S3NBPtr
97 );
98
99VOID
100MemMContextSave (
101 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
102 );
103
104BOOLEAN
105MemMContextRestore (
106 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
107 );
108BOOLEAN
109MemMS3Save (
110 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
111 );
112/*-----------------------------------------------------------------------------
113* EXPORTED FUNCTIONS
114*
115*-----------------------------------------------------------------------------
116*/
117extern MEM_NB_SUPPORT memNBInstalled[];
118
119/* -----------------------------------------------------------------------------*/
120/**
121 *
122 * Check and save memory context if possible.
123 *
124 * @param[in,out] *MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
125 *
126 */
127VOID
128MemMContextSave (
129 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
130 )
131{
132 UINT8 Node;
133 UINT8 i;
134 MEM_PARAMETER_STRUCT *RefPtr;
135 LOCATE_HEAP_PTR LocHeap;
136 ALLOCATE_HEAP_PARAMS AllocHeapParams;
137 DEVICE_BLOCK_HEADER *DeviceList;
138 AMD_CONFIG_PARAMS *StdHeader;
139 UINT32 BufferSize;
140 VOID *BufferOffset;
141 MEM_NB_BLOCK *NBArray;
142 S3_MEM_NB_BLOCK *S3NBPtr;
143 DESCRIPTOR_GROUP DeviceDescript[MAX_NODES_SUPPORTED];
144
145 NBArray = MemMainPtr->NBPtr;
146 RefPtr = NBArray[BSP_DIE].RefPtr;
147
148 if (RefPtr->SaveMemContextCtl) {
149 RefPtr->MemContext.NvStorage = NULL;
150 RefPtr->MemContext.NvStorageSize = 0;
151
152 // Make sure DQS training has occurred before saving memory context
153 if (!RefPtr->MemRestoreCtl) {
154 StdHeader = &MemMainPtr->MemPtr->StdHeader;
155
156 MemMCreateS3NbBlock (MemMainPtr, &S3NBPtr);
157 if (S3NBPtr != NULL) {
158 // Get the mask bit and the register list for node that presents
159 BufferSize = 0;
160 for (Node = 0; Node < MemMainPtr->DieCount; Node ++) {
161 S3NBPtr->MemS3GetConPCIMask (S3NBPtr[Node].NBPtr, (VOID *)&DeviceDescript[Node]);
162 S3NBPtr->MemS3GetConMSRMask (S3NBPtr[Node].NBPtr, (VOID *)&DeviceDescript[Node]);
163 BufferSize += S3NBPtr->MemS3GetRegLstPtr (S3NBPtr[Node].NBPtr, (VOID *)&DeviceDescript[Node]);
164 }
165
166 // Base on the size of the device list, apply for a buffer for it.
167 AllocHeapParams.RequestedBufferSize = (UINT32) (BufferSize + sizeof (DEVICE_BLOCK_HEADER));
168 AllocHeapParams.BufferHandle = AMD_MEM_S3_DATA_HANDLE;
169 AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
170 if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
171 DeviceList = (DEVICE_BLOCK_HEADER *) AllocHeapParams.BufferPtr;
172 DeviceList->RelativeOrMaskOffset = (UINT16) AllocHeapParams.RequestedBufferSize;
173
174 // Copy device list on the stack to the heap.
175 BufferOffset = sizeof (DEVICE_BLOCK_HEADER) + AllocHeapParams.BufferPtr;
176 for (Node = 0; Node < MemMainPtr->DieCount; Node ++) {
177 for (i = PRESELFREF; i <= POSTSELFREF; i ++) {
178 // Copy PCI device descriptor to the heap if it exists.
179 if (DeviceDescript[Node].PCIDevice[i].RegisterListID != 0xFFFFFFFF) {
180 LibAmdMemCopy (BufferOffset, &(DeviceDescript[Node].PCIDevice[i]), sizeof (PCI_DEVICE_DESCRIPTOR), StdHeader);
181 DeviceList->NumDevices ++;
182 BufferOffset = sizeof (PCI_DEVICE_DESCRIPTOR) + (UINT8 *)BufferOffset;
183 }
184 // Copy conditional PCI device descriptor to the heap if it exists.
185 if (DeviceDescript[Node].CPCIDevice[i].RegisterListID != 0xFFFFFFFF) {
186 LibAmdMemCopy (BufferOffset, &(DeviceDescript[Node].CPCIDevice[i]), sizeof (CONDITIONAL_PCI_DEVICE_DESCRIPTOR), StdHeader);
187 DeviceList->NumDevices ++;
188 BufferOffset = sizeof (CONDITIONAL_PCI_DEVICE_DESCRIPTOR) + (UINT8 *)BufferOffset;
189 }
190 // Copy MSR device descriptor to the heap if it exists.
191 if (DeviceDescript[Node].MSRDevice[i].RegisterListID != 0xFFFFFFFF) {
192 LibAmdMemCopy (BufferOffset, &(DeviceDescript[Node].MSRDevice[i]), sizeof (MSR_DEVICE_DESCRIPTOR), StdHeader);
193 DeviceList->NumDevices ++;
194 BufferOffset = sizeof (MSR_DEVICE_DESCRIPTOR) + (UINT8 *)BufferOffset;
195 }
196 // Copy conditional MSR device descriptor to the heap if it exists.
197 if (DeviceDescript[Node].CMSRDevice[i].RegisterListID != 0xFFFFFFFF) {
198 LibAmdMemCopy (BufferOffset, &(DeviceDescript[Node].PCIDevice[i]), sizeof (CONDITIONAL_MSR_DEVICE_DESCRIPTOR), StdHeader);
199 DeviceList->NumDevices ++;
200 BufferOffset = sizeof (CONDITIONAL_MSR_DEVICE_DESCRIPTOR) + (UINT8 *)BufferOffset;
201 }
202 }
203 }
204
205 // Determine size needed
206 BufferSize = GetWorstCaseContextSize (DeviceList, INIT_RESUME, StdHeader);
207 AllocHeapParams.RequestedBufferSize = BufferSize;
208 AllocHeapParams.BufferHandle = AMD_S3_SAVE_HANDLE;
209 AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
210 if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
211 // Save memory context
212 SaveDeviceListContext (DeviceList, AllocHeapParams.BufferPtr, INIT_RESUME, &BufferSize, StdHeader);
213 RefPtr->MemContext.NvStorageSize = BufferSize;
214 }
215
216 HeapDeallocateBuffer (AMD_MEM_S3_DATA_HANDLE, StdHeader);
217 }
218 }
219 HeapDeallocateBuffer (AMD_MEM_S3_NB_HANDLE, StdHeader);
220
221 // Locate MemContext since it might have been shifted after deallocating
222 LocHeap.BufferHandle = AMD_S3_SAVE_HANDLE;
223 if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) {
224 RefPtr->MemContext.NvStorage = LocHeap.BufferPtr;
225 }
226 }
227 }
228
229 for (Node = 0; Node < MemMainPtr->DieCount; Node++) {
230 NBArray[Node].FamilySpecificHook[AfterSaveRestore] (&NBArray[Node], &NBArray[Node]);
231 }
232}
233
234/* -----------------------------------------------------------------------------*/
235/**
236 *
237 * Check and restore memory context if possible.
238 *
239 * @param[in,out] *MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
240 *
241 * @return TRUE - DQS timing restore succeeds.
242 * @return FALSE - DQS timing restore fails.
243 */
244BOOLEAN
245MemMContextRestore (
246 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
247 )
248{
249 UINT8 Node;
250 MEM_NB_BLOCK *NBArray;
251 MEM_PARAMETER_STRUCT *RefPtr;
252 S3_MEM_NB_BLOCK *S3NBPtr;
253
254 NBArray = MemMainPtr->NBPtr;
255 RefPtr = NBArray[BSP_DIE].RefPtr;
256
257 IDS_HDT_CONSOLE (MEM_STATUS, "\nStart Mem Restore\n");
258 if (RefPtr->MemRestoreCtl) {
259 if (RefPtr->MemContext.NvStorage != NULL) {
260 MemMCreateS3NbBlock (MemMainPtr, &S3NBPtr);
261 if (S3NBPtr != NULL) {
262 // Check DIMM config and restore DQS timings if possible
263 if (!MemMRestoreDqsTimings (RefPtr->MemContext.NvStorage, MemMainPtr)) {
264 RefPtr->MemRestoreCtl = FALSE;
265 }
266 } else {
267 RefPtr->MemRestoreCtl = FALSE;
268 }
269 HeapDeallocateBuffer (AMD_MEM_S3_NB_HANDLE, &(MemMainPtr->MemPtr->StdHeader));
270 } else {
271 IEM_SKIP_CODE (IEM_MEM_RESTORE) {
272 RefPtr->MemRestoreCtl = FALSE;
273 }
274 }
275 }
276
277 for (Node = 0; Node < MemMainPtr->DieCount; Node++) {
278 NBArray[Node].FamilySpecificHook[AfterSaveRestore] (&NBArray[Node], &NBArray[Node]);
279 }
280 IDS_HDT_CONSOLE (MEM_FLOW, RefPtr->MemRestoreCtl ? "Mem Restore Succeeds!\n" : "Mem Restore Fails!\n");
281 return RefPtr->MemRestoreCtl;
282}
283
284/* -----------------------------------------------------------------------------*/
285/**
286 *
287 * Save all memory related data for S3.
288 *
289 * @param[in,out] *MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
290 *
291 * @return TRUE - No fatal error occurs.
292 * @return FALSE - Fatal error occurs.
293 */
294BOOLEAN
295MemMS3Save (
296 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr
297 )
298{
299 ALLOCATE_HEAP_PARAMS AllocHeapParams;
300 MEM_PARAMETER_STRUCT *RefPtr;
301 BOOLEAN SaveMemContextCtl;
302 BOOLEAN MemRestoreCtl;
303
304 RefPtr = MemMainPtr->NBPtr[BSP_DIE].RefPtr;
305
306 // If memory context has not been saved
307 if (RefPtr->MemContext.NvStorage == NULL) {
308 // Change memory context save and restore control to allow memory context to happen
309 SaveMemContextCtl = RefPtr->SaveMemContextCtl;
310 MemRestoreCtl = RefPtr->MemRestoreCtl;
311 RefPtr->SaveMemContextCtl = TRUE;
312 RefPtr->MemRestoreCtl = FALSE;
313
314 MemMContextSave (MemMainPtr);
315
316 // Restore the original control
317 RefPtr->SaveMemContextCtl = SaveMemContextCtl;
318 RefPtr->MemRestoreCtl = MemRestoreCtl;
319
320 if (RefPtr->MemContext.NvStorage == NULL) {
321 // Memory context cannot be saved succesfully
zbao7d94cf92012-07-02 14:19:14 +0800322 return FALSE;
323 }
324 }
325
326 // Allocate heap for memory S3 data to pass to main AMDS3Save
327 // Apply for 4 bytes more than the size of the data buffer to store the size of data buffer
328 IDS_HDT_CONSOLE (MEM_FLOW, "\nSave memory S3 data in heap\n");
329 AllocHeapParams.RequestedBufferSize = RefPtr->MemContext.NvStorageSize + 4;
330 AllocHeapParams.BufferHandle = AMD_MEM_S3_SAVE_HANDLE;
331 AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
332
333 if (HeapAllocateBuffer (&AllocHeapParams, &(MemMainPtr->MemPtr->StdHeader)) == AGESA_SUCCESS) {
334 LibAmdMemCopy (AllocHeapParams.BufferPtr + 4, RefPtr->MemContext.NvStorage, RefPtr->MemContext.NvStorageSize, &(MemMainPtr->MemPtr->StdHeader));
335 *(UINT32 *) AllocHeapParams.BufferPtr = RefPtr->MemContext.NvStorageSize;
336 return TRUE;
337 } else {
338 ASSERT (FALSE);
339 return FALSE;
340 }
341}
342
343/*----------------------------------------------------------------------------
344 * LOCAL FUNCTIONS
345 *
346 *----------------------------------------------------------------------------
347 */
348
349/*---------------------------------------------------------------------------------------*/
350/**
351 * Restores all devices that contains DQS timings
352 *
353 * @param[in] Storage Beginning of the device list.
354 * @param[in,out] MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
355 *
356 * @return TRUE - No fatal error occurs.
357 * @return FALSE - Fatal error occurs.
358 *
359 */
360BOOLEAN
361STATIC
362MemMRestoreDqsTimings (
363 IN VOID *Storage,
364 IN MEM_MAIN_DATA_BLOCK *MemMainPtr
365 )
366{
367 AMD_CONFIG_PARAMS *StdHeader;
368 UINT8 *OrMask;
369 DEVICE_DESCRIPTORS Device;
370 INT16 i;
371 INT16 j;
372 DEVICE_BLOCK_HEADER *DeviceList;
373 PCI_REGISTER_BLOCK_HEADER *Reg;
374 CPCI_REGISTER_BLOCK_HEADER *CReg;
375 MSR_REGISTER_BLOCK_HEADER *MsrReg;
376 CMSR_REGISTER_BLOCK_HEADER *CMsrReg;
377 PCI_ADDR PciAddress;
378 MEM_NB_BLOCK *NBArray;
379 UINT8 State;
380 UINT8 Node;
381 UINT8 Dct;
382 UINT8 MaxNode;
383
384 NBArray = MemMainPtr->NBPtr;
385 StdHeader = &(MemMainPtr->MemPtr->StdHeader);
386 DeviceList = (DEVICE_BLOCK_HEADER *) Storage;
387 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
388 OrMask = (UINT8 *) DeviceList + DeviceList->RelativeOrMaskOffset;
389
390 if (DeviceList->NumDevices == 0) {
391 return FALSE;
392 }
393
394 MaxNode = 0;
395 State = ST_PRE_ESR;
396 for (i = 0; State != ST_DONE; i++) {
397 if (((State == ST_PRE_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_PCI_PRE_ESR)) ||
398 ((State == ST_POST_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_PCI))) {
399 MemFS3GetPciDeviceRegisterList (Device.PciDevice, &Reg, StdHeader);
400 Node = Device.PciDevice->Node;
401 IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", Node);
402 PciAddress = NBArray[Node].PciAddr;
403 for (j = 0; j < Reg->NumRegisters; j++) {
404 PciAddress.Address.Function = Reg->RegisterList[j].Function;
405 PciAddress.Address.Register = Reg->RegisterList[j].Offset;
406 PciAddress.Address.Segment = (Reg->RegisterList[j].Type.SpecialCaseFlag != 0) ?
407 0xF - Reg->RegisterList[j].Type.SpecialCaseIndex : 0;
408 if (!MemMSetCSRNb (&NBArray[Node], Reg->SpecialCases, PciAddress, *((UINT32 *) OrMask) & Reg->RegisterList[j].AndMask)) {
409 return FALSE; // Restore fails
410 }
Kyösti Mälkkif7109552017-07-24 03:35:11 +0300411 if (Reg->RegisterList[j].Type.RegisterSize != 3)
412 OrMask += (Reg->RegisterList[j].Type.RegisterSize == 0) ? 4 :
413 Reg->RegisterList[j].Type.RegisterSize;
zbao7d94cf92012-07-02 14:19:14 +0800414 }
415
416 if (MaxNode < Node) {
417 MaxNode = Node;
418 }
419
420 } else if (((State == ST_PRE_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_CPCI_PRE_ESR)) ||
421 ((State == ST_POST_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_CPCI))) {
422 MemFS3GetCPciDeviceRegisterList (Device.CPciDevice, &CReg, StdHeader);
423 Node = Device.CPciDevice->Node;
424 IDS_HDT_CONSOLE (MEM_STATUS, "Node %d\n", Node);
425 PciAddress = NBArray[Node].PciAddr;
426 for (j = 0; j < CReg->NumRegisters; j++) {
427 if (((Device.CPciDevice->Mask1 & CReg->RegisterList[j].Mask1) != 0) &&
428 ((Device.CPciDevice->Mask2 & CReg->RegisterList[j].Mask2) != 0)) {
429 PciAddress.Address.Function = CReg->RegisterList[j].Function;
430 PciAddress.Address.Register = CReg->RegisterList[j].Offset;
431 PciAddress.Address.Segment = (CReg->RegisterList[j].Type.SpecialCaseFlag != 0) ?
432 0xF - CReg->RegisterList[j].Type.SpecialCaseIndex : 0;
433 if (!MemMSetCSRNb (&NBArray[Node], CReg->SpecialCases, PciAddress, *((UINT32 *) OrMask) & CReg->RegisterList[j].AndMask)) {
434 return FALSE; // Restore fails
435 }
Kyösti Mälkkif7109552017-07-24 03:35:11 +0300436 if (CReg->RegisterList[j].Type.RegisterSize != 3)
437 OrMask += (CReg->RegisterList[j].Type.RegisterSize == 0) ? 4 :
438 CReg->RegisterList[j].Type.RegisterSize;
zbao7d94cf92012-07-02 14:19:14 +0800439 }
440 }
441 } else if (((State == ST_PRE_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_MSR_PRE_ESR)) ||
442 ((State == ST_POST_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_MSR))) {
443 MemFS3GetMsrDeviceRegisterList (Device.MsrDevice, &MsrReg, StdHeader);
444 for (j = 0; j < MsrReg->NumRegisters; j++) {
445 OrMask += 8;
446 }
447 } else if (((State == ST_PRE_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_CMSR_PRE_ESR)) ||
448 ((State == ST_POST_ESR) && (Device.CommonDeviceHeader->Type == DEV_TYPE_CMSR))) {
449 MemFS3GetCMsrDeviceRegisterList (Device.CMsrDevice, &CMsrReg, StdHeader);
450 for (j = 0; j < CMsrReg->NumRegisters; j++) {
451 if (((Device.CMsrDevice->Mask1 & CMsrReg->RegisterList[j].Mask1) != 0) &&
452 ((Device.CMsrDevice->Mask2 & CMsrReg->RegisterList[j].Mask2) != 0)) {
453 OrMask += 8;
454 }
455 }
456 }
457
458 switch (Device.CommonDeviceHeader->Type) {
459 case DEV_TYPE_PCI_PRE_ESR:
460 // Fall through to advance the pointer after restoring context
461 case DEV_TYPE_PCI:
462 Device.PciDevice++;
463 break;
464 case DEV_TYPE_CPCI_PRE_ESR:
465 // Fall through to advance the pointer after restoring context
466 case DEV_TYPE_CPCI:
467 Device.CPciDevice++;
468 break;
469 case DEV_TYPE_MSR_PRE_ESR:
470 // Fall through to advance the pointer after restoring context
471 case DEV_TYPE_MSR:
472 Device.MsrDevice++;
473 break;
474 case DEV_TYPE_CMSR_PRE_ESR:
475 // Fall through to advance the pointer after restoring context
476 case DEV_TYPE_CMSR:
477 Device.CMsrDevice++;
478 break;
479 default:
480 ASSERT (FALSE);
481 break;
482 }
483
484 if (i == (DeviceList->NumDevices - 1)) {
485 // Go to next state
486 State++;
487 i = -1;
488 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
489
490 // Check to see if processor or DIMM population has changed
491 if ((MaxNode + 1) != MemMainPtr->DieCount) {
492 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: Population changed\n");
493 return FALSE;
494 }
495
496 // Perform MemClk frequency change
497 for (Node = 0; Node < MemMainPtr->DieCount; Node ++) {
498 if (NBArray[Node].MCTPtr->NodeMemSize != 0) {
499 NBArray[Node].BeforeDqsTraining (&NBArray[Node]);
500 if (NBArray[Node].DCTPtr->Timings.Speed < NBArray[Node].DCTPtr->Timings.TargetSpeed) {
501 for (Dct = 0; Dct < NBArray[Node].DctCount; Dct++) {
502 NBArray[Node].SwitchDCT (&NBArray[Node], Dct);
503 NBArray[Node].DCTPtr->Timings.Speed = NBArray[Node].DCTPtr->Timings.TargetSpeed;
504 }
505 IDS_OPTION_HOOK (IDS_BEFORE_MEM_FREQ_CHG, &NBArray[Node], &(MemMainPtr->MemPtr->StdHeader));
506 NBArray[Node].ChangeFrequency (&NBArray[Node]);
507 }
508 }
509 }
510 }
511 }
512
513 return TRUE;
514}
515
516/* -----------------------------------------------------------------------------*/
517/**
518 *
519 * This function filters out other settings and only restores DQS timings.
520 *
521 * @param[in,out] NBPtr - Pointer to the MEM_NB_BLOCK
522 * @param[in] SpecialCases - Pointer to special cases array handlers
523 * @param[in] PciAddr - address of the CSR register in PCI_ADDR format.
524 * @param[in] Value - Value to be programmed
525 *
526 * @return TRUE - No fatal error occurs.
527 * @return FALSE - Fatal error occurs.
528 *
529 */
530
531BOOLEAN
532STATIC
533MemMSetCSRNb (
534 IN OUT MEM_NB_BLOCK *NBPtr,
Arthur Heymans8d3640d2022-05-16 12:27:36 +0200535 CONST IN PCI_SPECIAL_CASE *SpecialCases,
zbao7d94cf92012-07-02 14:19:14 +0800536 IN PCI_ADDR PciAddr,
537 IN UINT32 Value
538 )
539{
540 UINT32 Offset;
541 UINT8 Dct;
542 UINT32 Temp;
543 BOOLEAN RetVal;
544 UINT32 BOffset;
545
546 RetVal = TRUE;
547 if (PciAddr.Address.Segment != 0) {
548 if (PciAddr.Address.Segment == 0xF) {
549 PciAddr.Address.Segment = 0;
550 Dct = (UINT8) ((PciAddr.Address.Register >> 10) & 1);
551 Offset = PciAddr.Address.Register & 0x3FF;
552 BOffset = PciAddr.Address.Register & 0xFF;
553 if ((PciAddr.Address.Register & 0x800) == 0) {
554 if (((BOffset >= 1) && (BOffset <= 3)) ||
555 ((BOffset >= 5) && (BOffset <= 7)) ||
556 ((Offset >= 0x10) && (Offset <= 0x2B)) ||
557 ((Offset >= 0x30) && (Offset <= 0x4A))) {
558 IDS_HDT_CONSOLE (MEM_FLOW, "\t\tF2_%d9C_%03x = %08x\n", Dct, Offset, Value);
559 //MemNS3SetCSR
560 SpecialCases[0].Restore (AccessS3SaveWidth32, PciAddr, &Value, &NBPtr->MemPtr->StdHeader);
561 }
562 }
563 }
564 } else {
565 Dct = (UINT8) ((PciAddr.Address.Register >> 8) & 1);
566 Offset = PciAddr.Address.Register & 0xFF;
567
568 if (PciAddr.Address.Function == 2) {
569 if ((Offset >= 0x40) && (Offset < 0x60) && ((Value & 4) != 0)) {
570 // If TestFail bit is set, set CsTestFail
571 NBPtr->SwitchDCT (NBPtr, Dct);
572 NBPtr->DCTPtr->Timings.CsTrainFail |= (UINT16)1 << ((Offset - 0x40) >> 2);
573 IDS_HDT_CONSOLE (MEM_FLOW, "\tBad CS:%d\n", ((Offset - 0x40) >> 2));
574 } else if (Offset == 0x80) {
575 LibAmdPciRead (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
576 if (Temp != Value) {
577 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: DIMM config changed\n");
578 RetVal = FALSE;
579 }
580 } else if (Offset == 0x90) {
581 LibAmdPciRead (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
582 if ((Temp & 0x0001F000) != (Value & 0x0001F000)) {
583 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: DIMM config changed\n");
584 RetVal = FALSE;
585 }
586 } else if (Offset == 0x94) {
587 LibAmdPciRead (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
588 if ((Temp & 0x00061000) != (Value & 0x00061000)) {
589 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: DIMM config changed\n");
590 RetVal = FALSE;
591 }
592 if (((Value & 0x4000) == 0) && (NBPtr->GetMemClkFreqId (NBPtr, NBPtr->DCTPtr->Timings.TargetSpeed) != ((Value & 7) + 1))) {
593 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: MemClk has changed\n");
594 RetVal = FALSE;
595 }
596 // Restore ZqcsInterval
597 Temp &= 0xFFFFF3FF;
598 Temp |= (Value & 0x00000C00);
599 LibAmdPciWrite (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
600 } else if (Offset == 0x78) {
601 // Program MaxRdLat
602 LibAmdPciRead (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
603 Temp &= 0x0009BF0F;
604 Temp |= (Value & 0xFFC00000);
605 LibAmdPciWrite (AccessWidth32, PciAddr, &Temp, &NBPtr->MemPtr->StdHeader);
606 } else if (PciAddr.Address.Register == 0x110) {
607 if ((NBPtr->MCTPtr->NodeMemSize != 0) && (Value == 0x00000100)) {
608 IDS_HDT_CONSOLE (MEM_FLOW, "\tSTOP: DIMM config changed\n");
609 RetVal = FALSE;
610 }
611 }
612 }
613 }
614
615 if (RetVal == FALSE) {
616 NBPtr->SwitchDCT (NBPtr, 0);
617 NBPtr->DCTPtr->Timings.CsTrainFail = 0;
618 NBPtr->SwitchDCT (NBPtr, 1);
619 NBPtr->DCTPtr->Timings.CsTrainFail = 0;
620 }
621
622 return RetVal;
623}
624
625/* -----------------------------------------------------------------------------*/
626/**
627 *
628 * Create S3 NB Block.
629 *
630 * @param[in,out] MemMainPtr - Pointer to the MEM_MAIN_DATA_BLOCK
631 * @param[out] S3NBPtr - Pointer to the S3 NB Block pointer
632 *
633 */
634VOID
635STATIC
636MemMCreateS3NbBlock (
637 IN OUT MEM_MAIN_DATA_BLOCK *MemMainPtr,
638 OUT S3_MEM_NB_BLOCK **S3NBPtr
639 )
640{
641 UINT8 Node;
642 UINT8 i;
643 MEM_NB_BLOCK *NBArray;
644 MEM_NB_BLOCK *DummyNBs;
645 ALLOCATE_HEAP_PARAMS AllocHeapParams;
646
647 NBArray = MemMainPtr->NBPtr;
648
649 *S3NBPtr = NULL;
650
651 // Allocate heap for S3 NB Blocks
652 AllocHeapParams.RequestedBufferSize = (MemMainPtr->DieCount * (sizeof (S3_MEM_NB_BLOCK) + sizeof (MEM_NB_BLOCK)));
653 AllocHeapParams.BufferHandle = AMD_MEM_S3_NB_HANDLE;
654 AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
655 if (HeapAllocateBuffer (&AllocHeapParams, &(MemMainPtr->MemPtr->StdHeader)) == AGESA_SUCCESS) {
656 *S3NBPtr = (S3_MEM_NB_BLOCK *) AllocHeapParams.BufferPtr;
657 DummyNBs = (MEM_NB_BLOCK *) (AllocHeapParams.BufferPtr + MemMainPtr->DieCount * sizeof (S3_MEM_NB_BLOCK));
658
659 // Initialize S3 NB Blocks
660 for (Node = 0; Node < MemMainPtr->DieCount; Node ++) {
661 (*S3NBPtr)[Node].NBPtr = &DummyNBs[Node];
662
663 for (i = 0; memNBInstalled[i].MemS3ResumeConstructNBBlock != 0; i++) {
664 if (memNBInstalled[i].MemS3ResumeConstructNBBlock (&(*S3NBPtr)[Node], NBArray[BSP_DIE].MemPtr, Node)) {
665 break;
666 }
667 };
668 if (memNBInstalled[i].MemS3ResumeConstructNBBlock == 0) {
669 *S3NBPtr = NULL;
670 break;
671 }
672 }
673 }
674}