summaryrefslogtreecommitdiffstats
path: root/QuarkPlatformPkg/Acpi/DxeSmm
diff options
context:
space:
mode:
authorMichael Kinney <michael.d.kinney@intel.com>2015-12-15 19:23:57 +0000
committermdkinney <mdkinney@Edk2>2015-12-15 19:23:57 +0000
commitb303605e1b7e113b4311daf161c6c3289350447b (patch)
tree67bf068eb99ea84822f234b7194ee1084ee5455a /QuarkPlatformPkg/Acpi/DxeSmm
parent9b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164 (diff)
downloadedk2-b303605e1b7e113b4311daf161c6c3289350447b.tar.gz
edk2-b303605e1b7e113b4311daf161c6c3289350447b.tar.bz2
edk2-b303605e1b7e113b4311daf161c6c3289350447b.zip
QuarkPlatformPkg: Add new package for Galileo boards
Changes for V4 ============== 1) Move delete of QuarkSocPkg\QuarkNorthCluster\Binary\QuarkMicrocode from QuarkPlatformPkg commit to QuarkSocPkg commit 2) Fix incorrect license header in PlatformSecLibModStrs.uni Changes for V3 ============== 1) Set PcdResetOnMemoryTypeInformationChange FALSE in QuarkMin.dsc This is required because QuarkMin.dsc uses the emulated variable driver that does not preserve any non-volatile UEFI variables across reset. If the condition is met where the memory type information variable needs to be updated, then the system will reset every time the UEFI Shell is run. By setting this PCD to FALSE, then reset action is disabled. 2) Move one binary file to QuarkSocBinPkg 3) Change RMU.bin FILE statements to INF statement in DSC FD region to be compatible with PACKAGES_PATH search for QuarkSocBinPkg Changes for V2 ============== 1) Use new generic PCI serial driver PciSioSerialDxe in MdeModulePkg 2) Configure PcdPciSerialParameters for PCI serial driver for Quark 3) Use new MtrrLib API to reduce time to set MTRRs for all DRAM 4) Convert all UNI files to utf-8 5) Replace tabs with spaces and remove trailing spaces 6) Add License.txt Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Michael Kinney <michael.d.kinney@intel.com> Acked-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19287 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'QuarkPlatformPkg/Acpi/DxeSmm')
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c1017
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h173
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf84
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c390
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h156
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c119
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h58
-rw-r--r--QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf80
8 files changed, 2077 insertions, 0 deletions
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c
new file mode 100644
index 0000000000..321cf620eb
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c
@@ -0,0 +1,1017 @@
+/** @file
+ACPISMM Driver implementation file.
+
+This is QNC Smm platform driver
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#include <AcpiSmmPlatform.h>
+
+#define PCILIB_TO_COMMON_ADDRESS(Address) \
+ ((UINT64) ((((UINTN) ((Address>>20) & 0xff)) << 24) + (((UINTN) ((Address>>15) & 0x1f)) << 16) + (((UINTN) ((Address>>12) & 0x07)) << 8) + ((UINTN) (Address & 0xfff ))))
+
+//
+// Modular variables needed by this driver
+//
+EFI_ACPI_SMM_DEV mAcpiSmm;
+
+UINT8 mPciCfgRegTable[] = {
+ //
+ // Logic to decode the table masks to arrive at the registers saved
+ // Dword Registers are saved. For a given mask, the Base+offset register
+ // will be saved as in the table below.
+ // (example) To save register 0x24, 0x28 the mask at the Base 0x20 will be 0x06
+ // Base 0x00 0x20 0x40 0x60 0x80 0xA0 0xC0 0xE0
+ // Mask offset
+ // 0x01 0x00
+ // 0x02 0x04
+ // 0x04 0x08
+ // 0x08 0x0C
+ // 0x10 0x10
+ // 0x20 0x14
+ // 0x40 0x18
+ // 0x80 0x1C
+ //
+
+ //
+ // Bus, Dev, Func,
+ // 00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
+ // Only Bus 0 device is supported now
+ //
+
+ //
+ // Quark South Cluster devices
+ //
+ PCI_DEVICE (0, 20, 0),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 1),
+ PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 2),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 3),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00),
+
+ PCI_DEVICE (0, 20, 4),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 5),
+ PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 6),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 20, 7),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 21, 0),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 21, 1),
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 21, 2),
+ PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ //
+ // Quark North Cluster devices
+ //
+ PCI_DEVICE (0, 0, 0),
+ PCI_REG_MASK (0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 23, 0),
+ PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 23, 1),
+ PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),
+
+ PCI_DEVICE (0, 31, 0),
+ PCI_REG_MASK (0x00, 0x08, 0x4E, 0x03, 0x02, 0x00, 0x60, 0x10),
+
+ PCI_DEVICE_END
+};
+
+EFI_PLATFORM_TYPE mPlatformType;
+
+ // These registers have to set in byte order
+const UINT8 QNCS3SaveExtReg[] = {
+ QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, // SMRAM settings
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXH,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXRM,
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM,
+
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_END_MEM_REG, // ECC Scrub settings
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_START_MEM_REG,
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_NEXT_READ_REG,
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG,
+
+ 0xFF
+ };
+
+/**
+ Allocate EfiACPIMemoryNVS below 4G memory address.
+
+ This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+ @param Size Size of memory to allocate.
+
+ @return Allocated address for output.
+
+**/
+VOID*
+AllocateAcpiNvsMemoryBelow4G (
+ IN UINTN Size
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+ VOID* Buffer;
+
+ Pages = EFI_SIZE_TO_PAGES (Size);
+ Address = 0xffffffff;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &Address
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Buffer = (VOID *) (UINTN) Address;
+ ZeroMem (Buffer, Size);
+
+ return Buffer;
+}
+
+EFI_STATUS
+EFIAPI
+ReservedS3Memory (
+ UINTN SystemMemoryLength
+
+ )
+/*++
+
+Routine Description:
+
+ Reserved S3 memory for InstallS3Memory
+
+Arguments:
+
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.
+ EFI_SUCCESS - Function has completed successfully.
+
+--*/
+{
+
+ VOID *GuidHob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
+ VOID *AcpiReservedBase;
+
+ UINTN TsegIndex;
+ UINTN TsegSize;
+ UINTN TsegBase;
+ RESERVED_ACPI_S3_RANGE *AcpiS3Range;
+ //
+ // Get Hob list for SMRAM desc
+ //
+ GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
+ ASSERT (GuidHob);
+ DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (DescriptorBlock);
+
+ //
+ // Use the hob to get SMRAM capabilities
+ //
+ TsegIndex = DescriptorBlock->NumberOfSmmReservedRegions - 1;
+ ASSERT (TsegIndex <= (MAX_SMRAM_RANGES - 1));
+ TsegBase = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalStart;
+ TsegSize = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalSize;
+
+ DEBUG ((EFI_D_INFO, "SMM Base: %08X\n", TsegBase));
+ DEBUG ((EFI_D_INFO, "SMM Size: %08X\n", TsegSize));
+
+ //
+ // Now find the location of the data structure that is used to store the address
+ // of the S3 reserved memory.
+ //
+ AcpiS3Range = (RESERVED_ACPI_S3_RANGE*) (UINTN) (TsegBase + RESERVED_ACPI_S3_RANGE_OFFSET);
+
+ //
+ // Allocate reserved ACPI memory for S3 resume. Pointer to this region is
+ // stored in SMRAM in the first page of TSEG.
+ //
+ AcpiReservedBase = AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize));
+ if (AcpiReservedBase != NULL) {
+ AcpiS3Range->AcpiReservedMemoryBase = (UINT32)(UINTN) AcpiReservedBase;
+ AcpiS3Range->AcpiReservedMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);
+ }
+ AcpiS3Range->SystemMemoryLength = (UINT32)SystemMemoryLength;
+
+ DEBUG ((EFI_D_INFO, "S3 Memory Base: %08X\n", AcpiS3Range->AcpiReservedMemoryBase));
+ DEBUG ((EFI_D_INFO, "S3 Memory Size: %08X\n", AcpiS3Range->AcpiReservedMemorySize));
+ DEBUG ((EFI_D_INFO, "S3 SysMemoryLength: %08X\n", AcpiS3Range->SystemMemoryLength));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+InitAcpiSmmPlatform (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initializes the SMM S3 Handler Driver.
+
+Arguments:
+
+ ImageHandle - The image handle of Sleep State Wake driver.
+ SystemTable - The starndard EFI system table.
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.
+ EFI_SUCCESS - Function has completed successfully.
+ Other - Error occured during execution.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *AcpiNvsProtocol = NULL;
+ UINTN MemoryLength;
+ EFI_PEI_HOB_POINTERS Hob;
+
+ Status = gBS->LocateProtocol (
+ &gEfiGlobalNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &AcpiNvsProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mAcpiSmm.BootScriptSaved = 0;
+
+ mPlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);
+
+ //
+ // Calculate the system memory length by memory hobs
+ //
+ MemoryLength = 0x100000;
+ Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+ ASSERT (Hob.Raw != NULL);
+ while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {
+ if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ //
+ // Skip the memory region below 1MB
+ //
+ if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {
+ MemoryLength += (UINTN)Hob.ResourceDescriptor->ResourceLength;
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
+ }
+
+ ReservedS3Memory(MemoryLength);
+
+ //
+ // Locate and Register to Parent driver
+ //
+ Status = RegisterToDispatchDriver ();
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RegisterToDispatchDriver (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Register to dispatch driver.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - Successfully init the device.
+ Other - Error occured whening calling Dxe lib functions.
+
+--*/
+{
+ UINTN Length;
+ EFI_STATUS Status;
+ EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryDispatchContext;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS1DispatchContext;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS3DispatchContext;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS4DispatchContext;
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS5DispatchContext;
+ EFI_SMM_SW_REGISTER_CONTEXT *SwContext;
+ EFI_SMM_SW_REGISTER_CONTEXT *AcpiDisableSwContext;
+ EFI_SMM_SW_REGISTER_CONTEXT *AcpiEnableSwContext;
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &SxDispatch
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &SwDispatch
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Length = sizeof (EFI_SMM_SX_REGISTER_CONTEXT) * 4 + sizeof (EFI_SMM_SW_REGISTER_CONTEXT) * 2;
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ Length,
+ (VOID **) &EntryDispatchContext
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SetMem (EntryDispatchContext, Length, 0);
+
+ EntryS1DispatchContext = EntryDispatchContext++;
+ EntryS3DispatchContext = EntryDispatchContext++;
+ EntryS4DispatchContext = EntryDispatchContext++;
+ EntryS5DispatchContext = EntryDispatchContext++;
+
+ SwContext = (EFI_SMM_SW_REGISTER_CONTEXT *)EntryDispatchContext;
+ AcpiDisableSwContext = SwContext++;
+ AcpiEnableSwContext = SwContext++;
+
+ //
+ // Register the enable handler
+ //
+ AcpiEnableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_ENABLE;
+ Status = SwDispatch->Register (
+ SwDispatch,
+ EnableAcpiCallback,
+ AcpiEnableSwContext,
+ &(mAcpiSmm.DisableAcpiHandle)
+ );
+
+ //
+ // Register the disable handler
+ //
+ AcpiDisableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_DISABLE;
+ Status = SwDispatch->Register (
+ SwDispatch,
+ DisableAcpiCallback,
+ AcpiDisableSwContext,
+ &(mAcpiSmm.EnableAcpiHandle)
+ );
+
+
+ //
+ // Register entry phase call back function for S1
+ //
+ EntryS1DispatchContext->Type = SxS1;
+ EntryS1DispatchContext->Phase = SxEntry;
+ Status = SxDispatch->Register (
+ SxDispatch,
+ SxSleepEntryCallBack,
+ EntryS1DispatchContext,
+ &(mAcpiSmm.S1SleepEntryHandle)
+ );
+
+ //
+ // Register entry phase call back function
+ //
+ EntryS3DispatchContext->Type = SxS3;
+ EntryS3DispatchContext->Phase = SxEntry;
+ Status = SxDispatch->Register (
+ SxDispatch,
+ SxSleepEntryCallBack,
+ EntryS3DispatchContext,
+ &(mAcpiSmm.S3SleepEntryHandle)
+ );
+
+ //
+ // Register entry phase call back function for S4
+ //
+ EntryS4DispatchContext->Type = SxS4;
+ EntryS4DispatchContext->Phase = SxEntry;
+ Status = SxDispatch->Register (
+ SxDispatch,
+ SxSleepEntryCallBack,
+ EntryS4DispatchContext,
+ &(mAcpiSmm.S4SleepEntryHandle)
+ );
+
+ //
+ // Register callback for S5 in order to workaround the LAN shutdown issue
+ //
+ EntryS5DispatchContext->Type = SxS5;
+ EntryS5DispatchContext->Phase = SxEntry;
+ Status = SxDispatch->Register (
+ SxDispatch,
+ SxSleepEntryCallBack,
+ EntryS5DispatchContext,
+ &(mAcpiSmm.S5SoftOffEntryHandle)
+ );
+
+ return Status;
+}
+
+
+EFI_STATUS
+RestoreQncS3SwCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+/*++
+
+Routine Description:
+ SMI handler to retore QncS3 code & context for S3 path
+ This will be only triggered when BootScript got executed during resume
+
+Arguments:
+ DispatchHandle - EFI Handle
+ DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+Returns:
+ Nothing
+
+--*/
+{
+ //
+ // Restore to original address by default
+ //
+ RestoreLockBox(&gQncS3CodeInLockBoxGuid, NULL, NULL);
+ RestoreLockBox(&gQncS3ContextInLockBoxGuid, NULL, NULL);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DisableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+/*++
+
+Routine Description:
+ SMI handler to disable ACPI mode
+
+ Dispatched on reads from APM port with value 0xA1
+
+ ACPI events are disabled and ACPI event status is cleared.
+ SCI mode is then disabled.
+ Clear all ACPI event status and disable all ACPI events
+ Disable PM sources except power button
+ Clear status bits
+ Disable GPE0 sources
+ Clear status bits
+ Disable GPE1 sources
+ Clear status bits
+ Disable SCI
+
+Arguments:
+ DispatchHandle - EFI Handle
+ DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+Returns:
+ Nothing
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 Pm1Cnt;
+
+ Status = GetAllQncPmBase (gSmst);
+ ASSERT_EFI_ERROR (Status);
+ Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);
+
+ //
+ // Disable SCI
+ //
+ Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SCIEN;
+
+ IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EnableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+/*++
+
+Routine Description:
+ SMI handler to enable ACPI mode
+
+ Dispatched on reads from APM port with value 0xA0
+
+ Disables the SW SMI Timer.
+ ACPI events are disabled and ACPI event status is cleared.
+ SCI mode is then enabled.
+
+ Disable SW SMI Timer
+
+ Clear all ACPI event status and disable all ACPI events
+ Disable PM sources except power button
+ Clear status bits
+
+ Disable GPE0 sources
+ Clear status bits
+
+ Disable GPE1 sources
+ Clear status bits
+
+ Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
+
+ Enable SCI
+
+Arguments:
+ DispatchHandle - EFI Handle
+ DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+Returns:
+ Nothing
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 SmiEn;
+ UINT16 Pm1Cnt;
+ UINT8 Data8;
+
+ Status = GetAllQncPmBase (gSmst);
+ ASSERT_EFI_ERROR (Status);
+
+ SmiEn = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);
+
+ //
+ // Disable SW SMI Timer
+ //
+ SmiEn &= ~(B_QNC_GPE0BLK_SMIE_SWT);
+ IoWrite32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE, SmiEn);
+
+ //
+ // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
+ //
+ Data8 = RTC_ADDRESS_REGISTER_D;
+ IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);
+ Data8 = 0x0;
+ IoWrite8 (R_IOPORT_CMOS_STANDARD_DATA, Data8);
+
+ //
+ // Enable SCI
+ //
+ Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);
+ Pm1Cnt |= B_QNC_PM1BLK_PM1C_SCIEN;
+ IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);
+
+ //
+ // Do platform specific stuff for ACPI enable SMI
+ //
+
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SxSleepEntryCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+/*++
+
+Routine Description:
+
+ Callback function entry for Sx sleep state.
+
+Arguments:
+
+ DispatchHandle - The handle of this callback, obtained when registering.
+ DispatchContext - The predefined context which contained sleep type and phase.
+
+Returns:
+
+ EFI_SUCCESS - Operation successfully performed.
+ EFI_INVALID_PARAMETER - Invalid parameter passed in.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 Data8;
+ UINT16 Data16;
+ UINT32 Data32;
+
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeS3SuspendStart));
+
+ //
+ // Reget QNC power mgmr regs base in case of OS changing it at runtime
+ //
+ Status = GetAllQncPmBase (gSmst);
+
+ //
+ // Clear RTC Alarm (if set)
+ //
+ Data8 = RTC_ADDRESS_REGISTER_C;
+ IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);
+ Data8 = IoRead8 (R_IOPORT_CMOS_STANDARD_DATA);
+
+ //
+ // Clear all ACPI status bits
+ //
+ Data32 = B_QNC_GPE0BLK_GPE0S_ALL;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0S, 1, &Data32 );
+ Data16 = B_QNC_PM1BLK_PM1S_ALL;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1S, 1, &Data16 );
+
+ //
+ // Handling S1 - setting appropriate wake bits in GPE0_EN
+ //
+ if ((DispatchHandle == mAcpiSmm.S1SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS1)) {
+ //
+ // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+ Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+
+ //
+ // Enable bit10 (RTC) in PM1E
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+ Data16 |= B_QNC_PM1BLK_PM1E_RTC;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Handling S4, S5 and WOL - setting appropriate wake bits in GPE0_EN
+ //
+ if (((DispatchHandle == mAcpiSmm.S4SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS4)) ||
+ ((DispatchHandle == mAcpiSmm.S5SoftOffEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS5))
+ ) {
+ //
+ // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN
+ // Enable the WOL bits in GPE0_EN reg here for PME
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+ Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+
+ //
+ // Enable bit10 (RTC) in PM1E
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+ Data16 |= B_QNC_PM1BLK_PM1E_RTC;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+
+ } else {
+
+ if ((DispatchHandle != mAcpiSmm.S3SleepEntryHandle) || (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type != SxS3)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = SaveRuntimeScriptTable (gSmst);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Enable bit13 (EGPE), 14 (GPIO), 17 (PCIE) in GPE0_EN
+ // Enable the WOL bits in GPE0_EN reg here for PME
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+ Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );
+
+ //
+ // Enable bit10 (RTC) in PM1E
+ //
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+ Data16 |= B_QNC_PM1BLK_PM1E_RTC;
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );
+ }
+
+ //
+ // When entering a power-managed state like S3,
+ // PERST# must be asserted in advance of power-off.
+ //
+ PlatformPERSTAssert (mPlatformType);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetAllQncPmBase (
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst
+ )
+/*++
+
+Routine Description:
+
+ Get QNC chipset LPC Power Management I/O Base at runtime.
+
+Arguments:
+
+ Smst - The standard SMM system table.
+
+Returns:
+
+ EFI_SUCCESS - Successfully init the device.
+ Other - Error occured whening calling Dxe lib functions.
+
+--*/
+{
+ mAcpiSmm.QncPmBase = PciRead16 (PCI_LIB_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, R_QNC_LPC_PM1BLK)) & B_QNC_LPC_PM1BLK_MASK;
+ mAcpiSmm.QncGpe0Base = PciRead16 (PCI_LIB_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, R_QNC_LPC_GPE0BLK)) & B_QNC_LPC_GPE0BLK_MASK;
+
+ //
+ // Quark does not support Changing Primary SoC IOBARs from what was
+ // setup in SEC/PEI UEFI stages.
+ //
+ ASSERT (mAcpiSmm.QncPmBase == (UINT32) PcdGet16 (PcdPm1blkIoBaseAddress));
+ ASSERT (mAcpiSmm.QncGpe0Base == (UINT32) PcdGet16 (PcdGpe0blkIoBaseAddress));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SaveRuntimeScriptTable (
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst
+ )
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
+ UINT32 Data32;
+ UINT16 Data16;
+ UINT8 Mask;
+ UINTN Index;
+ UINTN Offset;
+ UINT16 DeviceId;
+
+ //
+ // Check what Soc we are running on (read Host bridge DeviceId)
+ //
+ DeviceId = QncGetSocDeviceId();
+
+ //
+ // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
+ // and vital to S3 resume. That's why we put save code here
+ //
+ Index = 0;
+ while (mPciCfgRegTable[Index] != PCI_DEVICE_END) {
+
+ PciAddress.Bus = mPciCfgRegTable[Index++];
+ PciAddress.Device = mPciCfgRegTable[Index++];
+ PciAddress.Function = mPciCfgRegTable[Index++];
+ PciAddress.Register = 0;
+ PciAddress.ExtendedRegister = 0;
+
+ Data16 = PciRead16 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));
+ if (Data16 == 0xFFFF) {
+ Index += 8;
+ continue;
+ }
+
+ for (Offset = 0, Mask = 0x01; Offset < 256; Offset += 4, Mask <<= 1) {
+
+ if (Mask == 0x00) {
+ Mask = 0x01;
+ }
+
+ if (mPciCfgRegTable[Index + Offset / 32] & Mask) {
+
+ PciAddress.Register = (UINT8) Offset;
+ Data32 = PciRead32 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));
+
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)),
+ 1,
+ &Data32
+ );
+ }
+ }
+
+ Index += 8;
+
+ }
+
+ //
+ // Save message bus registers
+ //
+ Index = 0;
+ while (QNCS3SaveExtReg[Index] != 0xFF) {
+ Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ //
+ // Save IMR settings with IMR protection disabled initially
+ // HMBOUND and IMRs will be locked just before jumping to the OS waking vector
+ //
+ if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {
+ if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {
+ Data32 &= ~IMR_LOCK;
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {
+ Data32 &= ~IMR_EN;
+ }
+ }
+ if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {
+ Data32 = (UINT32)IMRX_ALL_ACCESS;
+ }
+ }
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
+ 1,
+ &Data32
+ );
+
+ Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+ 1,
+ &Data32
+ );
+ Index += 2;
+ }
+
+ Index = 0;
+ while (QNCS3SaveExtReg[Index] != 0xFF) {
+ //
+ // Save IMR settings with IMR protection enabled (above script was to handle restoring all settings first - now we want to enable)
+ //
+ if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {
+ if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {
+ Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+ Data32 &= ~IMR_LOCK;
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
+ 1,
+ &Data32
+ );
+
+ Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+ 1,
+ &Data32
+ );
+ }
+ } else {
+ if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {
+ Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ //
+ // Save latest settings to runtime script table
+ //
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
+ 1,
+ &Data32
+ );
+
+ Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
+
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+ 1,
+ &Data32
+ );
+ }
+ }
+ }
+ Index += 2;
+ }
+
+ // Check if ECC scrub enabled and need re-enabling on resume
+ // All scrub related configuration registers are saved on suspend
+ // as part of QNCS3SaveExtReg configuration table script.
+ // The code below extends the S3 resume script with scrub reactivation
+ // message (if needed only)
+ Data32 = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG);
+ if( 0 != (Data32 & SCRUB_CFG_ACTIVE)) {
+
+ Data32 = SCRUB_RESUME_MSG();
+
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
+ 1,
+ &Data32
+ );
+ }
+
+ //
+ // Save I/O ports to S3 script table
+ //
+
+ //
+ // Important to trap Sx for SMM
+ //
+ Data32 = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);
+ S3BootScriptSaveIoWrite(S3BootScriptWidthUint32, (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE), 1, &Data32);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h
new file mode 100644
index 0000000000..fef1fd05c4
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.h
@@ -0,0 +1,173 @@
+/** @file
+Header file for SMM S3 Handler Driver.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#ifndef _ACPI_SMM_DRIVER_H
+#define _ACPI_SMM_DRIVER_H
+//
+// Include files
+//
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/FirmwareVolume.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Protocol/Spi.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/S3IoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Guid/Acpi.h>
+#include <Guid/GlobalVariable.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/HobLib.h>
+#include <QNCAccess.h>
+#include <Library/QNCAccessLib.h>
+#include <Library/IntelQNCLib.h>
+#include <Library/PlatformHelperLib.h>
+#include <Library/PlatformPcieHelperLib.h>
+#include "Platform.h"
+#include <IndustryStandard/Pci22.h>
+
+#define EFI_ACPI_ACPI_ENABLE 0xA0
+#define EFI_ACPI_ACPI_DISABLE 0xA1
+
+#define R_IOPORT_CMOS_STANDARD_INDEX 0x70
+#define R_IOPORT_CMOS_STANDARD_DATA 0x71
+#define RTC_ADDRESS_REGISTER_C 12
+#define RTC_ADDRESS_REGISTER_D 13
+
+#define PCI_DEVICE(Bus, Dev, Func) \
+ Bus, Dev, Func
+
+#define PCI_REG_MASK(Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7) \
+ Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7
+
+#define PCI_DEVICE_END 0xFF
+
+//
+// Related data structures definition
+//
+typedef struct _EFI_ACPI_SMM_DEV {
+
+ //
+ // Parent dispatch driver returned sleep handle
+ //
+ EFI_HANDLE S3SleepEntryHandle;
+
+ EFI_HANDLE S4SleepEntryHandle;
+
+ EFI_HANDLE S1SleepEntryHandle;
+
+ EFI_HANDLE S5SoftOffEntryHandle;
+
+ EFI_HANDLE EnableAcpiHandle;
+
+ EFI_HANDLE DisableAcpiHandle;
+
+ EFI_HANDLE PpCallbackHandle;
+
+ EFI_HANDLE MorCallbackHandle;
+
+ //
+ // QNC Power Management I/O register base
+ //
+ UINT32 QncPmBase;
+
+ //
+ // QNC General Purpose Event0 register base
+ //
+ UINT32 QncGpe0Base;
+
+ UINT32 BootScriptSaved;
+
+} EFI_ACPI_SMM_DEV;
+
+//
+// Prototypes
+//
+EFI_STATUS
+InitPlatformAcpiSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+EFI_STATUS
+SxSleepEntryCallBack (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+EFI_STATUS
+DisableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+EFI_STATUS
+EnableAcpiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+EFI_STATUS
+RegisterToDispatchDriver (
+ VOID
+ );
+
+EFI_STATUS
+GetAllQncPmBase (
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst
+ );
+
+EFI_STATUS
+SaveRuntimeScriptTable (
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst
+ );
+
+EFI_STATUS
+RestoreQncS3SwCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *DispatchContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+extern EFI_GUID gQncS3CodeInLockBoxGuid;
+extern EFI_GUID gQncS3ContextInLockBoxGuid;
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf
new file mode 100644
index 0000000000..a3e8f36517
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.inf
@@ -0,0 +1,84 @@
+## @file
+# Component description file for ACPI SMM Platform handler module
+#
+# This is QNC Smm platform driver .
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiSmmPlatform
+ FILE_GUID = F5AC7057-5650-466e-B692-76A47223EFB0
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = InitAcpiSmmPlatform
+
+[Sources]
+ AcpiSmmPlatform.c
+ AcpiSmmPlatform.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ ReportStatusCodeLib
+ UefiDriverEntryPoint
+ DebugLib
+ IoLib
+ PciLib
+ BaseMemoryLib
+ BaseLib
+ SmmServicesTableLib
+ PcdLib
+ HobLib
+ S3BootScriptLib
+ LockBoxLib
+ PlatformHelperLib
+ IntelQNCLib
+ PlatformPcieHelperLib
+
+[Protocols]
+ gEfiSmmSxDispatch2ProtocolGuid
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiVariableArchProtocolGuid
+ gEfiVariableWriteArchProtocolGuid
+ gEfiGlobalNvsAreaProtocolGuid
+ gEfiSmmSwDispatch2ProtocolGuid
+
+[Guids]
+ gEfiSmmPeiSmramMemoryReserveGuid
+ gQncS3CodeInLockBoxGuid
+ gQncS3ContextInLockBoxGuid
+
+[Pcd]
+ gQuarkPlatformTokenSpaceGuid.PcdPlatformType
+ gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
+
+[Depex]
+ gEfiSmmSxDispatch2ProtocolGuid AND
+ gEfiPciRootBridgeIoProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiGlobalNvsAreaProtocolGuid AND
+ gEfiQncS3SupportProtocolGuid
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c
new file mode 100644
index 0000000000..8f5e6a324c
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.c
@@ -0,0 +1,390 @@
+/** @file
+
+Processor power management initialization code.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#include "SmmPowerManagement.h"
+
+//
+// Global variables
+//
+extern EFI_ACPI_SDT_PROTOCOL *mAcpiSdt;
+extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
+
+extern EFI_GUID gPowerManagementAcpiTableStorageGuid;
+
+/**
+ This function is the entry of processor power management initialization code.
+ It initializes the processor's power management features based on the user
+ configurations and hardware capabilities.
+**/
+VOID
+PpmInit (
+ VOID
+ )
+{
+ //
+ // Processor Power Management Flags
+ //
+ mGlobalNvsAreaPtr->Cfgd = PcdGet32(PcdPpmFlags);
+
+ //
+ // Patch and publish power management related acpi tables
+ //
+ PpmPatchAndPublishAcpiTables();
+}
+
+/**
+ This function is to patch and publish power management related acpi tables.
+**/
+VOID
+PpmPatchAndPublishAcpiTables (
+ VOID
+ )
+{
+ //
+ // Patch FADT table to enable C2,C3
+ //
+ PpmPatchFadtTable();
+
+ //
+ // Load all the power management acpi tables and patch IST table
+ //
+ PpmLoadAndPatchPMTables();
+}
+
+/**
+ This function is to patch PLvl2Lat and PLvl3Lat to enable C2, C3 support in OS.
+**/
+VOID
+PpmPatchFadtTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ EFI_ACPI_SDT_HEADER *CurrentTable;
+ EFI_ACPI_TABLE_VERSION Version;
+ UINTN Index;
+ UINTN Handle;
+ EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtPointer;
+
+ //
+ // Scan all the acpi tables to find FADT 2.0
+ //
+ Index = 0;
+ do {
+ Status = mAcpiSdt->GetAcpiTable (
+ Index,
+ &CurrentTable,
+ &Version,
+ &Handle
+ );
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while (CurrentTable->Signature != EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE || CurrentTable->Revision != 0x03);
+
+ ASSERT (CurrentTable->Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);
+
+ Table = NULL;
+ Status = gBS->AllocatePool (EfiBootServicesData, CurrentTable->Length, (VOID **) &Table);
+ ASSERT (Table != NULL);
+ CopyMem (Table, CurrentTable, CurrentTable->Length);
+
+ FadtPointer = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE*) Table;
+
+ //
+ // Update the ACPI table and recalculate checksum
+ //
+ Status = mAcpiTable->UninstallAcpiTable (mAcpiTable, Handle);
+ if (EFI_ERROR (Status)) {
+ //
+ // Should not get an error here ever, but abort if we do.
+ //
+ return ;
+ }
+
+ //
+ // Update the check sum
+ // It needs to be zeroed before the checksum calculation
+ //
+ ((EFI_ACPI_SDT_HEADER *)Table)->Checksum = 0;
+ ((EFI_ACPI_SDT_HEADER *)Table)->Checksum =
+ CalculateCheckSum8 ((VOID *)Table, Table->Length);
+
+ //
+ // Add the table
+ //
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ Table,
+ Table->Length,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ gBS->FreePool (Table);
+}
+
+VOID
+SsdtTableUpdate (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader
+ )
+/*++
+
+ Routine Description:
+
+ Update the SSDT table
+
+ Arguments:
+
+ Table - The SSDT table to be patched
+
+ Returns:
+
+ None
+
+--*/
+{
+ UINT8 *CurrPtr;
+ UINT8 *SsdtPointer;
+ UINT32 *Signature;
+
+ //
+ // Loop through the ASL looking for values that we must fix up.
+ //
+ CurrPtr = (UINT8 *) TableHeader;
+ for (SsdtPointer = CurrPtr;
+ SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
+ SsdtPointer++
+ )
+ {
+ Signature = (UINT32 *) SsdtPointer;
+ if ((*Signature) == SIGNATURE_32 ('P', 'M', 'B', 'A')) {
+ switch (*(Signature+1)) {
+ case (SIGNATURE_32 ('L', 'V', 'L', '0')):
+ Signature[0] = PcdGet16(PcdPmbaIoBaseAddress);
+ Signature[1] = 0;
+ break;
+ case (SIGNATURE_32 ('L', 'V', 'L', '2')):
+ Signature[0] = PcdGet16(PcdPmbaIoLVL2);
+ Signature[1] = 0;
+ break;
+ }
+ }
+ }
+}
+
+EFI_STATUS
+LocateSupportProtocol (
+ IN EFI_GUID *Protocol,
+ OUT VOID **Instance,
+ IN UINT32 Type
+ )
+/*++
+
+Routine Description:
+
+ Locate the first instance of a protocol. If the protocol requested is an
+ FV protocol, then it will return the first FV that contains the ACPI table
+ storage file.
+
+Arguments:
+
+ Protocol The protocol to find.
+ Instance Return pointer to the first instance of the protocol
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_NOT_FOUND The protocol could not be located.
+ EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN i;
+
+ FvStatus = 0;
+
+ //
+ // Locate protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Protocol,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+
+ //
+ // Defined errors at this time are not found and out of resources.
+ //
+ return Status;
+ }
+
+
+
+ //
+ // Looking for FV with ACPI storage file
+ //
+
+ for (i = 0; i < NumberOfHandles; i++) {
+ //
+ // Get the protocol on this handle
+ // This should not fail because of LocateHandleBuffer
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[i],
+ Protocol,
+ Instance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!Type) {
+ //
+ // Not looking for the FV protocol, so find the first instance of the
+ // protocol. There should not be any errors because our handle buffer
+ // should always contain at least one or LocateHandleBuffer would have
+ // returned not found.
+ //
+ break;
+ }
+
+ //
+ // See if it has the ACPI storage file
+ //
+
+ Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL*) (*Instance))->ReadFile (*Instance,
+ &gPowerManagementAcpiTableStorageGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ //
+ // If we found it, then we are done
+ //
+ if (Status == EFI_SUCCESS) {
+ break;
+ }
+ }
+
+ //
+ // Our exit status is determined by the success of the previous operations
+ // If the protocol was found, Instance already points to it.
+ //
+
+ //
+ // Free any allocated buffers
+ //
+ gBS->FreePool (HandleBuffer);
+
+ return Status;
+}
+
+/**
+ This function is to load all the power management acpi tables and patch IST table.
+**/
+VOID
+PpmLoadAndPatchPMTables (
+ VOID
+ )
+{
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ EFI_STATUS Status;
+ INTN Instance;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN TableHandle;
+ UINT32 FvStatus;
+ UINTN Size;
+ EFI_ACPI_TABLE_VERSION Version;
+
+ Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Read tables from the storage file.
+ //
+ Instance = 0;
+ CurrentTable = NULL;
+
+ while (Status == EFI_SUCCESS) {
+
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gPowerManagementAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID**)&CurrentTable,
+ &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR(Status)) {
+ Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+
+ if(((EFI_ACPI_DESCRIPTION_HEADER*) CurrentTable)->OemTableId == SIGNATURE_64 ('C', 'p', 'u', '0', 'I', 's', 't', 0)) {
+ Version = EFI_ACPI_TABLE_VERSION_NONE;
+ } else if(((EFI_ACPI_DESCRIPTION_HEADER*) CurrentTable)->OemTableId == SIGNATURE_64 ('C', 'p', 'u', '1', 'I', 's', 't', 0)) {
+ Version = EFI_ACPI_TABLE_VERSION_NONE;
+ }
+
+ SsdtTableUpdate ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable);
+
+ //
+ // Update the check sum
+ // It needs to be zeroed before the checksum calculation
+ //
+ ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
+ ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = (UINT8)
+ CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
+
+ //
+ // Add the table
+ //
+ TableHandle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ CurrentTable,
+ CurrentTable->Length,
+ &TableHandle
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Increment the instance
+ //
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+
+}
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h
new file mode 100644
index 0000000000..419e7ce028
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/Ppm.h
@@ -0,0 +1,156 @@
+/** @file
+
+Processor power management initialization code.
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#ifndef _PPM_H
+#define _PPM_H
+
+//
+// Bit definitions of PPMFlags
+//
+#define PPM_GV3 (1 << 0) // Geyserville 3
+#define PPM_TURBO (1 << 1) // Turbo Mode
+#define PPM_SUPER_LFM (1 << 2) // N/2 Ratio
+#define PPM_C1 (1 << 4) // C1 Capable, Enabled
+#define PPM_C2 (1 << 5) // C2 Capable, Enabled
+#define PPM_C3 (1 << 6) // C3 Capable, Enabled
+#define PPM_C4 (1 << 7) // C4 Capable, Enabled
+#define PPM_C5 (1 << 8) // C5/Deep C4 Capable, Enabled
+#define PPM_C6 (1 << 9) // C6 Capable, Enabled
+#define PPM_C1E (1 << 10) // C1E Enabled
+#define PPM_C2E (1 << 11) // C2E Enabled
+#define PPM_C3E (1 << 12) // C3E Enabled
+#define PPM_C4E (1 << 13) // C4E Enabled
+#define PPM_HARD_C4E (1 << 14) // Hard C4E Capable, Enabled
+#define PPM_TM1 (1 << 16) // Thermal Monitor 1
+#define PPM_TM2 (1 << 17) // Thermal Monitor 2
+#define PPM_PHOT (1 << 19) // Bi-directional ProcHot
+#define PPM_MWAIT_EXT (1 << 21) // MWAIT extensions supported
+#define PPM_CMP (1 << 24) // CMP supported, Enabled
+#define PPM_TSTATE (1 << 28) // CPU T states supported
+
+#define PPM_C_STATES (PPM_C1 + PPM_C2 + PPM_C3 + PPM_C4 + PPM_C5 + PPM_C6)
+#define PPM_CE_STATES (PPM_C1E + PPM_C2E + PPM_C3E + PPM_C4E + PPM_HARD_C4E)
+
+
+#define MAX_P_STATES_NUM 12
+
+#define AML_NAME_OP 0x08
+#define AML_SCOPE_OP 0x10
+#define AML_PACKAGE_OP 0x12
+#define AML_METHOD_OP 0x14
+
+#define S3_CPU_REGISTER_TABLE_GUID \
+ { \
+ 0xc4ef988d, 0xe5e, 0x4403, { 0xbe, 0xeb, 0xf1, 0xbb, 0x6, 0x79, 0x6e, 0xdf } \
+ }
+
+#pragma pack(1)
+typedef struct {
+ UINT8 StartByte;
+ UINT32 NameStr;
+ UINT8 OpCode;
+ UINT16 Size; // Hardcode to 16bit width because the table we use is fixed size
+ UINT8 NumEntries;
+} EFI_ACPI_NAME_COMMAND;
+
+typedef struct {
+ UINT8 PackageOp;
+ UINT8 PkgLeadByte;
+ UINT8 NumEntries;
+ UINT8 DwordPrefix0;
+ UINT32 CoreFreq;
+ UINT8 DwordPrefix1;
+ UINT32 Power;
+ UINT8 DwordPrefix2;
+ UINT32 TransLatency;
+ UINT8 DwordPrefix3;
+ UINT32 BMLatency;
+ UINT8 DwordPrefix4;
+ UINT32 Control;
+ UINT8 DwordPrefix5;
+ UINT32 Status;
+} EFI_PSS_PACKAGE;
+#pragma pack()
+
+typedef struct {
+ UINT32 Index;
+ UINT64 Value;
+} S3_CPU_REGISTER;
+
+//
+// Function prototypes
+//
+
+/**
+ This function is the entry of processor power management initialization code.
+ It initializes the processor's power management features based on the user
+ configurations and hardware capablities.
+**/
+VOID
+PpmInit (
+ VOID
+ );
+
+/**
+ This function is to determine the Processor Power Management Flags
+ based on the hardware capability.
+**/
+VOID
+PpmDetectCapability (
+ VOID
+ );
+
+/**
+ This function is to determine the user configuration mask
+**/
+VOID
+PpmGetUserConfigurationMask (
+ VOID
+ );
+
+/**
+ This function is to patch and publish power management related acpi tables.
+**/
+VOID
+PpmPatchAndPublishAcpiTables (
+ VOID
+ );
+
+/**
+ This function is to patch PLvl2Lat and PLvl3Lat to enable C2, C3 support in OS.
+**/
+VOID
+PpmPatchFadtTable (
+ VOID
+ );
+
+/**
+ This function is to load all the power management acpi tables and patch IST table.
+**/
+VOID
+PpmLoadAndPatchPMTables (
+ VOID
+ );
+
+/**
+ This function is to save cpu registers for s3 resume.
+**/
+VOID
+PpmS3SaveRegisters (
+ VOID
+ );
+#endif
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c
new file mode 100644
index 0000000000..d10d7be94c
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.c
@@ -0,0 +1,119 @@
+/** @file
+
+This is QNC Smm Power Management driver
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#include "SmmPowerManagement.h"
+
+//
+// Global variables
+//
+EFI_SMM_CPU_PROTOCOL *mSmmCpu = NULL;
+EFI_GLOBAL_NVS_AREA *mGlobalNvsAreaPtr = NULL;
+EFI_MP_SERVICES_PROTOCOL *mMpService = NULL;
+EFI_ACPI_SDT_PROTOCOL *mAcpiSdt = NULL;
+EFI_ACPI_TABLE_PROTOCOL *mAcpiTable = NULL;
+
+EFI_GUID mS3CpuRegisterTableGuid = S3_CPU_REGISTER_TABLE_GUID;
+
+EFI_STATUS
+EFIAPI
+InitializePowerManagement (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initializes the SMM Handler Driver
+
+Arguments:
+
+ ImageHandle -
+
+ SystemTable -
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsAreaProtocol;
+
+ //
+ // Get SMM CPU protocol
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmCpuProtocolGuid,
+ NULL,
+ (VOID **)&mSmmCpu
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get the Sw dispatch protocol
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ NULL,
+ (VOID**)&SwDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Global NVS Area Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiGlobalNvsAreaProtocolGuid, NULL, (VOID **)&GlobalNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mGlobalNvsAreaPtr = GlobalNvsAreaProtocol->Area;
+
+ //
+ // Locate and cache PI AcpiSdt Protocol.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiSdtProtocolGuid,
+ NULL,
+ (VOID **) &mAcpiSdt
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Locate and cache PI AcpiSdt Protocol.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ NULL,
+ (VOID **) &mAcpiTable
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Get MpService protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&mMpService);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Initialize power management features on processors
+ //
+ PpmInit();
+
+ return Status;
+}
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h
new file mode 100644
index 0000000000..4ffe398923
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.h
@@ -0,0 +1,58 @@
+/** @file
+Header file for QNC Smm Power Management driver
+
+Copyright (c) 2013-2015 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SMM_POWER_MANAGEMENT_H_
+#define _SMM_POWER_MANAGEMENT_H_
+
+#include <PiSmm.h>
+#include <IntelQNCDxe.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/SmmCpu.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/MpService.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <IndustryStandard/Acpi.h>
+
+#include <AcpiCpuData.h>
+
+#include "Ppm.h"
+
+//
+// Module global variable
+//
+extern EFI_SMM_CPU_PROTOCOL *mSmmCpu;
+extern EFI_GLOBAL_NVS_AREA *mGlobalNvsAreaPtr;
+extern EFI_MP_SERVICES_PROTOCOL *mMpService;
+
+//
+// Function prototypes
+//
+
+#endif
diff --git a/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf
new file mode 100644
index 0000000000..4c869d8f74
--- /dev/null
+++ b/QuarkPlatformPkg/Acpi/DxeSmm/SmmPowerManagement/SmmPowerManagement.inf
@@ -0,0 +1,80 @@
+## @file
+# Component description file for SMM Power Management module
+#
+# This is QNC Smm Power Management driver .
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmPowerManagement
+ FILE_GUID = 271F1343-20D6-4e14-9B62-3C0297F56F07
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = InitializePowerManagement
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ SmmPowerManagement.c
+ SmmPowerManagement.h
+ Ppm.c
+ Ppm.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ QuarkSocPkg/QuarkSocPkg.dec
+ QuarkPlatformPkg/QuarkPlatformPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ PcdLib
+ IoLib
+ PciLib
+ BaseLib
+ BaseMemoryLib
+ SmmServicesTableLib
+ UefiBootServicesTableLib
+ S3BootScriptLib
+ MemoryAllocationLib
+
+[Protocols]
+ gEfiSmmCpuProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSmmSwDispatch2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiGlobalNvsAreaProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Guids]
+ gPowerManagementAcpiTableStorageGuid
+
+[Pcd]
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress
+ gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoLVL2
+ gQuarkPlatformTokenSpaceGuid.PcdPpmFlags
+
+[Depex]
+ gEfiSmmCpuProtocolGuid AND
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiGlobalNvsAreaProtocolGuid AND
+ gEfiAcpiTableProtocolGuid AND
+ gEfiMpServiceProtocolGuid