--- /dev/null
+/** @file\r
+ACPISMM Driver implementation file.\r
+\r
+This is QNC Smm platform driver\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#include <AcpiSmmPlatform.h>\r
+\r
+#define PCILIB_TO_COMMON_ADDRESS(Address) \\r
+ ((UINT64) ((((UINTN) ((Address>>20) & 0xff)) << 24) + (((UINTN) ((Address>>15) & 0x1f)) << 16) + (((UINTN) ((Address>>12) & 0x07)) << 8) + ((UINTN) (Address & 0xfff ))))\r
+\r
+//\r
+// Modular variables needed by this driver\r
+//\r
+EFI_ACPI_SMM_DEV mAcpiSmm;\r
+\r
+UINT8 mPciCfgRegTable[] = {\r
+ //\r
+ // Logic to decode the table masks to arrive at the registers saved\r
+ // Dword Registers are saved. For a given mask, the Base+offset register\r
+ // will be saved as in the table below.\r
+ // (example) To save register 0x24, 0x28 the mask at the Base 0x20 will be 0x06\r
+ // Base 0x00 0x20 0x40 0x60 0x80 0xA0 0xC0 0xE0\r
+ // Mask offset\r
+ // 0x01 0x00\r
+ // 0x02 0x04\r
+ // 0x04 0x08\r
+ // 0x08 0x0C\r
+ // 0x10 0x10\r
+ // 0x20 0x14\r
+ // 0x40 0x18\r
+ // 0x80 0x1C\r
+ //\r
+\r
+ //\r
+ // Bus, Dev, Func,\r
+ // 00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF\r
+ // Only Bus 0 device is supported now\r
+ //\r
+\r
+ //\r
+ // Quark South Cluster devices\r
+ //\r
+ PCI_DEVICE (0, 20, 0),\r
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 20, 1),\r
+ PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 20, 2),\r
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 20, 3),\r
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00),\r
+\r
+ PCI_DEVICE (0, 20, 4),\r
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 20, 5),\r
+ PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 20, 6),\r
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 20, 7),\r
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 21, 0),\r
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 21, 1),\r
+ PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 21, 2),\r
+ PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ //\r
+ // Quark North Cluster devices\r
+ //\r
+ PCI_DEVICE (0, 0, 0),\r
+ PCI_REG_MASK (0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 23, 0),\r
+ PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 23, 1),\r
+ PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),\r
+\r
+ PCI_DEVICE (0, 31, 0),\r
+ PCI_REG_MASK (0x00, 0x08, 0x4E, 0x03, 0x02, 0x00, 0x60, 0x10),\r
+\r
+ PCI_DEVICE_END\r
+};\r
+\r
+EFI_PLATFORM_TYPE mPlatformType;\r
+\r
+ // These registers have to set in byte order\r
+const UINT8 QNCS3SaveExtReg[] = {\r
+ QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, // SMRAM settings\r
+\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
+\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
+\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
+\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
+\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
+\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
+\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
+\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
+ QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
+\r
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_END_MEM_REG, // ECC Scrub settings\r
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_START_MEM_REG,\r
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_NEXT_READ_REG,\r
+ QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG,\r
+\r
+ 0xFF\r
+ };\r
+\r
+/**\r
+ Allocate EfiACPIMemoryNVS below 4G memory address.\r
+\r
+ This function allocates EfiACPIMemoryNVS below 4G memory address.\r
+\r
+ @param Size Size of memory to allocate.\r
+\r
+ @return Allocated address for output.\r
+\r
+**/\r
+VOID*\r
+AllocateAcpiNvsMemoryBelow4G (\r
+ IN UINTN Size\r
+ )\r
+{\r
+ UINTN Pages;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+ EFI_STATUS Status;\r
+ VOID* Buffer;\r
+\r
+ Pages = EFI_SIZE_TO_PAGES (Size);\r
+ Address = 0xffffffff;\r
+\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ Pages,\r
+ &Address\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ Buffer = (VOID *) (UINTN) Address;\r
+ ZeroMem (Buffer, Size);\r
+\r
+ return Buffer;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ReservedS3Memory (\r
+ UINTN SystemMemoryLength\r
+\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Reserved S3 memory for InstallS3Memory\r
+\r
+Arguments:\r
+\r
+\r
+Returns:\r
+\r
+ EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.\r
+ EFI_SUCCESS - Function has completed successfully.\r
+\r
+--*/\r
+{\r
+\r
+ VOID *GuidHob;\r
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;\r
+ VOID *AcpiReservedBase;\r
+\r
+ UINTN TsegIndex;\r
+ UINTN TsegSize;\r
+ UINTN TsegBase;\r
+ RESERVED_ACPI_S3_RANGE *AcpiS3Range;\r
+ //\r
+ // Get Hob list for SMRAM desc\r
+ //\r
+ GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r
+ ASSERT (GuidHob);\r
+ DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);\r
+ ASSERT (DescriptorBlock);\r
+\r
+ //\r
+ // Use the hob to get SMRAM capabilities\r
+ //\r
+ TsegIndex = DescriptorBlock->NumberOfSmmReservedRegions - 1;\r
+ ASSERT (TsegIndex <= (MAX_SMRAM_RANGES - 1));\r
+ TsegBase = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalStart;\r
+ TsegSize = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalSize;\r
+\r
+ DEBUG ((EFI_D_INFO, "SMM Base: %08X\n", TsegBase));\r
+ DEBUG ((EFI_D_INFO, "SMM Size: %08X\n", TsegSize));\r
+\r
+ //\r
+ // Now find the location of the data structure that is used to store the address\r
+ // of the S3 reserved memory.\r
+ //\r
+ AcpiS3Range = (RESERVED_ACPI_S3_RANGE*) (UINTN) (TsegBase + RESERVED_ACPI_S3_RANGE_OFFSET);\r
+\r
+ //\r
+ // Allocate reserved ACPI memory for S3 resume. Pointer to this region is\r
+ // stored in SMRAM in the first page of TSEG.\r
+ //\r
+ AcpiReservedBase = AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize));\r
+ if (AcpiReservedBase != NULL) {\r
+ AcpiS3Range->AcpiReservedMemoryBase = (UINT32)(UINTN) AcpiReservedBase;\r
+ AcpiS3Range->AcpiReservedMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);\r
+ }\r
+ AcpiS3Range->SystemMemoryLength = (UINT32)SystemMemoryLength;\r
+\r
+ DEBUG ((EFI_D_INFO, "S3 Memory Base: %08X\n", AcpiS3Range->AcpiReservedMemoryBase));\r
+ DEBUG ((EFI_D_INFO, "S3 Memory Size: %08X\n", AcpiS3Range->AcpiReservedMemorySize));\r
+ DEBUG ((EFI_D_INFO, "S3 SysMemoryLength: %08X\n", AcpiS3Range->SystemMemoryLength));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitAcpiSmmPlatform (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initializes the SMM S3 Handler Driver.\r
+\r
+Arguments:\r
+\r
+ ImageHandle - The image handle of Sleep State Wake driver.\r
+ SystemTable - The starndard EFI system table.\r
+\r
+Returns:\r
+\r
+ EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.\r
+ EFI_SUCCESS - Function has completed successfully.\r
+ Other - Error occured during execution.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *AcpiNvsProtocol = NULL;\r
+ UINTN MemoryLength;\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiGlobalNvsAreaProtocolGuid,\r
+ NULL,\r
+ (VOID **) &AcpiNvsProtocol\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ mAcpiSmm.BootScriptSaved = 0;\r
+\r
+ mPlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);\r
+\r
+ //\r
+ // Calculate the system memory length by memory hobs\r
+ //\r
+ MemoryLength = 0x100000;\r
+ Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
+ ASSERT (Hob.Raw != NULL);\r
+ while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {\r
+ if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
+ //\r
+ // Skip the memory region below 1MB\r
+ //\r
+ if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {\r
+ MemoryLength += (UINTN)Hob.ResourceDescriptor->ResourceLength;\r
+ }\r
+ }\r
+ Hob.Raw = GET_NEXT_HOB (Hob);\r
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
+ }\r
+\r
+ ReservedS3Memory(MemoryLength);\r
+\r
+ //\r
+ // Locate and Register to Parent driver\r
+ //\r
+ Status = RegisterToDispatchDriver ();\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+RegisterToDispatchDriver (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Register to dispatch driver.\r
+\r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Successfully init the device.\r
+ Other - Error occured whening calling Dxe lib functions.\r
+\r
+--*/\r
+{\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+ EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;\r
+ EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;\r
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryDispatchContext;\r
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS1DispatchContext;\r
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS3DispatchContext;\r
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS4DispatchContext;\r
+ EFI_SMM_SX_REGISTER_CONTEXT *EntryS5DispatchContext;\r
+ EFI_SMM_SW_REGISTER_CONTEXT *SwContext;\r
+ EFI_SMM_SW_REGISTER_CONTEXT *AcpiDisableSwContext;\r
+ EFI_SMM_SW_REGISTER_CONTEXT *AcpiEnableSwContext;\r
+\r
+ Status = gSmst->SmmLocateProtocol (\r
+ &gEfiSmmSxDispatch2ProtocolGuid,\r
+ NULL,\r
+ (VOID **) &SxDispatch\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gSmst->SmmLocateProtocol (\r
+ &gEfiSmmSwDispatch2ProtocolGuid,\r
+ NULL,\r
+ (VOID **) &SwDispatch\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Length = sizeof (EFI_SMM_SX_REGISTER_CONTEXT) * 4 + sizeof (EFI_SMM_SW_REGISTER_CONTEXT) * 2;\r
+ Status = gSmst->SmmAllocatePool (\r
+ EfiRuntimeServicesData,\r
+ Length,\r
+ (VOID **) &EntryDispatchContext\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ SetMem (EntryDispatchContext, Length, 0);\r
+\r
+ EntryS1DispatchContext = EntryDispatchContext++;\r
+ EntryS3DispatchContext = EntryDispatchContext++;\r
+ EntryS4DispatchContext = EntryDispatchContext++;\r
+ EntryS5DispatchContext = EntryDispatchContext++;\r
+\r
+ SwContext = (EFI_SMM_SW_REGISTER_CONTEXT *)EntryDispatchContext;\r
+ AcpiDisableSwContext = SwContext++;\r
+ AcpiEnableSwContext = SwContext++;\r
+\r
+ //\r
+ // Register the enable handler\r
+ //\r
+ AcpiEnableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_ENABLE;\r
+ Status = SwDispatch->Register (\r
+ SwDispatch,\r
+ EnableAcpiCallback,\r
+ AcpiEnableSwContext,\r
+ &(mAcpiSmm.DisableAcpiHandle)\r
+ );\r
+\r
+ //\r
+ // Register the disable handler\r
+ //\r
+ AcpiDisableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_DISABLE;\r
+ Status = SwDispatch->Register (\r
+ SwDispatch,\r
+ DisableAcpiCallback,\r
+ AcpiDisableSwContext,\r
+ &(mAcpiSmm.EnableAcpiHandle)\r
+ );\r
+\r
+\r
+ //\r
+ // Register entry phase call back function for S1\r
+ //\r
+ EntryS1DispatchContext->Type = SxS1;\r
+ EntryS1DispatchContext->Phase = SxEntry;\r
+ Status = SxDispatch->Register (\r
+ SxDispatch,\r
+ SxSleepEntryCallBack,\r
+ EntryS1DispatchContext,\r
+ &(mAcpiSmm.S1SleepEntryHandle)\r
+ );\r
+\r
+ //\r
+ // Register entry phase call back function\r
+ //\r
+ EntryS3DispatchContext->Type = SxS3;\r
+ EntryS3DispatchContext->Phase = SxEntry;\r
+ Status = SxDispatch->Register (\r
+ SxDispatch,\r
+ SxSleepEntryCallBack,\r
+ EntryS3DispatchContext,\r
+ &(mAcpiSmm.S3SleepEntryHandle)\r
+ );\r
+\r
+ //\r
+ // Register entry phase call back function for S4\r
+ //\r
+ EntryS4DispatchContext->Type = SxS4;\r
+ EntryS4DispatchContext->Phase = SxEntry;\r
+ Status = SxDispatch->Register (\r
+ SxDispatch,\r
+ SxSleepEntryCallBack,\r
+ EntryS4DispatchContext,\r
+ &(mAcpiSmm.S4SleepEntryHandle)\r
+ );\r
+\r
+ //\r
+ // Register callback for S5 in order to workaround the LAN shutdown issue\r
+ //\r
+ EntryS5DispatchContext->Type = SxS5;\r
+ EntryS5DispatchContext->Phase = SxEntry;\r
+ Status = SxDispatch->Register (\r
+ SxDispatch,\r
+ SxSleepEntryCallBack,\r
+ EntryS5DispatchContext,\r
+ &(mAcpiSmm.S5SoftOffEntryHandle)\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+RestoreQncS3SwCallback (\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *DispatchContext,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ SMI handler to retore QncS3 code & context for S3 path\r
+ This will be only triggered when BootScript got executed during resume\r
+\r
+Arguments:\r
+ DispatchHandle - EFI Handle\r
+ DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT\r
+\r
+Returns:\r
+ Nothing\r
+\r
+--*/\r
+{\r
+ //\r
+ // Restore to original address by default\r
+ //\r
+ RestoreLockBox(&gQncS3CodeInLockBoxGuid, NULL, NULL);\r
+ RestoreLockBox(&gQncS3ContextInLockBoxGuid, NULL, NULL);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DisableAcpiCallback (\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *DispatchContext,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ SMI handler to disable ACPI mode\r
+\r
+ Dispatched on reads from APM port with value 0xA1\r
+\r
+ ACPI events are disabled and ACPI event status is cleared.\r
+ SCI mode is then disabled.\r
+ Clear all ACPI event status and disable all ACPI events\r
+ Disable PM sources except power button\r
+ Clear status bits\r
+ Disable GPE0 sources\r
+ Clear status bits\r
+ Disable GPE1 sources\r
+ Clear status bits\r
+ Disable SCI\r
+\r
+Arguments:\r
+ DispatchHandle - EFI Handle\r
+ DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT\r
+\r
+Returns:\r
+ Nothing\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 Pm1Cnt;\r
+\r
+ Status = GetAllQncPmBase (gSmst);\r
+ ASSERT_EFI_ERROR (Status);\r
+ Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);\r
+\r
+ //\r
+ // Disable SCI\r
+ //\r
+ Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SCIEN;\r
+\r
+ IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EnableAcpiCallback (\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *DispatchContext,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ SMI handler to enable ACPI mode\r
+\r
+ Dispatched on reads from APM port with value 0xA0\r
+\r
+ Disables the SW SMI Timer.\r
+ ACPI events are disabled and ACPI event status is cleared.\r
+ SCI mode is then enabled.\r
+\r
+ Disable SW SMI Timer\r
+\r
+ Clear all ACPI event status and disable all ACPI events\r
+ Disable PM sources except power button\r
+ Clear status bits\r
+\r
+ Disable GPE0 sources\r
+ Clear status bits\r
+\r
+ Disable GPE1 sources\r
+ Clear status bits\r
+\r
+ Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)\r
+\r
+ Enable SCI\r
+\r
+Arguments:\r
+ DispatchHandle - EFI Handle\r
+ DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT\r
+\r
+Returns:\r
+ Nothing\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 SmiEn;\r
+ UINT16 Pm1Cnt;\r
+ UINT8 Data8;\r
+\r
+ Status = GetAllQncPmBase (gSmst);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ SmiEn = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);\r
+\r
+ //\r
+ // Disable SW SMI Timer\r
+ //\r
+ SmiEn &= ~(B_QNC_GPE0BLK_SMIE_SWT);\r
+ IoWrite32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE, SmiEn);\r
+\r
+ //\r
+ // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)\r
+ //\r
+ Data8 = RTC_ADDRESS_REGISTER_D;\r
+ IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);\r
+ Data8 = 0x0;\r
+ IoWrite8 (R_IOPORT_CMOS_STANDARD_DATA, Data8);\r
+\r
+ //\r
+ // Enable SCI\r
+ //\r
+ Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);\r
+ Pm1Cnt |= B_QNC_PM1BLK_PM1C_SCIEN;\r
+ IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);\r
+\r
+ //\r
+ // Do platform specific stuff for ACPI enable SMI\r
+ //\r
+\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SxSleepEntryCallBack (\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *DispatchContext,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Callback function entry for Sx sleep state.\r
+\r
+Arguments:\r
+\r
+ DispatchHandle - The handle of this callback, obtained when registering.\r
+ DispatchContext - The predefined context which contained sleep type and phase.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Operation successfully performed.\r
+ EFI_INVALID_PARAMETER - Invalid parameter passed in.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 Data8;\r
+ UINT16 Data16;\r
+ UINT32 Data32;\r
+\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeS3SuspendStart));\r
+\r
+ //\r
+ // Reget QNC power mgmr regs base in case of OS changing it at runtime\r
+ //\r
+ Status = GetAllQncPmBase (gSmst);\r
+\r
+ //\r
+ // Clear RTC Alarm (if set)\r
+ //\r
+ Data8 = RTC_ADDRESS_REGISTER_C;\r
+ IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);\r
+ Data8 = IoRead8 (R_IOPORT_CMOS_STANDARD_DATA);\r
+\r
+ //\r
+ // Clear all ACPI status bits\r
+ //\r
+ Data32 = B_QNC_GPE0BLK_GPE0S_ALL;\r
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0S, 1, &Data32 );\r
+ Data16 = B_QNC_PM1BLK_PM1S_ALL;\r
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1S, 1, &Data16 );\r
+\r
+ //\r
+ // Handling S1 - setting appropriate wake bits in GPE0_EN\r
+ //\r
+ if ((DispatchHandle == mAcpiSmm.S1SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS1)) {\r
+ //\r
+ // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN\r
+ //\r
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
+ Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);\r
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
+\r
+ //\r
+ // Enable bit10 (RTC) in PM1E\r
+ //\r
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
+ Data16 |= B_QNC_PM1BLK_PM1E_RTC;\r
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Handling S4, S5 and WOL - setting appropriate wake bits in GPE0_EN\r
+ //\r
+ if (((DispatchHandle == mAcpiSmm.S4SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS4)) ||\r
+ ((DispatchHandle == mAcpiSmm.S5SoftOffEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS5))\r
+ ) {\r
+ //\r
+ // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN\r
+ // Enable the WOL bits in GPE0_EN reg here for PME\r
+ //\r
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
+ Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);\r
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
+\r
+ //\r
+ // Enable bit10 (RTC) in PM1E\r
+ //\r
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
+ Data16 |= B_QNC_PM1BLK_PM1E_RTC;\r
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
+\r
+ } else {\r
+\r
+ if ((DispatchHandle != mAcpiSmm.S3SleepEntryHandle) || (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type != SxS3)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = SaveRuntimeScriptTable (gSmst);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Enable bit13 (EGPE), 14 (GPIO), 17 (PCIE) in GPE0_EN\r
+ // Enable the WOL bits in GPE0_EN reg here for PME\r
+ //\r
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
+ Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);\r
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
+\r
+ //\r
+ // Enable bit10 (RTC) in PM1E\r
+ //\r
+ Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
+ Data16 |= B_QNC_PM1BLK_PM1E_RTC;\r
+ Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
+ }\r
+\r
+ //\r
+ // When entering a power-managed state like S3,\r
+ // PERST# must be asserted in advance of power-off.\r
+ //\r
+ PlatformPERSTAssert (mPlatformType);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetAllQncPmBase (\r
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Get QNC chipset LPC Power Management I/O Base at runtime.\r
+\r
+Arguments:\r
+\r
+ Smst - The standard SMM system table.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Successfully init the device.\r
+ Other - Error occured whening calling Dxe lib functions.\r
+\r
+--*/\r
+{\r
+ 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;\r
+ 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;\r
+\r
+ //\r
+ // Quark does not support Changing Primary SoC IOBARs from what was\r
+ // setup in SEC/PEI UEFI stages.\r
+ //\r
+ ASSERT (mAcpiSmm.QncPmBase == (UINT32) PcdGet16 (PcdPm1blkIoBaseAddress));\r
+ ASSERT (mAcpiSmm.QncGpe0Base == (UINT32) PcdGet16 (PcdGpe0blkIoBaseAddress));\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SaveRuntimeScriptTable (\r
+ IN EFI_SMM_SYSTEM_TABLE2 *Smst\r
+ )\r
+{\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r
+ UINT32 Data32;\r
+ UINT16 Data16;\r
+ UINT8 Mask;\r
+ UINTN Index;\r
+ UINTN Offset;\r
+ UINT16 DeviceId;\r
+\r
+ //\r
+ // Check what Soc we are running on (read Host bridge DeviceId)\r
+ //\r
+ DeviceId = QncGetSocDeviceId();\r
+\r
+ //\r
+ // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM\r
+ // and vital to S3 resume. That's why we put save code here\r
+ //\r
+ Index = 0;\r
+ while (mPciCfgRegTable[Index] != PCI_DEVICE_END) {\r
+\r
+ PciAddress.Bus = mPciCfgRegTable[Index++];\r
+ PciAddress.Device = mPciCfgRegTable[Index++];\r
+ PciAddress.Function = mPciCfgRegTable[Index++];\r
+ PciAddress.Register = 0;\r
+ PciAddress.ExtendedRegister = 0;\r
+\r
+ Data16 = PciRead16 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));\r
+ if (Data16 == 0xFFFF) {\r
+ Index += 8;\r
+ continue;\r
+ }\r
+\r
+ for (Offset = 0, Mask = 0x01; Offset < 256; Offset += 4, Mask <<= 1) {\r
+\r
+ if (Mask == 0x00) {\r
+ Mask = 0x01;\r
+ }\r
+\r
+ if (mPciCfgRegTable[Index + Offset / 32] & Mask) {\r
+\r
+ PciAddress.Register = (UINT8) Offset;\r
+ Data32 = PciRead32 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));\r
+\r
+\r
+ //\r
+ // Save latest settings to runtime script table\r
+ //\r
+ S3BootScriptSavePciCfgWrite (\r
+ S3BootScriptWidthUint32,\r
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)),\r
+ 1,\r
+ &Data32\r
+ );\r
+ }\r
+ }\r
+\r
+ Index += 8;\r
+\r
+ }\r
+\r
+ //\r
+ // Save message bus registers\r
+ //\r
+ Index = 0;\r
+ while (QNCS3SaveExtReg[Index] != 0xFF) {\r
+ Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
+\r
+ //\r
+ // Save IMR settings with IMR protection disabled initially\r
+ // HMBOUND and IMRs will be locked just before jumping to the OS waking vector\r
+ //\r
+ if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {\r
+ 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)) {\r
+ Data32 &= ~IMR_LOCK;\r
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {\r
+ Data32 &= ~IMR_EN;\r
+ }\r
+ }\r
+ 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)) {\r
+ Data32 = (UINT32)IMRX_ALL_ACCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Save latest settings to runtime script table\r
+ //\r
+ S3BootScriptSavePciCfgWrite (\r
+ S3BootScriptWidthUint32,\r
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),\r
+ 1,\r
+ &Data32\r
+ );\r
+\r
+ Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
+\r
+ S3BootScriptSavePciCfgWrite (\r
+ S3BootScriptWidthUint32,\r
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r
+ 1,\r
+ &Data32\r
+ );\r
+ Index += 2;\r
+ }\r
+\r
+ Index = 0;\r
+ while (QNCS3SaveExtReg[Index] != 0xFF) {\r
+ //\r
+ // Save IMR settings with IMR protection enabled (above script was to handle restoring all settings first - now we want to enable)\r
+ //\r
+ if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {\r
+ if (DeviceId == QUARK2_MC_DEVICE_ID) {\r
+ 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)) {\r
+ Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
+ Data32 &= ~IMR_LOCK;\r
+\r
+ //\r
+ // Save latest settings to runtime script table\r
+ //\r
+ S3BootScriptSavePciCfgWrite (\r
+ S3BootScriptWidthUint32,\r
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),\r
+ 1,\r
+ &Data32\r
+ );\r
+\r
+ Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
+\r
+ S3BootScriptSavePciCfgWrite (\r
+ S3BootScriptWidthUint32,\r
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r
+ 1,\r
+ &Data32\r
+ );\r
+ }\r
+ } else {\r
+ 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)) {\r
+ Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
+\r
+ //\r
+ // Save latest settings to runtime script table\r
+ //\r
+ S3BootScriptSavePciCfgWrite (\r
+ S3BootScriptWidthUint32,\r
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),\r
+ 1,\r
+ &Data32\r
+ );\r
+\r
+ Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
+\r
+ S3BootScriptSavePciCfgWrite (\r
+ S3BootScriptWidthUint32,\r
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r
+ 1,\r
+ &Data32\r
+ );\r
+ }\r
+ }\r
+ }\r
+ Index += 2;\r
+ }\r
+\r
+ // Check if ECC scrub enabled and need re-enabling on resume\r
+ // All scrub related configuration registers are saved on suspend\r
+ // as part of QNCS3SaveExtReg configuration table script.\r
+ // The code below extends the S3 resume script with scrub reactivation\r
+ // message (if needed only)\r
+ Data32 = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG);\r
+ if( 0 != (Data32 & SCRUB_CFG_ACTIVE)) {\r
+\r
+ Data32 = SCRUB_RESUME_MSG();\r
+\r
+ S3BootScriptSavePciCfgWrite (\r
+ S3BootScriptWidthUint32,\r
+ PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r
+ 1,\r
+ &Data32\r
+ );\r
+ }\r
+\r
+ //\r
+ // Save I/O ports to S3 script table\r
+ //\r
+\r
+ //\r
+ // Important to trap Sx for SMM\r
+ //\r
+ Data32 = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);\r
+ S3BootScriptSaveIoWrite(S3BootScriptWidthUint32, (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE), 1, &Data32);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r