5 * ACPI S3 Support routines
7 * Contains routines needed for supporting resume from the ACPI S3 sleep state.
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: Interface
12 * @e \$Revision: 35136 $ @e \$Date: 2010-07-16 11:29:48 +0800 (Fri, 16 Jul 2010) $
16 *****************************************************************************
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 * ***************************************************************************
48 /*----------------------------------------------------------------------------------------
49 * M O D U L E S U S E D
50 *----------------------------------------------------------------------------------------
59 #include "GeneralServices.h"
60 #include "cpuServices.h"
63 RDATA_GROUP (G1_PEICC)
65 #define FILECODE PROC_CPU_S3_FILECODE
66 /*----------------------------------------------------------------------------------------
67 * D E F I N I T I O N S A N D M A C R O S
68 *----------------------------------------------------------------------------------------
72 /*----------------------------------------------------------------------------------------
73 * T Y P E D E F S A N D S T R U C T U R E S
74 *----------------------------------------------------------------------------------------
78 /*----------------------------------------------------------------------------------------
79 * 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
80 *----------------------------------------------------------------------------------------
84 IN DEVICE_BLOCK_HEADER *DeviceList,
85 IN CALL_POINTS CallPoint,
86 OUT UINT32 *ActualBufferSize,
87 IN AMD_CONFIG_PARAMS *StdHeader
92 IN AMD_CONFIG_PARAMS *StdHeader,
93 IN PCI_DEVICE_DESCRIPTOR *Device,
94 IN CALL_POINTS CallPoint,
99 SaveConditionalPciDevice (
100 IN AMD_CONFIG_PARAMS *StdHeader,
101 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
102 IN CALL_POINTS CallPoint,
108 IN AMD_CONFIG_PARAMS *StdHeader,
109 IN MSR_DEVICE_DESCRIPTOR *Device,
110 IN CALL_POINTS CallPoint,
111 IN OUT UINT64 **OrMask
115 SaveConditionalMsrDevice (
116 IN AMD_CONFIG_PARAMS *StdHeader,
117 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
118 IN CALL_POINTS CallPoint,
119 IN OUT UINT64 **OrMask
124 IN AMD_CONFIG_PARAMS *StdHeader,
125 IN PCI_DEVICE_DESCRIPTOR *Device,
126 IN CALL_POINTS CallPoint,
131 RestoreConditionalPciDevice (
132 IN AMD_CONFIG_PARAMS *StdHeader,
133 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
134 IN CALL_POINTS CallPoint,
140 IN AMD_CONFIG_PARAMS *StdHeader,
141 IN MSR_DEVICE_DESCRIPTOR *Device,
142 IN CALL_POINTS CallPoint,
143 IN OUT UINT64 **OrMask
147 RestoreConditionalMsrDevice (
148 IN AMD_CONFIG_PARAMS *StdHeader,
149 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
150 IN CALL_POINTS CallPoint,
151 IN OUT UINT64 **OrMask
154 /*----------------------------------------------------------------------------------------
155 * E X P O R T E D F U N C T I O N S
156 *----------------------------------------------------------------------------------------
159 /*---------------------------------------------------------------------------------------*/
161 * Saves all devices in the given device list.
163 * This traverses the entire device list twice. In the first pass, we save
164 * all devices identified as Pre ESR. In the second pass, we save devices
165 * marked as post ESR.
167 * @param[in] DeviceList Beginning of the device list to save.
168 * @param[in] Storage Beginning of the context buffer.
169 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
170 * AMD_S3LATE_RESTORE.
171 * @param[out] ActualBufferSize Actual size used in saving the device list.
172 * @param[in] StdHeader AMD standard header config param.
176 SaveDeviceListContext (
177 IN DEVICE_BLOCK_HEADER *DeviceList,
179 IN CALL_POINTS CallPoint,
180 OUT UINT32 *ActualBufferSize,
181 IN AMD_CONFIG_PARAMS *StdHeader
184 // Copy device list over
185 LibAmdMemCopy (Storage,
187 (UINTN) DeviceList->RelativeOrMaskOffset,
189 SaveDeviceContext (Storage, CallPoint, ActualBufferSize, StdHeader);
192 /*---------------------------------------------------------------------------------------*/
194 * Saves all devices in the given device list.
196 * This traverses the entire device list twice. In the first pass, we save
197 * all devices identified as Pre ESR. In the second pass, we save devices
198 * marked as post ESR.
200 * @param[in,out] DeviceList Beginning of the device list to save.
201 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
202 * AMD_S3LATE_RESTORE.
203 * @param[out] ActualBufferSize Actual size used in saving the device list.
204 * @param[in] StdHeader AMD standard header config param.
209 IN DEVICE_BLOCK_HEADER *DeviceList,
210 IN CALL_POINTS CallPoint,
211 OUT UINT32 *ActualBufferSize,
212 IN AMD_CONFIG_PARAMS *StdHeader
215 DEVICE_DESCRIPTORS Device;
221 StartAddress = DeviceList;
222 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
223 OrMask = (UINT8 *) DeviceList + DeviceList->RelativeOrMaskOffset;
225 // Process Pre ESR List
226 for (i = 0; i < DeviceList->NumDevices; i++) {
227 switch (Device.CommonDeviceHeader->Type) {
228 case DEV_TYPE_PCI_PRE_ESR:
229 SavePciDevice (StdHeader, Device.PciDevice, CallPoint, &OrMask);
230 // Fall through to advance the pointer after saving context
234 case DEV_TYPE_CPCI_PRE_ESR:
235 SaveConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, &OrMask);
236 // Fall through to advance the pointer after saving context
240 case DEV_TYPE_MSR_PRE_ESR:
241 SaveMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) &OrMask);
242 // Fall through to advance the pointer after saving context
246 case DEV_TYPE_CMSR_PRE_ESR:
247 SaveConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) &OrMask);
248 // Fall through to advance the pointer after saving context
255 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
256 // Process Post ESR List
257 for (i = 0; i < DeviceList->NumDevices; i++) {
258 switch (Device.CommonDeviceHeader->Type) {
260 SavePciDevice (StdHeader, Device.PciDevice, CallPoint, &OrMask);
261 // Fall through to advance the pointer after saving context
262 case DEV_TYPE_PCI_PRE_ESR:
266 SaveConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, &OrMask);
267 // Fall through to advance the pointer after saving context
268 case DEV_TYPE_CPCI_PRE_ESR:
272 SaveMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) &OrMask);
273 // Fall through to advance the pointer after saving context
274 case DEV_TYPE_MSR_PRE_ESR:
278 SaveConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) &OrMask);
279 // Fall through to advance the pointer after saving context
280 case DEV_TYPE_CMSR_PRE_ESR:
285 EndAddress = (VOID *) OrMask;
286 *ActualBufferSize = (UINT32) (EndAddress - StartAddress);
289 /*---------------------------------------------------------------------------------------*/
291 * Saves the context of a PCI device.
293 * This traverses the provided register list saving PCI registers.
295 * @param[in] StdHeader AMD standard header config param.
296 * @param[in] Device PCI device to restore.
297 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
298 * AMD_S3LATE_RESTORE.
299 * @param[in,out] OrMask Current buffer pointer of raw register values.
304 IN AMD_CONFIG_PARAMS *StdHeader,
305 IN PCI_DEVICE_DESCRIPTOR *Device,
306 IN CALL_POINTS CallPoint,
310 UINT8 RegSizeInBytes;
311 UINT8 SpecialCaseIndex;
312 UINT8 *IntermediatePtr;
317 ACCESS_WIDTH AccessWidth;
318 AGESA_STATUS IgnoredSts;
320 PCI_REGISTER_BLOCK_HEADER *RegisterHdr;
322 GetSocketModuleOfNode ((UINT32) Device->Node,
326 GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);
328 if (CallPoint == INIT_RESUME) {
329 MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
331 S3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
334 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
335 PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
336 PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
337 RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
338 switch (RegSizeInBytes) {
340 AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
341 AccessWidth = AccessS3SaveWidth8;
344 AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
345 AccessWidth = AccessS3SaveWidth16;
348 // In this case, we don't need to save a register. We just need to call a special
349 // function to do certain things in the save and resume sequence.
350 // This should not be used in a non-special case.
356 AndMask = RegisterHdr->RegisterList[i].AndMask;
358 AccessWidth = AccessS3SaveWidth32;
361 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
362 ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0));
363 LibAmdPciRead (AccessWidth, PciAddress, *OrMask, StdHeader);
365 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
366 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, *OrMask, StdHeader);
369 // If AndMask is 0, then it is a not-care. Don't need to apply it to the OrMask
370 **((UINT32 **) OrMask) &= AndMask;
372 IntermediatePtr = (UINT8 *) *OrMask;
373 *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes;
377 /*---------------------------------------------------------------------------------------*/
379 * Saves the context of a 'conditional' PCI device.
381 * This traverses the provided register list saving PCI registers when appropriate.
383 * @param[in] StdHeader AMD standard header config param.
384 * @param[in] Device 'conditional' PCI device to restore.
385 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
386 * AMD_S3LATE_RESTORE.
387 * @param[in,out] OrMask Current buffer pointer of raw register values.
391 SaveConditionalPciDevice (
392 IN AMD_CONFIG_PARAMS *StdHeader,
393 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
394 IN CALL_POINTS CallPoint,
398 UINT8 RegSizeInBytes;
399 UINT8 SpecialCaseIndex;
400 UINT8 *IntermediatePtr;
405 ACCESS_WIDTH AccessWidth;
406 AGESA_STATUS IgnoredSts;
408 CPCI_REGISTER_BLOCK_HEADER *RegisterHdr;
410 GetSocketModuleOfNode ((UINT32) Device->Node,
414 GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);
416 if (CallPoint == INIT_RESUME) {
417 MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
419 S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
422 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
423 if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
424 ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
425 PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
426 PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
427 RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
428 switch (RegSizeInBytes) {
430 AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
431 AccessWidth = AccessS3SaveWidth8;
434 AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
435 AccessWidth = AccessS3SaveWidth16;
438 // In this case, we don't need to save a register. We just need to call a special
439 // function to do certain things in the save and resume sequence.
440 // This should not be used in a non-special case.
446 AndMask = RegisterHdr->RegisterList[i].AndMask;
448 AccessWidth = AccessS3SaveWidth32;
451 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
452 ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0));
453 LibAmdPciRead (AccessWidth, PciAddress, *OrMask, StdHeader);
455 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
456 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, *OrMask, StdHeader);
459 // If AndMask is 0, then it is a not-care. Don't need to apply it to the OrMask
460 **((UINT32 **) OrMask) &= AndMask;
462 IntermediatePtr = (UINT8 *) *OrMask;
463 *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes;
468 /*---------------------------------------------------------------------------------------*/
470 * Saves the context of an MSR device.
472 * This traverses the provided register list saving MSRs.
474 * @param[in] StdHeader AMD standard header config param.
475 * @param[in] Device MSR device to restore.
476 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
477 * AMD_S3LATE_RESTORE.
478 * @param[in,out] OrMask Current buffer pointer of raw register values.
483 IN AMD_CONFIG_PARAMS *StdHeader,
484 IN MSR_DEVICE_DESCRIPTOR *Device,
485 IN CALL_POINTS CallPoint,
486 IN OUT UINT64 **OrMask
489 UINT8 SpecialCaseIndex;
491 MSR_REGISTER_BLOCK_HEADER *RegisterHdr;
493 if (CallPoint == INIT_RESUME) {
494 MemFS3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
496 S3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
499 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
500 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
501 LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, *OrMask, StdHeader);
503 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
504 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address, *OrMask, StdHeader);
506 **OrMask &= RegisterHdr->RegisterList[i].AndMask;
511 /*---------------------------------------------------------------------------------------*/
513 * Saves the context of a 'conditional' MSR device.
515 * This traverses the provided register list saving MSRs when appropriate.
517 * @param[in] StdHeader AMD standard header config param.
518 * @param[in] Device 'conditional' MSR device to restore.
519 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
520 * AMD_S3LATE_RESTORE.
521 * @param[in,out] OrMask Current buffer pointer of raw register values.
525 SaveConditionalMsrDevice (
526 IN AMD_CONFIG_PARAMS *StdHeader,
527 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
528 IN CALL_POINTS CallPoint,
529 IN OUT UINT64 **OrMask
532 UINT8 SpecialCaseIndex;
534 CMSR_REGISTER_BLOCK_HEADER *RegisterHdr;
536 if (CallPoint == INIT_RESUME) {
537 MemFS3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
539 S3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
542 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
543 if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
544 ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
545 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
546 LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, (UINT64 *) *OrMask, StdHeader);
548 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
549 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address, (UINT64 *) *OrMask, StdHeader);
551 **OrMask &= RegisterHdr->RegisterList[i].AndMask;
557 /*---------------------------------------------------------------------------------------*/
559 * Determines the maximum amount of space required to store all raw register
560 * values for the given device list.
562 * This traverses the entire device list, and calculates the worst case size
563 * of each device in the device list.
565 * @param[in] DeviceList Beginning of the device list.
566 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
567 * AMD_S3LATE_RESTORE.
568 * @param[in] StdHeader AMD standard header config param.
570 * @retval Size in bytes required for storing all registers.
573 GetWorstCaseContextSize (
574 IN DEVICE_BLOCK_HEADER *DeviceList,
575 IN CALL_POINTS CallPoint,
576 IN AMD_CONFIG_PARAMS *StdHeader
579 UINT32 WorstCaseSize;
580 DEVICE_DESCRIPTORS Device;
582 REGISTER_BLOCK_HEADERS RegisterHdr;
584 WorstCaseSize = DeviceList->RelativeOrMaskOffset;
585 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
587 // Process Device List
588 for (i = 0; i < DeviceList->NumDevices; i++) {
589 switch (Device.CommonDeviceHeader->Type) {
590 case DEV_TYPE_PCI_PRE_ESR:
591 // PRE_ESR and post ESR take the same amount of space
593 if (CallPoint == INIT_RESUME) {
594 MemFS3GetPciDeviceRegisterList (Device.PciDevice, &RegisterHdr.PciRegisters, StdHeader);
596 S3GetPciDeviceRegisterList (Device.PciDevice, &RegisterHdr.PciRegisters, StdHeader);
598 WorstCaseSize += (RegisterHdr.PciRegisters->NumRegisters * 4);
601 case DEV_TYPE_CPCI_PRE_ESR:
602 // PRE_ESR and post ESR take the same amount of space
604 if (CallPoint == INIT_RESUME) {
605 MemFS3GetCPciDeviceRegisterList (Device.CPciDevice, &RegisterHdr.CPciRegisters, StdHeader);
607 S3GetCPciDeviceRegisterList (Device.CPciDevice, &RegisterHdr.CPciRegisters, StdHeader);
609 WorstCaseSize += (RegisterHdr.CPciRegisters->NumRegisters * 4);
612 case DEV_TYPE_MSR_PRE_ESR:
613 // PRE_ESR and post ESR take the same amount of space
615 if (CallPoint == INIT_RESUME) {
616 MemFS3GetMsrDeviceRegisterList (Device.MsrDevice, &RegisterHdr.MsrRegisters, StdHeader);
618 S3GetMsrDeviceRegisterList (Device.MsrDevice, &RegisterHdr.MsrRegisters, StdHeader);
620 WorstCaseSize += (RegisterHdr.MsrRegisters->NumRegisters * 8);
623 case DEV_TYPE_CMSR_PRE_ESR:
624 // PRE_ESR and post ESR take the same amount of space
626 if (CallPoint == INIT_RESUME) {
627 MemFS3GetCMsrDeviceRegisterList (Device.CMsrDevice, &RegisterHdr.CMsrRegisters, StdHeader);
629 S3GetCMsrDeviceRegisterList (Device.CMsrDevice, &RegisterHdr.CMsrRegisters, StdHeader);
631 WorstCaseSize += (RegisterHdr.CMsrRegisters->NumRegisters * 8);
638 return (WorstCaseSize);
641 /*---------------------------------------------------------------------------------------*/
643 * Restores all devices marked as 'before exiting self-refresh.'
645 * This traverses the entire device list, restoring all devices identified
648 * @param[in,out] OrMaskPtr Current buffer pointer of raw register values.
649 * @param[in] Storage Beginning of the device list.
650 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
651 * AMD_S3LATE_RESTORE.
652 * @param[in] StdHeader AMD standard header config param.
656 RestorePreESRContext (
657 OUT VOID **OrMaskPtr,
659 IN CALL_POINTS CallPoint,
660 IN AMD_CONFIG_PARAMS *StdHeader
663 DEVICE_DESCRIPTORS Device;
665 DEVICE_BLOCK_HEADER *DeviceList;
667 DeviceList = (DEVICE_BLOCK_HEADER *) Storage;
668 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
669 *OrMaskPtr = (UINT8 *) DeviceList + DeviceList->RelativeOrMaskOffset;
671 // Process Pre ESR List
672 for (i = 0; i < DeviceList->NumDevices; i++) {
673 switch (Device.CommonDeviceHeader->Type) {
674 case DEV_TYPE_PCI_PRE_ESR:
675 RestorePciDevice (StdHeader, Device.PciDevice, CallPoint, OrMaskPtr);
676 // Fall through to advance the pointer after restoring context
680 case DEV_TYPE_CPCI_PRE_ESR:
681 RestoreConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, OrMaskPtr);
682 // Fall through to advance the pointer after restoring context
686 case DEV_TYPE_MSR_PRE_ESR:
687 RestoreMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) OrMaskPtr);
688 // Fall through to advance the pointer after restoring context
692 case DEV_TYPE_CMSR_PRE_ESR:
693 RestoreConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) OrMaskPtr);
694 // Fall through to advance the pointer after restoring context
702 /*---------------------------------------------------------------------------------------*/
704 * Restores all devices marked as 'after exiting self-refresh.'
706 * This traverses the entire device list, restoring all devices identified
709 * @param[in] OrMaskPtr Current buffer pointer of raw register values.
710 * @param[in] Storage Beginning of the device list.
711 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
712 * AMD_S3LATE_RESTORE.
713 * @param[in] StdHeader AMD standard header config param.
717 RestorePostESRContext (
720 IN CALL_POINTS CallPoint,
721 IN AMD_CONFIG_PARAMS *StdHeader
724 DEVICE_DESCRIPTORS Device;
726 DEVICE_BLOCK_HEADER *DeviceList;
728 DeviceList = (DEVICE_BLOCK_HEADER *) Storage;
729 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
731 // Process Pre ESR List
732 for (i = 0; i < DeviceList->NumDevices; i++) {
733 switch (Device.CommonDeviceHeader->Type) {
735 RestorePciDevice (StdHeader, Device.PciDevice, CallPoint, &OrMaskPtr);
736 // Fall through to advance the pointer after restoring context
737 case DEV_TYPE_PCI_PRE_ESR:
741 RestoreConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, &OrMaskPtr);
742 // Fall through to advance the pointer after restoring context
743 case DEV_TYPE_CPCI_PRE_ESR:
747 RestoreMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) &OrMaskPtr);
748 // Fall through to advance the pointer after restoring context
749 case DEV_TYPE_MSR_PRE_ESR:
753 RestoreConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) &OrMaskPtr);
754 // Fall through to advance the pointer after restoring context
755 case DEV_TYPE_CMSR_PRE_ESR:
762 /*---------------------------------------------------------------------------------------*/
764 * Restores the context of a PCI device.
766 * This traverses the provided register list restoring PCI registers.
768 * @param[in] StdHeader AMD standard header config param.
769 * @param[in] Device 'conditional' PCI device to restore.
770 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
771 * AMD_S3LATE_RESTORE.
772 * @param[in,out] OrMask Current buffer pointer of raw register values.
777 IN AMD_CONFIG_PARAMS *StdHeader,
778 IN PCI_DEVICE_DESCRIPTOR *Device,
779 IN CALL_POINTS CallPoint,
783 UINT8 RegSizeInBytes;
784 UINT8 SpecialCaseIndex;
785 UINT8 *IntermediatePtr;
791 UINT32 RegValueWrite;
792 ACCESS_WIDTH AccessWidth;
793 AGESA_STATUS IgnoredSts;
795 PCI_REGISTER_BLOCK_HEADER *RegisterHdr;
797 GetSocketModuleOfNode ((UINT32) Device->Node,
801 GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);
803 if (CallPoint == INIT_RESUME) {
804 MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
806 S3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
809 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
810 PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
811 PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
812 RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
813 switch (RegSizeInBytes) {
815 AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
816 RegValueWrite = **(UINT8 **)OrMask;
817 AccessWidth = AccessS3SaveWidth8;
820 AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
821 RegValueWrite = **(UINT16 **)OrMask;
822 AccessWidth = AccessS3SaveWidth16;
825 // In this case, we don't need to restore a register. We just need to call a special
826 // function to do certain things in the save and resume sequence.
827 // This should not be used in a non-special case.
834 AndMask = RegisterHdr->RegisterList[i].AndMask;
836 RegValueWrite = **(UINT32 **)OrMask;
837 AccessWidth = AccessS3SaveWidth32;
840 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
841 ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0));
842 LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader);
843 RegValueWrite |= RegValueRead & (~AndMask);
844 LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader);
846 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
848 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth,
852 RegValueWrite |= RegValueRead & (~AndMask);
854 RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth,
859 IntermediatePtr = (UINT8 *) *OrMask;
860 *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes;
864 /*---------------------------------------------------------------------------------------*/
866 * Restores the context of a 'conditional' PCI device.
868 * This traverses the provided register list restoring PCI registers when appropriate.
870 * @param[in] StdHeader AMD standard header config param.
871 * @param[in] Device 'conditional' PCI device to restore.
872 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
873 * AMD_S3LATE_RESTORE.
874 * @param[in,out] OrMask Current buffer pointer of raw register values.
878 RestoreConditionalPciDevice (
879 IN AMD_CONFIG_PARAMS *StdHeader,
880 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
881 IN CALL_POINTS CallPoint,
885 UINT8 RegSizeInBytes;
886 UINT8 SpecialCaseIndex;
887 UINT8 *IntermediatePtr;
892 UINT32 RegValueWrite;
894 ACCESS_WIDTH AccessWidth;
895 AGESA_STATUS IgnoredSts;
897 CPCI_REGISTER_BLOCK_HEADER *RegisterHdr;
899 GetSocketModuleOfNode ((UINT32) Device->Node,
903 GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);
905 if (CallPoint == INIT_RESUME) {
906 MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
908 S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
911 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
912 if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
913 ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
914 PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
915 PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
916 RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
917 switch (RegSizeInBytes) {
919 AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
920 RegValueWrite = **(UINT8 **)OrMask;
921 AccessWidth = AccessS3SaveWidth8;
924 AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
925 RegValueWrite = **(UINT16 **)OrMask;
926 AccessWidth = AccessS3SaveWidth16;
929 // In this case, we don't need to restore a register. We just need to call a special
930 // function to do certain things in the save and resume sequence.
931 // This should not be used in a non-special case.
938 AndMask = RegisterHdr->RegisterList[i].AndMask;
940 RegValueWrite = **(UINT32 **)OrMask;
941 AccessWidth = AccessS3SaveWidth32;
944 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
945 LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader);
946 RegValueWrite |= RegValueRead & (~AndMask);
947 LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader);
949 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
951 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth,
955 RegValueWrite |= RegValueRead & (~AndMask);
957 RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth,
962 IntermediatePtr = (UINT8 *) *OrMask;
963 *OrMask = &IntermediatePtr[RegSizeInBytes];
968 /*---------------------------------------------------------------------------------------*/
970 * Restores the context of an MSR device.
972 * This traverses the provided register list restoring MSRs.
974 * @param[in] StdHeader AMD standard header config param.
975 * @param[in] Device MSR device to restore.
976 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
977 * AMD_S3LATE_RESTORE.
978 * @param[in,out] OrMask Current buffer pointer of raw register values.
983 IN AMD_CONFIG_PARAMS *StdHeader,
984 IN MSR_DEVICE_DESCRIPTOR *Device,
985 IN CALL_POINTS CallPoint,
986 IN OUT UINT64 **OrMask
989 UINT8 SpecialCaseIndex;
992 UINT64 RegValueWrite;
993 MSR_REGISTER_BLOCK_HEADER *RegisterHdr;
995 if (CallPoint == INIT_RESUME) {
996 MemFS3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
998 S3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
1001 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
1002 RegValueWrite = **OrMask;
1003 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
1004 LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, &RegValueRead, StdHeader);
1005 RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
1006 LibAmdMsrWrite (RegisterHdr->RegisterList[i].Address, &RegValueWrite, StdHeader);
1008 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
1009 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address,
1012 RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
1013 RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (RegisterHdr->RegisterList[i].Address,
1021 /*---------------------------------------------------------------------------------------*/
1023 * Restores the context of a 'conditional' MSR device.
1025 * This traverses the provided register list restoring MSRs when appropriate.
1027 * @param[in] StdHeader AMD standard header config param.
1028 * @param[in] Device 'conditional' MSR device to restore.
1029 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
1030 * AMD_S3LATE_RESTORE.
1031 * @param[in,out] OrMask Current buffer pointer of raw register values.
1035 RestoreConditionalMsrDevice (
1036 IN AMD_CONFIG_PARAMS *StdHeader,
1037 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
1038 IN CALL_POINTS CallPoint,
1039 IN OUT UINT64 **OrMask
1042 UINT8 SpecialCaseIndex;
1044 UINT64 RegValueRead;
1045 UINT64 RegValueWrite;
1046 CMSR_REGISTER_BLOCK_HEADER *RegisterHdr;
1048 if (CallPoint == INIT_RESUME) {
1049 MemFS3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
1051 S3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
1054 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
1055 if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
1056 ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
1057 RegValueWrite = **OrMask;
1058 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
1059 LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, &RegValueRead, StdHeader);
1060 RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
1061 LibAmdMsrWrite (RegisterHdr->RegisterList[i].Address, &RegValueWrite, StdHeader);
1063 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
1064 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address,
1067 RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
1068 RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (RegisterHdr->RegisterList[i].Address,
1077 /*---------------------------------------------------------------------------------------*/
1079 * Unique device ID to PCI register list translator.
1081 * This translates the given device header in storage to the appropriate list
1082 * of registers in the AGESA image.
1084 * @param[out] NonMemoryRelatedDeviceList List of devices to save and restore
1085 * during S3LateRestore.
1086 * @param[in] StdHeader AMD standard header config param.
1090 GetNonMemoryRelatedDeviceList (
1091 OUT DEVICE_BLOCK_HEADER **NonMemoryRelatedDeviceList,
1092 IN AMD_CONFIG_PARAMS *StdHeader
1095 *NonMemoryRelatedDeviceList = NULL;
1098 /*---------------------------------------------------------------------------------------*/
1100 * Unique device ID to PCI register list translator.
1102 * This translates the given device header in storage to the appropriate list
1103 * of registers in the AGESA image.
1105 * @param[in] Device Device header containing the unique ID.
1106 * @param[out] RegisterHdr Output PCI register list pointer.
1107 * @param[in] StdHeader AMD standard header config param.
1109 * @retval AGESA_SUCCESS Always succeeds.
1112 S3GetPciDeviceRegisterList (
1113 IN PCI_DEVICE_DESCRIPTOR *Device,
1114 OUT PCI_REGISTER_BLOCK_HEADER **RegisterHdr,
1115 IN AMD_CONFIG_PARAMS *StdHeader
1118 *RegisterHdr = NULL;
1119 return AGESA_SUCCESS;
1122 /*---------------------------------------------------------------------------------------*/
1124 * Unique device ID to 'conditional' PCI register list translator.
1126 * This translates the given device header in storage to the appropriate list
1127 * of registers in the AGESA image.
1129 * @param[in] Device Device header containing the unique ID.
1130 * @param[out] RegisterHdr Output 'conditional' PCI register list pointer.
1131 * @param[in] StdHeader AMD standard header config param.
1133 * @retval AGESA_SUCCESS Always succeeds.
1136 S3GetCPciDeviceRegisterList (
1137 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
1138 OUT CPCI_REGISTER_BLOCK_HEADER **RegisterHdr,
1139 IN AMD_CONFIG_PARAMS *StdHeader
1142 *RegisterHdr = NULL;
1143 return AGESA_SUCCESS;
1147 /*---------------------------------------------------------------------------------------*/
1149 * Unique device ID to MSR register list translator.
1151 * This translates the given device header in storage to the appropriate list
1152 * of registers in the AGESA image.
1154 * @param[in] Device Device header containing the unique ID.
1155 * @param[out] RegisterHdr Output MSR register list pointer.
1156 * @param[in] StdHeader AMD standard header config param.
1158 * @retval AGESA_SUCCESS Always succeeds.
1161 S3GetMsrDeviceRegisterList (
1162 IN MSR_DEVICE_DESCRIPTOR *Device,
1163 OUT MSR_REGISTER_BLOCK_HEADER **RegisterHdr,
1164 IN AMD_CONFIG_PARAMS *StdHeader
1167 *RegisterHdr = NULL;
1168 return AGESA_SUCCESS;
1171 /*---------------------------------------------------------------------------------------*/
1173 * Unique device ID to 'conditional' MSR register list translator.
1175 * This translates the given device header in storage to the appropriate list
1176 * of registers in the AGESA image.
1178 * @param[in] Device Device header containing the unique ID.
1179 * @param[out] RegisterHdr Output 'conditional' MSR register list pointer.
1180 * @param[in] StdHeader AMD standard header config param.
1182 * @retval AGESA_SUCCESS Always succeeds.
1185 S3GetCMsrDeviceRegisterList (
1186 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
1187 OUT CMSR_REGISTER_BLOCK_HEADER **RegisterHdr,
1188 IN AMD_CONFIG_PARAMS *StdHeader
1191 *RegisterHdr = NULL;
1192 return AGESA_SUCCESS;
1195 /*---------------------------------------------------------------------------------------*/
1197 * Constructor for the AMD_S3_PARAMS structure.
1199 * This routine initializes failsafe values for the AMD_S3_PARAMS structure
1200 * to be used by the AMD_INIT_RESUME, AMD_S3_SAVE, and AMD_S3LATE_RESTORE
1203 * @param[in,out] S3Params Required input parameter for the AMD_S3_SAVE,
1204 * AMD_INIT_RESUME, and AMD_S3_SAVE entry points.
1208 AmdS3ParamsInitializer (
1209 OUT AMD_S3_PARAMS *S3Params
1212 S3Params->Signature = 0x52545341;
1213 S3Params->Version = 0x0000;
1214 S3Params->VolatileStorage = NULL;
1215 S3Params->VolatileStorageSize = 0x00000000;
1216 S3Params->Flags = 0x00000000;
1217 S3Params->NvStorage = NULL;
1218 S3Params->NvStorageSize = 0x00000000;