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: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
15 /*****************************************************************************
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
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.
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.
42 ******************************************************************************
46 /*----------------------------------------------------------------------------------------
47 * M O D U L E S U S E D
48 *----------------------------------------------------------------------------------------
57 #include "GeneralServices.h"
58 #include "cpuServices.h"
63 #define FILECODE PROC_CPU_S3_FILECODE
64 /*----------------------------------------------------------------------------------------
65 * D E F I N I T I O N S A N D M A C R O S
66 *----------------------------------------------------------------------------------------
70 /*----------------------------------------------------------------------------------------
71 * T Y P E D E F S A N D S T R U C T U R E S
72 *----------------------------------------------------------------------------------------
76 /*----------------------------------------------------------------------------------------
77 * 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
78 *----------------------------------------------------------------------------------------
82 IN DEVICE_BLOCK_HEADER *DeviceList,
83 IN CALL_POINTS CallPoint,
84 OUT UINT32 *ActualBufferSize,
85 IN AMD_CONFIG_PARAMS *StdHeader
90 IN AMD_CONFIG_PARAMS *StdHeader,
91 IN PCI_DEVICE_DESCRIPTOR *Device,
92 IN CALL_POINTS CallPoint,
97 SaveConditionalPciDevice (
98 IN AMD_CONFIG_PARAMS *StdHeader,
99 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
100 IN CALL_POINTS CallPoint,
106 IN AMD_CONFIG_PARAMS *StdHeader,
107 IN MSR_DEVICE_DESCRIPTOR *Device,
108 IN CALL_POINTS CallPoint,
109 IN OUT UINT64 **OrMask
113 SaveConditionalMsrDevice (
114 IN AMD_CONFIG_PARAMS *StdHeader,
115 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
116 IN CALL_POINTS CallPoint,
117 IN OUT UINT64 **OrMask
122 IN AMD_CONFIG_PARAMS *StdHeader,
123 IN PCI_DEVICE_DESCRIPTOR *Device,
124 IN CALL_POINTS CallPoint,
129 RestoreConditionalPciDevice (
130 IN AMD_CONFIG_PARAMS *StdHeader,
131 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
132 IN CALL_POINTS CallPoint,
138 IN AMD_CONFIG_PARAMS *StdHeader,
139 IN MSR_DEVICE_DESCRIPTOR *Device,
140 IN CALL_POINTS CallPoint,
141 IN OUT UINT64 **OrMask
145 RestoreConditionalMsrDevice (
146 IN AMD_CONFIG_PARAMS *StdHeader,
147 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
148 IN CALL_POINTS CallPoint,
149 IN OUT UINT64 **OrMask
152 /*----------------------------------------------------------------------------------------
153 * E X P O R T E D F U N C T I O N S
154 *----------------------------------------------------------------------------------------
157 /*---------------------------------------------------------------------------------------*/
159 * Saves all devices in the given device list.
161 * This traverses the entire device list twice. In the first pass, we save
162 * all devices identified as Pre ESR. In the second pass, we save devices
163 * marked as post ESR.
165 * @param[in] DeviceList Beginning of the device list to save.
166 * @param[in] Storage Beginning of the context buffer.
167 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
168 * AMD_S3LATE_RESTORE.
169 * @param[out] ActualBufferSize Actual size used in saving the device list.
170 * @param[in] StdHeader AMD standard header config param.
174 SaveDeviceListContext (
175 IN DEVICE_BLOCK_HEADER *DeviceList,
177 IN CALL_POINTS CallPoint,
178 OUT UINT32 *ActualBufferSize,
179 IN AMD_CONFIG_PARAMS *StdHeader
182 // Copy device list over
183 LibAmdMemCopy (Storage,
185 (UINTN) DeviceList->RelativeOrMaskOffset,
187 SaveDeviceContext (Storage, CallPoint, ActualBufferSize, StdHeader);
190 /*---------------------------------------------------------------------------------------*/
192 * Saves all devices in the given device list.
194 * This traverses the entire device list twice. In the first pass, we save
195 * all devices identified as Pre ESR. In the second pass, we save devices
196 * marked as post ESR.
198 * @param[in,out] DeviceList Beginning of the device list to save.
199 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
200 * AMD_S3LATE_RESTORE.
201 * @param[out] ActualBufferSize Actual size used in saving the device list.
202 * @param[in] StdHeader AMD standard header config param.
207 IN DEVICE_BLOCK_HEADER *DeviceList,
208 IN CALL_POINTS CallPoint,
209 OUT UINT32 *ActualBufferSize,
210 IN AMD_CONFIG_PARAMS *StdHeader
213 DEVICE_DESCRIPTORS Device;
219 StartAddress = (UINT64) DeviceList;
220 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
221 OrMask = (UINT8 *) DeviceList + DeviceList->RelativeOrMaskOffset;
223 // Process Pre ESR List
224 for (i = 0; i < DeviceList->NumDevices; i++) {
225 switch (Device.CommonDeviceHeader->Type) {
226 case DEV_TYPE_PCI_PRE_ESR:
227 SavePciDevice (StdHeader, Device.PciDevice, CallPoint, &OrMask);
228 // Fall through to advance the pointer after saving context
232 case DEV_TYPE_CPCI_PRE_ESR:
233 SaveConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, &OrMask);
234 // Fall through to advance the pointer after saving context
238 case DEV_TYPE_MSR_PRE_ESR:
239 SaveMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) &OrMask);
240 // Fall through to advance the pointer after saving context
244 case DEV_TYPE_CMSR_PRE_ESR:
245 SaveConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) &OrMask);
246 // Fall through to advance the pointer after saving context
253 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
254 // Process Post ESR List
255 for (i = 0; i < DeviceList->NumDevices; i++) {
256 switch (Device.CommonDeviceHeader->Type) {
258 SavePciDevice (StdHeader, Device.PciDevice, CallPoint, &OrMask);
259 // Fall through to advance the pointer after saving context
260 case DEV_TYPE_PCI_PRE_ESR:
264 SaveConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, &OrMask);
265 // Fall through to advance the pointer after saving context
266 case DEV_TYPE_CPCI_PRE_ESR:
270 SaveMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) &OrMask);
271 // Fall through to advance the pointer after saving context
272 case DEV_TYPE_MSR_PRE_ESR:
276 SaveConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) &OrMask);
277 // Fall through to advance the pointer after saving context
278 case DEV_TYPE_CMSR_PRE_ESR:
283 EndAddress = (UINT64) OrMask;
284 *ActualBufferSize = (UINT32) (EndAddress - StartAddress);
287 /*---------------------------------------------------------------------------------------*/
289 * Saves the context of a PCI device.
291 * This traverses the provided register list saving PCI registers.
293 * @param[in] StdHeader AMD standard header config param.
294 * @param[in] Device PCI device to restore.
295 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
296 * AMD_S3LATE_RESTORE.
297 * @param[in,out] OrMask Current buffer pointer of raw register values.
302 IN AMD_CONFIG_PARAMS *StdHeader,
303 IN PCI_DEVICE_DESCRIPTOR *Device,
304 IN CALL_POINTS CallPoint,
308 UINT8 RegSizeInBytes;
309 UINT8 SpecialCaseIndex;
310 UINT8 *IntermediatePtr;
315 ACCESS_WIDTH AccessWidth;
316 AGESA_STATUS IgnoredSts;
318 PCI_REGISTER_BLOCK_HEADER *RegisterHdr;
320 GetSocketModuleOfNode ((UINT32) Device->Node,
324 GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);
326 if (CallPoint == INIT_RESUME) {
327 MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
329 S3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
332 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
333 PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
334 PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
335 RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
336 switch (RegSizeInBytes) {
338 AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
339 AccessWidth = AccessS3SaveWidth8;
342 AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
343 AccessWidth = AccessS3SaveWidth16;
346 // In this case, we don't need to save a register. We just need to call a special
347 // function to do certain things in the save and resume sequence.
348 // This should not be used in a non-special case.
354 AndMask = RegisterHdr->RegisterList[i].AndMask;
356 AccessWidth = AccessS3SaveWidth32;
359 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
360 ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0));
361 LibAmdPciRead (AccessWidth, PciAddress, *OrMask, StdHeader);
363 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
364 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, *OrMask, StdHeader);
367 // If AndMask is 0, then it is a not-care. Don't need to apply it to the OrMask
368 **((UINT32 **) OrMask) &= AndMask;
370 if ((RegSizeInBytes == 0) && (**((UINT32 **) OrMask) == RESTART_FROM_BEGINNING_LIST)) {
371 // Restart from the beginning of the register list
374 IntermediatePtr = (UINT8 *) *OrMask;
375 *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes;
379 /*---------------------------------------------------------------------------------------*/
381 * Saves the context of a 'conditional' PCI device.
383 * This traverses the provided register list saving PCI registers when appropriate.
385 * @param[in] StdHeader AMD standard header config param.
386 * @param[in] Device 'conditional' PCI device to restore.
387 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
388 * AMD_S3LATE_RESTORE.
389 * @param[in,out] OrMask Current buffer pointer of raw register values.
393 SaveConditionalPciDevice (
394 IN AMD_CONFIG_PARAMS *StdHeader,
395 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
396 IN CALL_POINTS CallPoint,
400 UINT8 RegSizeInBytes;
401 UINT8 SpecialCaseIndex;
402 UINT8 *IntermediatePtr;
407 ACCESS_WIDTH AccessWidth;
408 AGESA_STATUS IgnoredSts;
410 CPCI_REGISTER_BLOCK_HEADER *RegisterHdr;
412 GetSocketModuleOfNode ((UINT32) Device->Node,
416 GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);
418 if (CallPoint == INIT_RESUME) {
419 MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
421 S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
424 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
425 if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
426 ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
427 PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
428 PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
429 RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
430 switch (RegSizeInBytes) {
432 AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
433 AccessWidth = AccessS3SaveWidth8;
436 AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
437 AccessWidth = AccessS3SaveWidth16;
440 // In this case, we don't need to save a register. We just need to call a special
441 // function to do certain things in the save and resume sequence.
442 // This should not be used in a non-special case.
448 AndMask = RegisterHdr->RegisterList[i].AndMask;
450 AccessWidth = AccessS3SaveWidth32;
453 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
454 ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0));
455 LibAmdPciRead (AccessWidth, PciAddress, *OrMask, StdHeader);
457 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
458 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, *OrMask, StdHeader);
461 // If AndMask is 0, then it is a not-care. Don't need to apply it to the OrMask
462 **((UINT32 **) OrMask) &= AndMask;
464 if ((RegSizeInBytes == 0) && (**((UINT32 **) OrMask) == RESTART_FROM_BEGINNING_LIST)) {
465 // Restart from the beginning of the register list
468 IntermediatePtr = (UINT8 *) *OrMask;
469 *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes;
474 /*---------------------------------------------------------------------------------------*/
476 * Saves the context of an MSR device.
478 * This traverses the provided register list saving MSRs.
480 * @param[in] StdHeader AMD standard header config param.
481 * @param[in] Device MSR device to restore.
482 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
483 * AMD_S3LATE_RESTORE.
484 * @param[in,out] OrMask Current buffer pointer of raw register values.
489 IN AMD_CONFIG_PARAMS *StdHeader,
490 IN MSR_DEVICE_DESCRIPTOR *Device,
491 IN CALL_POINTS CallPoint,
492 IN OUT UINT64 **OrMask
495 UINT8 SpecialCaseIndex;
497 MSR_REGISTER_BLOCK_HEADER *RegisterHdr;
499 if (CallPoint == INIT_RESUME) {
500 MemFS3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
502 S3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
505 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
506 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
507 LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, *OrMask, StdHeader);
509 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
510 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address, *OrMask, StdHeader);
512 **OrMask &= RegisterHdr->RegisterList[i].AndMask;
517 /*---------------------------------------------------------------------------------------*/
519 * Saves the context of a 'conditional' MSR device.
521 * This traverses the provided register list saving MSRs when appropriate.
523 * @param[in] StdHeader AMD standard header config param.
524 * @param[in] Device 'conditional' MSR device to restore.
525 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
526 * AMD_S3LATE_RESTORE.
527 * @param[in,out] OrMask Current buffer pointer of raw register values.
531 SaveConditionalMsrDevice (
532 IN AMD_CONFIG_PARAMS *StdHeader,
533 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
534 IN CALL_POINTS CallPoint,
535 IN OUT UINT64 **OrMask
538 UINT8 SpecialCaseIndex;
540 CMSR_REGISTER_BLOCK_HEADER *RegisterHdr;
542 if (CallPoint == INIT_RESUME) {
543 MemFS3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
545 S3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
548 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
549 if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
550 ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
551 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
552 LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, (UINT64 *) *OrMask, StdHeader);
554 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
555 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address, (UINT64 *) *OrMask, StdHeader);
557 **OrMask &= RegisterHdr->RegisterList[i].AndMask;
563 /*---------------------------------------------------------------------------------------*/
565 * Determines the maximum amount of space required to store all raw register
566 * values for the given device list.
568 * This traverses the entire device list, and calculates the worst case size
569 * of each device in the device list.
571 * @param[in] DeviceList Beginning of the device list.
572 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
573 * AMD_S3LATE_RESTORE.
574 * @param[in] StdHeader AMD standard header config param.
576 * @retval Size in bytes required for storing all registers.
579 GetWorstCaseContextSize (
580 IN DEVICE_BLOCK_HEADER *DeviceList,
581 IN CALL_POINTS CallPoint,
582 IN AMD_CONFIG_PARAMS *StdHeader
585 UINT32 WorstCaseSize;
586 DEVICE_DESCRIPTORS Device;
588 REGISTER_BLOCK_HEADERS RegisterHdr;
590 WorstCaseSize = DeviceList->RelativeOrMaskOffset;
591 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
593 // Process Device List
594 for (i = 0; i < DeviceList->NumDevices; i++) {
595 switch (Device.CommonDeviceHeader->Type) {
596 case DEV_TYPE_PCI_PRE_ESR:
597 // PRE_ESR and post ESR take the same amount of space
599 if (CallPoint == INIT_RESUME) {
600 MemFS3GetPciDeviceRegisterList (Device.PciDevice, &RegisterHdr.PciRegisters, StdHeader);
602 S3GetPciDeviceRegisterList (Device.PciDevice, &RegisterHdr.PciRegisters, StdHeader);
604 WorstCaseSize += (RegisterHdr.PciRegisters->NumRegisters * 4);
607 case DEV_TYPE_CPCI_PRE_ESR:
608 // PRE_ESR and post ESR take the same amount of space
610 if (CallPoint == INIT_RESUME) {
611 MemFS3GetCPciDeviceRegisterList (Device.CPciDevice, &RegisterHdr.CPciRegisters, StdHeader);
613 S3GetCPciDeviceRegisterList (Device.CPciDevice, &RegisterHdr.CPciRegisters, StdHeader);
615 WorstCaseSize += (RegisterHdr.CPciRegisters->NumRegisters * 4);
618 case DEV_TYPE_MSR_PRE_ESR:
619 // PRE_ESR and post ESR take the same amount of space
621 if (CallPoint == INIT_RESUME) {
622 MemFS3GetMsrDeviceRegisterList (Device.MsrDevice, &RegisterHdr.MsrRegisters, StdHeader);
624 S3GetMsrDeviceRegisterList (Device.MsrDevice, &RegisterHdr.MsrRegisters, StdHeader);
626 WorstCaseSize += (RegisterHdr.MsrRegisters->NumRegisters * 8);
629 case DEV_TYPE_CMSR_PRE_ESR:
630 // PRE_ESR and post ESR take the same amount of space
632 if (CallPoint == INIT_RESUME) {
633 MemFS3GetCMsrDeviceRegisterList (Device.CMsrDevice, &RegisterHdr.CMsrRegisters, StdHeader);
635 S3GetCMsrDeviceRegisterList (Device.CMsrDevice, &RegisterHdr.CMsrRegisters, StdHeader);
637 WorstCaseSize += (RegisterHdr.CMsrRegisters->NumRegisters * 8);
644 return (WorstCaseSize);
647 /*---------------------------------------------------------------------------------------*/
649 * Restores all devices marked as 'before exiting self-refresh.'
651 * This traverses the entire device list, restoring all devices identified
654 * @param[in,out] OrMaskPtr Current buffer pointer of raw register values.
655 * @param[in] Storage Beginning of the device list.
656 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
657 * AMD_S3LATE_RESTORE.
658 * @param[in] StdHeader AMD standard header config param.
662 RestorePreESRContext (
663 OUT VOID **OrMaskPtr,
665 IN CALL_POINTS CallPoint,
666 IN AMD_CONFIG_PARAMS *StdHeader
669 DEVICE_DESCRIPTORS Device;
671 DEVICE_BLOCK_HEADER *DeviceList;
673 DeviceList = (DEVICE_BLOCK_HEADER *) Storage;
674 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
675 *OrMaskPtr = (UINT8 *) DeviceList + DeviceList->RelativeOrMaskOffset;
677 // Process Pre ESR List
678 for (i = 0; i < DeviceList->NumDevices; i++) {
679 switch (Device.CommonDeviceHeader->Type) {
680 case DEV_TYPE_PCI_PRE_ESR:
681 RestorePciDevice (StdHeader, Device.PciDevice, CallPoint, OrMaskPtr);
682 // Fall through to advance the pointer after restoring context
686 case DEV_TYPE_CPCI_PRE_ESR:
687 RestoreConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, OrMaskPtr);
688 // Fall through to advance the pointer after restoring context
692 case DEV_TYPE_MSR_PRE_ESR:
693 RestoreMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) OrMaskPtr);
694 // Fall through to advance the pointer after restoring context
698 case DEV_TYPE_CMSR_PRE_ESR:
699 RestoreConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) OrMaskPtr);
700 // Fall through to advance the pointer after restoring context
708 /*---------------------------------------------------------------------------------------*/
710 * Restores all devices marked as 'after exiting self-refresh.'
712 * This traverses the entire device list, restoring all devices identified
715 * @param[in] OrMaskPtr Current buffer pointer of raw register values.
716 * @param[in] Storage Beginning of the device list.
717 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
718 * AMD_S3LATE_RESTORE.
719 * @param[in] StdHeader AMD standard header config param.
723 RestorePostESRContext (
726 IN CALL_POINTS CallPoint,
727 IN AMD_CONFIG_PARAMS *StdHeader
730 DEVICE_DESCRIPTORS Device;
732 DEVICE_BLOCK_HEADER *DeviceList;
734 DeviceList = (DEVICE_BLOCK_HEADER *) Storage;
735 Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
737 // Process Pre ESR List
738 for (i = 0; i < DeviceList->NumDevices; i++) {
739 switch (Device.CommonDeviceHeader->Type) {
741 RestorePciDevice (StdHeader, Device.PciDevice, CallPoint, &OrMaskPtr);
742 // Fall through to advance the pointer after restoring context
743 case DEV_TYPE_PCI_PRE_ESR:
747 RestoreConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, &OrMaskPtr);
748 // Fall through to advance the pointer after restoring context
749 case DEV_TYPE_CPCI_PRE_ESR:
753 RestoreMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) &OrMaskPtr);
754 // Fall through to advance the pointer after restoring context
755 case DEV_TYPE_MSR_PRE_ESR:
759 RestoreConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) &OrMaskPtr);
760 // Fall through to advance the pointer after restoring context
761 case DEV_TYPE_CMSR_PRE_ESR:
768 /*---------------------------------------------------------------------------------------*/
770 * Restores the context of a PCI device.
772 * This traverses the provided register list restoring PCI registers.
774 * @param[in] StdHeader AMD standard header config param.
775 * @param[in] Device 'conditional' PCI device to restore.
776 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
777 * AMD_S3LATE_RESTORE.
778 * @param[in,out] OrMask Current buffer pointer of raw register values.
783 IN AMD_CONFIG_PARAMS *StdHeader,
784 IN PCI_DEVICE_DESCRIPTOR *Device,
785 IN CALL_POINTS CallPoint,
789 UINT8 RegSizeInBytes;
790 UINT8 SpecialCaseIndex;
791 UINT8 *IntermediatePtr;
797 UINT32 RegValueWrite;
798 ACCESS_WIDTH AccessWidth;
799 AGESA_STATUS IgnoredSts;
801 PCI_REGISTER_BLOCK_HEADER *RegisterHdr;
803 GetSocketModuleOfNode ((UINT32) Device->Node,
807 GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);
809 if (CallPoint == INIT_RESUME) {
810 MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
812 S3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
815 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
816 PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
817 PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
818 RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
819 switch (RegSizeInBytes) {
821 AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
822 RegValueWrite = **(UINT8 **)OrMask;
823 AccessWidth = AccessS3SaveWidth8;
826 AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
827 RegValueWrite = **(UINT16 **)OrMask;
828 AccessWidth = AccessS3SaveWidth16;
831 // In this case, we don't need to restore a register. We just need to call a special
832 // function to do certain things in the save and resume sequence.
833 // This should not be used in a non-special case.
840 AndMask = RegisterHdr->RegisterList[i].AndMask;
842 RegValueWrite = **(UINT32 **)OrMask;
843 AccessWidth = AccessS3SaveWidth32;
846 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
847 ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0));
848 LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader);
849 RegValueWrite |= RegValueRead & (~AndMask);
850 LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader);
852 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
854 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth,
858 RegValueWrite |= RegValueRead & (~AndMask);
860 RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth,
865 IntermediatePtr = (UINT8 *) *OrMask;
866 *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes;
867 if ((RegSizeInBytes == 0) && (RegValueWrite == RESTART_FROM_BEGINNING_LIST)) {
868 // Restart from the beginning of the register list
874 /*---------------------------------------------------------------------------------------*/
876 * Restores the context of a 'conditional' PCI device.
878 * This traverses the provided register list restoring PCI registers when appropriate.
880 * @param[in] StdHeader AMD standard header config param.
881 * @param[in] Device 'conditional' PCI device to restore.
882 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
883 * AMD_S3LATE_RESTORE.
884 * @param[in,out] OrMask Current buffer pointer of raw register values.
888 RestoreConditionalPciDevice (
889 IN AMD_CONFIG_PARAMS *StdHeader,
890 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
891 IN CALL_POINTS CallPoint,
895 UINT8 RegSizeInBytes;
896 UINT8 SpecialCaseIndex;
897 UINT8 *IntermediatePtr;
902 UINT32 RegValueWrite;
904 ACCESS_WIDTH AccessWidth;
905 AGESA_STATUS IgnoredSts;
907 CPCI_REGISTER_BLOCK_HEADER *RegisterHdr;
909 GetSocketModuleOfNode ((UINT32) Device->Node,
913 GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);
915 if (CallPoint == INIT_RESUME) {
916 MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
918 S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
921 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
922 if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
923 ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
924 PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
925 PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
926 RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
927 switch (RegSizeInBytes) {
929 AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
930 RegValueWrite = **(UINT8 **)OrMask;
931 AccessWidth = AccessS3SaveWidth8;
934 AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
935 RegValueWrite = **(UINT16 **)OrMask;
936 AccessWidth = AccessS3SaveWidth16;
939 // In this case, we don't need to restore a register. We just need to call a special
940 // function to do certain things in the save and resume sequence.
941 // This should not be used in a non-special case.
948 AndMask = RegisterHdr->RegisterList[i].AndMask;
950 RegValueWrite = **(UINT32 **)OrMask;
951 AccessWidth = AccessS3SaveWidth32;
954 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
955 LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader);
956 RegValueWrite |= RegValueRead & (~AndMask);
957 LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader);
959 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
961 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth,
965 RegValueWrite |= RegValueRead & (~AndMask);
967 RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth,
972 IntermediatePtr = (UINT8 *) *OrMask;
973 *OrMask = &IntermediatePtr[RegSizeInBytes];
974 if ((RegSizeInBytes == 0) && (RegValueWrite == RESTART_FROM_BEGINNING_LIST)) {
975 // Restart from the beginning of the register list
982 /*---------------------------------------------------------------------------------------*/
984 * Restores the context of an MSR device.
986 * This traverses the provided register list restoring MSRs.
988 * @param[in] StdHeader AMD standard header config param.
989 * @param[in] Device MSR device to restore.
990 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
991 * AMD_S3LATE_RESTORE.
992 * @param[in,out] OrMask Current buffer pointer of raw register values.
997 IN AMD_CONFIG_PARAMS *StdHeader,
998 IN MSR_DEVICE_DESCRIPTOR *Device,
999 IN CALL_POINTS CallPoint,
1000 IN OUT UINT64 **OrMask
1003 UINT8 SpecialCaseIndex;
1005 UINT64 RegValueRead;
1006 UINT64 RegValueWrite;
1007 MSR_REGISTER_BLOCK_HEADER *RegisterHdr;
1009 if (CallPoint == INIT_RESUME) {
1010 MemFS3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
1012 S3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
1015 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
1016 RegValueWrite = **OrMask;
1017 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
1018 LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, &RegValueRead, StdHeader);
1019 RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
1020 LibAmdMsrWrite (RegisterHdr->RegisterList[i].Address, &RegValueWrite, StdHeader);
1022 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
1023 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address,
1026 RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
1027 RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (RegisterHdr->RegisterList[i].Address,
1035 /*---------------------------------------------------------------------------------------*/
1037 * Restores the context of a 'conditional' MSR device.
1039 * This traverses the provided register list restoring MSRs when appropriate.
1041 * @param[in] StdHeader AMD standard header config param.
1042 * @param[in] Device 'conditional' MSR device to restore.
1043 * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or
1044 * AMD_S3LATE_RESTORE.
1045 * @param[in,out] OrMask Current buffer pointer of raw register values.
1049 RestoreConditionalMsrDevice (
1050 IN AMD_CONFIG_PARAMS *StdHeader,
1051 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
1052 IN CALL_POINTS CallPoint,
1053 IN OUT UINT64 **OrMask
1056 UINT8 SpecialCaseIndex;
1058 UINT64 RegValueRead;
1059 UINT64 RegValueWrite;
1060 CMSR_REGISTER_BLOCK_HEADER *RegisterHdr;
1062 if (CallPoint == INIT_RESUME) {
1063 MemFS3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
1065 S3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
1068 for (i = 0; i < RegisterHdr->NumRegisters; i++) {
1069 if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
1070 ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
1071 RegValueWrite = **OrMask;
1072 if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
1073 LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, &RegValueRead, StdHeader);
1074 RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
1075 LibAmdMsrWrite (RegisterHdr->RegisterList[i].Address, &RegValueWrite, StdHeader);
1077 SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
1078 RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address,
1081 RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
1082 RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (RegisterHdr->RegisterList[i].Address,
1091 /*---------------------------------------------------------------------------------------*/
1093 * Unique device ID to PCI register list translator.
1095 * This translates the given device header in storage to the appropriate list
1096 * of registers in the AGESA image.
1098 * @param[out] NonMemoryRelatedDeviceList List of devices to save and restore
1099 * during S3LateRestore.
1100 * @param[in] StdHeader AMD standard header config param.
1104 GetNonMemoryRelatedDeviceList (
1105 OUT DEVICE_BLOCK_HEADER **NonMemoryRelatedDeviceList,
1106 IN AMD_CONFIG_PARAMS *StdHeader
1109 *NonMemoryRelatedDeviceList = NULL;
1112 /*---------------------------------------------------------------------------------------*/
1114 * Unique device ID to PCI register list translator.
1116 * This translates the given device header in storage to the appropriate list
1117 * of registers in the AGESA image.
1119 * @param[in] Device Device header containing the unique ID.
1120 * @param[out] RegisterHdr Output PCI register list pointer.
1121 * @param[in] StdHeader AMD standard header config param.
1123 * @retval AGESA_SUCCESS Always succeeds.
1126 S3GetPciDeviceRegisterList (
1127 IN PCI_DEVICE_DESCRIPTOR *Device,
1128 OUT PCI_REGISTER_BLOCK_HEADER **RegisterHdr,
1129 IN AMD_CONFIG_PARAMS *StdHeader
1132 *RegisterHdr = NULL;
1133 return AGESA_SUCCESS;
1136 /*---------------------------------------------------------------------------------------*/
1138 * Unique device ID to 'conditional' PCI register list translator.
1140 * This translates the given device header in storage to the appropriate list
1141 * of registers in the AGESA image.
1143 * @param[in] Device Device header containing the unique ID.
1144 * @param[out] RegisterHdr Output 'conditional' PCI register list pointer.
1145 * @param[in] StdHeader AMD standard header config param.
1147 * @retval AGESA_SUCCESS Always succeeds.
1150 S3GetCPciDeviceRegisterList (
1151 IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
1152 OUT CPCI_REGISTER_BLOCK_HEADER **RegisterHdr,
1153 IN AMD_CONFIG_PARAMS *StdHeader
1156 *RegisterHdr = NULL;
1157 return AGESA_SUCCESS;
1161 /*---------------------------------------------------------------------------------------*/
1163 * Unique device ID to MSR register list translator.
1165 * This translates the given device header in storage to the appropriate list
1166 * of registers in the AGESA image.
1168 * @param[in] Device Device header containing the unique ID.
1169 * @param[out] RegisterHdr Output MSR register list pointer.
1170 * @param[in] StdHeader AMD standard header config param.
1172 * @retval AGESA_SUCCESS Always succeeds.
1175 S3GetMsrDeviceRegisterList (
1176 IN MSR_DEVICE_DESCRIPTOR *Device,
1177 OUT MSR_REGISTER_BLOCK_HEADER **RegisterHdr,
1178 IN AMD_CONFIG_PARAMS *StdHeader
1181 *RegisterHdr = NULL;
1182 return AGESA_SUCCESS;
1185 /*---------------------------------------------------------------------------------------*/
1187 * Unique device ID to 'conditional' MSR register list translator.
1189 * This translates the given device header in storage to the appropriate list
1190 * of registers in the AGESA image.
1192 * @param[in] Device Device header containing the unique ID.
1193 * @param[out] RegisterHdr Output 'conditional' MSR register list pointer.
1194 * @param[in] StdHeader AMD standard header config param.
1196 * @retval AGESA_SUCCESS Always succeeds.
1199 S3GetCMsrDeviceRegisterList (
1200 IN CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
1201 OUT CMSR_REGISTER_BLOCK_HEADER **RegisterHdr,
1202 IN AMD_CONFIG_PARAMS *StdHeader
1205 *RegisterHdr = NULL;
1206 return AGESA_SUCCESS;
1209 /*---------------------------------------------------------------------------------------*/
1211 * Constructor for the AMD_S3_PARAMS structure.
1213 * This routine initializes failsafe values for the AMD_S3_PARAMS structure
1214 * to be used by the AMD_INIT_RESUME, AMD_S3_SAVE, and AMD_S3LATE_RESTORE
1217 * @param[in,out] S3Params Required input parameter for the AMD_S3_SAVE,
1218 * AMD_INIT_RESUME, and AMD_S3_SAVE entry points.
1222 AmdS3ParamsInitializer (
1223 OUT AMD_S3_PARAMS *S3Params
1226 S3Params->Signature = 0x52545341;
1227 S3Params->Version = 0x0000;
1228 S3Params->VolatileStorage = NULL;
1229 S3Params->VolatileStorageSize = 0x00000000;
1230 S3Params->Flags = 0x00000000;
1231 S3Params->NvStorage = NULL;
1232 S3Params->NvStorageSize = 0x00000000;