]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Acpi/DxeSmm/AcpiSmm/AcpiSmmPlatform.c
OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Do not expose MMIO in SMM build
[mirror_edk2.git] / QuarkPlatformPkg / Acpi / DxeSmm / AcpiSmm / AcpiSmmPlatform.c
CommitLineData
b303605e
MK
1/** @file\r
2ACPISMM Driver implementation file.\r
3\r
4This is QNC Smm platform driver\r
5\r
65aec008 6Copyright (c) 2013-2016 Intel Corporation.\r
b303605e
MK
7\r
8This program and the accompanying materials\r
9are licensed and made available under the terms and conditions of the BSD License\r
10which accompanies this distribution. The full text of the license may be found at\r
11http://opensource.org/licenses/bsd-license.php\r
12\r
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16\r
17**/\r
18\r
19#include <AcpiSmmPlatform.h>\r
20\r
21#define PCILIB_TO_COMMON_ADDRESS(Address) \\r
22 ((UINT64) ((((UINTN) ((Address>>20) & 0xff)) << 24) + (((UINTN) ((Address>>15) & 0x1f)) << 16) + (((UINTN) ((Address>>12) & 0x07)) << 8) + ((UINTN) (Address & 0xfff ))))\r
23\r
24//\r
25// Modular variables needed by this driver\r
26//\r
27EFI_ACPI_SMM_DEV mAcpiSmm;\r
28\r
29UINT8 mPciCfgRegTable[] = {\r
30 //\r
31 // Logic to decode the table masks to arrive at the registers saved\r
32 // Dword Registers are saved. For a given mask, the Base+offset register\r
33 // will be saved as in the table below.\r
34 // (example) To save register 0x24, 0x28 the mask at the Base 0x20 will be 0x06\r
35 // Base 0x00 0x20 0x40 0x60 0x80 0xA0 0xC0 0xE0\r
36 // Mask offset\r
37 // 0x01 0x00\r
38 // 0x02 0x04\r
39 // 0x04 0x08\r
40 // 0x08 0x0C\r
41 // 0x10 0x10\r
42 // 0x20 0x14\r
43 // 0x40 0x18\r
44 // 0x80 0x1C\r
45 //\r
46\r
47 //\r
48 // Bus, Dev, Func,\r
49 // 00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF\r
50 // Only Bus 0 device is supported now\r
51 //\r
52\r
53 //\r
54 // Quark South Cluster devices\r
55 //\r
56 PCI_DEVICE (0, 20, 0),\r
57 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
58\r
59 PCI_DEVICE (0, 20, 1),\r
60 PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
61\r
62 PCI_DEVICE (0, 20, 2),\r
63 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
64\r
65 PCI_DEVICE (0, 20, 3),\r
66 PCI_REG_MASK (0x18, 0x98, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00),\r
67\r
68 PCI_DEVICE (0, 20, 4),\r
69 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
70\r
71 PCI_DEVICE (0, 20, 5),\r
72 PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
73\r
74 PCI_DEVICE (0, 20, 6),\r
75 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
76\r
77 PCI_DEVICE (0, 20, 7),\r
78 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
79\r
80 PCI_DEVICE (0, 21, 0),\r
81 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
82\r
83 PCI_DEVICE (0, 21, 1),\r
84 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
85\r
86 PCI_DEVICE (0, 21, 2),\r
87 PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
88\r
89 //\r
90 // Quark North Cluster devices\r
91 //\r
92 PCI_DEVICE (0, 0, 0),\r
93 PCI_REG_MASK (0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r
94\r
95 PCI_DEVICE (0, 23, 0),\r
96 PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),\r
97\r
98 PCI_DEVICE (0, 23, 1),\r
99 PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),\r
100\r
101 PCI_DEVICE (0, 31, 0),\r
102 PCI_REG_MASK (0x00, 0x08, 0x4E, 0x03, 0x02, 0x00, 0x60, 0x10),\r
103\r
104 PCI_DEVICE_END\r
105};\r
106\r
107EFI_PLATFORM_TYPE mPlatformType;\r
108\r
109 // These registers have to set in byte order\r
110const UINT8 QNCS3SaveExtReg[] = {\r
111 QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, // SMRAM settings\r
112\r
113 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
114 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
115 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
116 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
117\r
118 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
119 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
120 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
121 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
122\r
123 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
124 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
125 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
126 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
127\r
128 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
129 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
130 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
131 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
132\r
133 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
134 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
135 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
136 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
137\r
138 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
139 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
140 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
141 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
142\r
143 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
144 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
145 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
146 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
147\r
148 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL,\r
149 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXH,\r
150 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r
151 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r
152\r
153 QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_END_MEM_REG, // ECC Scrub settings\r
154 QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_START_MEM_REG,\r
155 QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_NEXT_READ_REG,\r
156 QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG,\r
157\r
158 0xFF\r
159 };\r
160\r
161/**\r
162 Allocate EfiACPIMemoryNVS below 4G memory address.\r
163\r
164 This function allocates EfiACPIMemoryNVS below 4G memory address.\r
165\r
166 @param Size Size of memory to allocate.\r
167\r
168 @return Allocated address for output.\r
169\r
170**/\r
171VOID*\r
172AllocateAcpiNvsMemoryBelow4G (\r
173 IN UINTN Size\r
174 )\r
175{\r
176 UINTN Pages;\r
177 EFI_PHYSICAL_ADDRESS Address;\r
178 EFI_STATUS Status;\r
179 VOID* Buffer;\r
180\r
181 Pages = EFI_SIZE_TO_PAGES (Size);\r
182 Address = 0xffffffff;\r
183\r
184 Status = gBS->AllocatePages (\r
185 AllocateMaxAddress,\r
186 EfiACPIMemoryNVS,\r
187 Pages,\r
188 &Address\r
189 );\r
190 if (EFI_ERROR (Status)) {\r
191 return NULL;\r
192 }\r
193\r
194 Buffer = (VOID *) (UINTN) Address;\r
195 ZeroMem (Buffer, Size);\r
196\r
197 return Buffer;\r
198}\r
199\r
200EFI_STATUS\r
201EFIAPI\r
202ReservedS3Memory (\r
203 UINTN SystemMemoryLength\r
204\r
205 )\r
206/*++\r
207\r
208Routine Description:\r
209\r
210 Reserved S3 memory for InstallS3Memory\r
211\r
212Arguments:\r
213\r
214\r
215Returns:\r
216\r
217 EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.\r
218 EFI_SUCCESS - Function has completed successfully.\r
219\r
220--*/\r
221{\r
222\r
223 VOID *GuidHob;\r
224 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;\r
225 VOID *AcpiReservedBase;\r
226\r
227 UINTN TsegIndex;\r
228 UINTN TsegSize;\r
229 UINTN TsegBase;\r
230 RESERVED_ACPI_S3_RANGE *AcpiS3Range;\r
231 //\r
232 // Get Hob list for SMRAM desc\r
233 //\r
234 GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r
235 ASSERT (GuidHob);\r
236 DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);\r
237 ASSERT (DescriptorBlock);\r
238\r
239 //\r
240 // Use the hob to get SMRAM capabilities\r
241 //\r
242 TsegIndex = DescriptorBlock->NumberOfSmmReservedRegions - 1;\r
243 ASSERT (TsegIndex <= (MAX_SMRAM_RANGES - 1));\r
244 TsegBase = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalStart;\r
245 TsegSize = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalSize;\r
246\r
247 DEBUG ((EFI_D_INFO, "SMM Base: %08X\n", TsegBase));\r
248 DEBUG ((EFI_D_INFO, "SMM Size: %08X\n", TsegSize));\r
249\r
250 //\r
251 // Now find the location of the data structure that is used to store the address\r
252 // of the S3 reserved memory.\r
253 //\r
254 AcpiS3Range = (RESERVED_ACPI_S3_RANGE*) (UINTN) (TsegBase + RESERVED_ACPI_S3_RANGE_OFFSET);\r
255\r
256 //\r
257 // Allocate reserved ACPI memory for S3 resume. Pointer to this region is\r
258 // stored in SMRAM in the first page of TSEG.\r
259 //\r
260 AcpiReservedBase = AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize));\r
261 if (AcpiReservedBase != NULL) {\r
262 AcpiS3Range->AcpiReservedMemoryBase = (UINT32)(UINTN) AcpiReservedBase;\r
263 AcpiS3Range->AcpiReservedMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);\r
264 }\r
265 AcpiS3Range->SystemMemoryLength = (UINT32)SystemMemoryLength;\r
266\r
267 DEBUG ((EFI_D_INFO, "S3 Memory Base: %08X\n", AcpiS3Range->AcpiReservedMemoryBase));\r
268 DEBUG ((EFI_D_INFO, "S3 Memory Size: %08X\n", AcpiS3Range->AcpiReservedMemorySize));\r
269 DEBUG ((EFI_D_INFO, "S3 SysMemoryLength: %08X\n", AcpiS3Range->SystemMemoryLength));\r
270\r
271 return EFI_SUCCESS;\r
272}\r
273\r
274\r
275EFI_STATUS\r
276EFIAPI\r
277InitAcpiSmmPlatform (\r
278 IN EFI_HANDLE ImageHandle,\r
279 IN EFI_SYSTEM_TABLE *SystemTable\r
280 )\r
281/*++\r
282\r
283Routine Description:\r
284\r
285 Initializes the SMM S3 Handler Driver.\r
286\r
287Arguments:\r
288\r
289 ImageHandle - The image handle of Sleep State Wake driver.\r
290 SystemTable - The starndard EFI system table.\r
291\r
292Returns:\r
293\r
294 EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.\r
295 EFI_SUCCESS - Function has completed successfully.\r
296 Other - Error occured during execution.\r
297\r
298--*/\r
299{\r
300 EFI_STATUS Status;\r
301 EFI_GLOBAL_NVS_AREA_PROTOCOL *AcpiNvsProtocol = NULL;\r
302 UINTN MemoryLength;\r
303 EFI_PEI_HOB_POINTERS Hob;\r
304\r
305 Status = gBS->LocateProtocol (\r
306 &gEfiGlobalNvsAreaProtocolGuid,\r
307 NULL,\r
308 (VOID **) &AcpiNvsProtocol\r
309 );\r
310 ASSERT_EFI_ERROR (Status);\r
311\r
312 mAcpiSmm.BootScriptSaved = 0;\r
313\r
314 mPlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);\r
315\r
316 //\r
317 // Calculate the system memory length by memory hobs\r
318 //\r
319 MemoryLength = 0x100000;\r
320 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
321 ASSERT (Hob.Raw != NULL);\r
322 while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {\r
323 if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
324 //\r
325 // Skip the memory region below 1MB\r
326 //\r
327 if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {\r
328 MemoryLength += (UINTN)Hob.ResourceDescriptor->ResourceLength;\r
329 }\r
330 }\r
331 Hob.Raw = GET_NEXT_HOB (Hob);\r
332 Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
333 }\r
334\r
335 ReservedS3Memory(MemoryLength);\r
336\r
337 //\r
338 // Locate and Register to Parent driver\r
339 //\r
340 Status = RegisterToDispatchDriver ();\r
341 ASSERT_EFI_ERROR (Status);\r
342\r
343 return EFI_SUCCESS;\r
344}\r
345\r
346EFI_STATUS\r
347RegisterToDispatchDriver (\r
348 VOID\r
349 )\r
350/*++\r
351\r
352Routine Description:\r
353\r
354 Register to dispatch driver.\r
355\r
356Arguments:\r
357\r
358 None.\r
359\r
360Returns:\r
361\r
362 EFI_SUCCESS - Successfully init the device.\r
363 Other - Error occured whening calling Dxe lib functions.\r
364\r
365--*/\r
366{\r
367 UINTN Length;\r
368 EFI_STATUS Status;\r
369 EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;\r
370 EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;\r
371 EFI_SMM_SX_REGISTER_CONTEXT *EntryDispatchContext;\r
372 EFI_SMM_SX_REGISTER_CONTEXT *EntryS1DispatchContext;\r
373 EFI_SMM_SX_REGISTER_CONTEXT *EntryS3DispatchContext;\r
374 EFI_SMM_SX_REGISTER_CONTEXT *EntryS4DispatchContext;\r
375 EFI_SMM_SX_REGISTER_CONTEXT *EntryS5DispatchContext;\r
376 EFI_SMM_SW_REGISTER_CONTEXT *SwContext;\r
377 EFI_SMM_SW_REGISTER_CONTEXT *AcpiDisableSwContext;\r
378 EFI_SMM_SW_REGISTER_CONTEXT *AcpiEnableSwContext;\r
379\r
380 Status = gSmst->SmmLocateProtocol (\r
381 &gEfiSmmSxDispatch2ProtocolGuid,\r
382 NULL,\r
383 (VOID **) &SxDispatch\r
384 );\r
385 if (EFI_ERROR (Status)) {\r
386 return Status;\r
387 }\r
388\r
389 Status = gSmst->SmmLocateProtocol (\r
390 &gEfiSmmSwDispatch2ProtocolGuid,\r
391 NULL,\r
392 (VOID **) &SwDispatch\r
393 );\r
394 if (EFI_ERROR (Status)) {\r
395 return Status;\r
396 }\r
397\r
398 Length = sizeof (EFI_SMM_SX_REGISTER_CONTEXT) * 4 + sizeof (EFI_SMM_SW_REGISTER_CONTEXT) * 2;\r
399 Status = gSmst->SmmAllocatePool (\r
400 EfiRuntimeServicesData,\r
401 Length,\r
402 (VOID **) &EntryDispatchContext\r
403 );\r
404 if (EFI_ERROR (Status)) {\r
405 return Status;\r
406 }\r
407\r
408 SetMem (EntryDispatchContext, Length, 0);\r
409\r
410 EntryS1DispatchContext = EntryDispatchContext++;\r
411 EntryS3DispatchContext = EntryDispatchContext++;\r
412 EntryS4DispatchContext = EntryDispatchContext++;\r
413 EntryS5DispatchContext = EntryDispatchContext++;\r
414\r
415 SwContext = (EFI_SMM_SW_REGISTER_CONTEXT *)EntryDispatchContext;\r
416 AcpiDisableSwContext = SwContext++;\r
417 AcpiEnableSwContext = SwContext++;\r
418\r
419 //\r
420 // Register the enable handler\r
421 //\r
422 AcpiEnableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_ENABLE;\r
423 Status = SwDispatch->Register (\r
424 SwDispatch,\r
425 EnableAcpiCallback,\r
426 AcpiEnableSwContext,\r
427 &(mAcpiSmm.DisableAcpiHandle)\r
428 );\r
429\r
430 //\r
431 // Register the disable handler\r
432 //\r
433 AcpiDisableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_DISABLE;\r
434 Status = SwDispatch->Register (\r
435 SwDispatch,\r
436 DisableAcpiCallback,\r
437 AcpiDisableSwContext,\r
438 &(mAcpiSmm.EnableAcpiHandle)\r
439 );\r
440\r
441\r
442 //\r
443 // Register entry phase call back function for S1\r
444 //\r
445 EntryS1DispatchContext->Type = SxS1;\r
446 EntryS1DispatchContext->Phase = SxEntry;\r
447 Status = SxDispatch->Register (\r
448 SxDispatch,\r
449 SxSleepEntryCallBack,\r
450 EntryS1DispatchContext,\r
451 &(mAcpiSmm.S1SleepEntryHandle)\r
452 );\r
453\r
454 //\r
455 // Register entry phase call back function\r
456 //\r
457 EntryS3DispatchContext->Type = SxS3;\r
458 EntryS3DispatchContext->Phase = SxEntry;\r
459 Status = SxDispatch->Register (\r
460 SxDispatch,\r
461 SxSleepEntryCallBack,\r
462 EntryS3DispatchContext,\r
463 &(mAcpiSmm.S3SleepEntryHandle)\r
464 );\r
465\r
466 //\r
467 // Register entry phase call back function for S4\r
468 //\r
469 EntryS4DispatchContext->Type = SxS4;\r
470 EntryS4DispatchContext->Phase = SxEntry;\r
471 Status = SxDispatch->Register (\r
472 SxDispatch,\r
473 SxSleepEntryCallBack,\r
474 EntryS4DispatchContext,\r
475 &(mAcpiSmm.S4SleepEntryHandle)\r
476 );\r
477\r
478 //\r
479 // Register callback for S5 in order to workaround the LAN shutdown issue\r
480 //\r
481 EntryS5DispatchContext->Type = SxS5;\r
482 EntryS5DispatchContext->Phase = SxEntry;\r
483 Status = SxDispatch->Register (\r
484 SxDispatch,\r
485 SxSleepEntryCallBack,\r
486 EntryS5DispatchContext,\r
487 &(mAcpiSmm.S5SoftOffEntryHandle)\r
488 );\r
489\r
490 return Status;\r
491}\r
492\r
493\r
494EFI_STATUS\r
495RestoreQncS3SwCallback (\r
496 IN EFI_HANDLE DispatchHandle,\r
497 IN CONST VOID *DispatchContext,\r
498 IN OUT VOID *CommBuffer,\r
499 IN OUT UINTN *CommBufferSize\r
500 )\r
501/*++\r
502\r
503Routine Description:\r
65aec008 504 SMI handler to restore QncS3 code & context for S3 path\r
b303605e
MK
505 This will be only triggered when BootScript got executed during resume\r
506\r
507Arguments:\r
508 DispatchHandle - EFI Handle\r
509 DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT\r
510\r
511Returns:\r
512 Nothing\r
513\r
514--*/\r
515{\r
516 //\r
517 // Restore to original address by default\r
518 //\r
519 RestoreLockBox(&gQncS3CodeInLockBoxGuid, NULL, NULL);\r
520 RestoreLockBox(&gQncS3ContextInLockBoxGuid, NULL, NULL);\r
521 return EFI_SUCCESS;\r
522}\r
523\r
524EFI_STATUS\r
525DisableAcpiCallback (\r
526 IN EFI_HANDLE DispatchHandle,\r
527 IN CONST VOID *DispatchContext,\r
528 IN OUT VOID *CommBuffer,\r
529 IN OUT UINTN *CommBufferSize\r
530 )\r
531/*++\r
532\r
533Routine Description:\r
534 SMI handler to disable ACPI mode\r
535\r
536 Dispatched on reads from APM port with value 0xA1\r
537\r
538 ACPI events are disabled and ACPI event status is cleared.\r
539 SCI mode is then disabled.\r
540 Clear all ACPI event status and disable all ACPI events\r
541 Disable PM sources except power button\r
542 Clear status bits\r
543 Disable GPE0 sources\r
544 Clear status bits\r
545 Disable GPE1 sources\r
546 Clear status bits\r
547 Disable SCI\r
548\r
549Arguments:\r
550 DispatchHandle - EFI Handle\r
551 DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT\r
552\r
553Returns:\r
554 Nothing\r
555\r
556--*/\r
557{\r
558 EFI_STATUS Status;\r
559 UINT16 Pm1Cnt;\r
560\r
561 Status = GetAllQncPmBase (gSmst);\r
562 ASSERT_EFI_ERROR (Status);\r
563 Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);\r
564\r
565 //\r
566 // Disable SCI\r
567 //\r
568 Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SCIEN;\r
569\r
570 IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);\r
571\r
572 return EFI_SUCCESS;\r
573}\r
574\r
575EFI_STATUS\r
576EnableAcpiCallback (\r
577 IN EFI_HANDLE DispatchHandle,\r
578 IN CONST VOID *DispatchContext,\r
579 IN OUT VOID *CommBuffer,\r
580 IN OUT UINTN *CommBufferSize\r
581 )\r
582/*++\r
583\r
584Routine Description:\r
585 SMI handler to enable ACPI mode\r
586\r
587 Dispatched on reads from APM port with value 0xA0\r
588\r
589 Disables the SW SMI Timer.\r
590 ACPI events are disabled and ACPI event status is cleared.\r
591 SCI mode is then enabled.\r
592\r
593 Disable SW SMI Timer\r
594\r
595 Clear all ACPI event status and disable all ACPI events\r
596 Disable PM sources except power button\r
597 Clear status bits\r
598\r
599 Disable GPE0 sources\r
600 Clear status bits\r
601\r
602 Disable GPE1 sources\r
603 Clear status bits\r
604\r
605 Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)\r
606\r
607 Enable SCI\r
608\r
609Arguments:\r
610 DispatchHandle - EFI Handle\r
611 DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT\r
612\r
613Returns:\r
614 Nothing\r
615\r
616--*/\r
617{\r
618 EFI_STATUS Status;\r
619 UINT32 SmiEn;\r
620 UINT16 Pm1Cnt;\r
621 UINT8 Data8;\r
622\r
623 Status = GetAllQncPmBase (gSmst);\r
624 ASSERT_EFI_ERROR (Status);\r
625\r
626 SmiEn = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);\r
627\r
628 //\r
629 // Disable SW SMI Timer\r
630 //\r
631 SmiEn &= ~(B_QNC_GPE0BLK_SMIE_SWT);\r
632 IoWrite32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE, SmiEn);\r
633\r
634 //\r
635 // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)\r
636 //\r
637 Data8 = RTC_ADDRESS_REGISTER_D;\r
638 IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);\r
639 Data8 = 0x0;\r
640 IoWrite8 (R_IOPORT_CMOS_STANDARD_DATA, Data8);\r
641\r
642 //\r
643 // Enable SCI\r
644 //\r
645 Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);\r
646 Pm1Cnt |= B_QNC_PM1BLK_PM1C_SCIEN;\r
647 IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);\r
648\r
649 //\r
650 // Do platform specific stuff for ACPI enable SMI\r
651 //\r
652\r
653\r
654 return EFI_SUCCESS;\r
655}\r
656\r
657EFI_STATUS\r
658SxSleepEntryCallBack (\r
659 IN EFI_HANDLE DispatchHandle,\r
660 IN CONST VOID *DispatchContext,\r
661 IN OUT VOID *CommBuffer,\r
662 IN OUT UINTN *CommBufferSize\r
663 )\r
664/*++\r
665\r
666Routine Description:\r
667\r
668 Callback function entry for Sx sleep state.\r
669\r
670Arguments:\r
671\r
672 DispatchHandle - The handle of this callback, obtained when registering.\r
673 DispatchContext - The predefined context which contained sleep type and phase.\r
674\r
675Returns:\r
676\r
677 EFI_SUCCESS - Operation successfully performed.\r
678 EFI_INVALID_PARAMETER - Invalid parameter passed in.\r
679\r
680--*/\r
681{\r
682 EFI_STATUS Status;\r
683 UINT8 Data8;\r
684 UINT16 Data16;\r
685 UINT32 Data32;\r
686\r
687 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeS3SuspendStart));\r
688\r
689 //\r
690 // Reget QNC power mgmr regs base in case of OS changing it at runtime\r
691 //\r
692 Status = GetAllQncPmBase (gSmst);\r
693\r
694 //\r
695 // Clear RTC Alarm (if set)\r
696 //\r
697 Data8 = RTC_ADDRESS_REGISTER_C;\r
698 IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);\r
699 Data8 = IoRead8 (R_IOPORT_CMOS_STANDARD_DATA);\r
700\r
701 //\r
702 // Clear all ACPI status bits\r
703 //\r
704 Data32 = B_QNC_GPE0BLK_GPE0S_ALL;\r
705 Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0S, 1, &Data32 );\r
706 Data16 = B_QNC_PM1BLK_PM1S_ALL;\r
707 Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1S, 1, &Data16 );\r
708\r
709 //\r
710 // Handling S1 - setting appropriate wake bits in GPE0_EN\r
711 //\r
712 if ((DispatchHandle == mAcpiSmm.S1SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS1)) {\r
713 //\r
714 // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN\r
715 //\r
716 Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
717 Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);\r
718 Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
719\r
720 //\r
721 // Enable bit10 (RTC) in PM1E\r
722 //\r
723 Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
724 Data16 |= B_QNC_PM1BLK_PM1E_RTC;\r
725 Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
726\r
727 return EFI_SUCCESS;\r
728 }\r
729\r
730 //\r
731 // Handling S4, S5 and WOL - setting appropriate wake bits in GPE0_EN\r
732 //\r
733 if (((DispatchHandle == mAcpiSmm.S4SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS4)) ||\r
734 ((DispatchHandle == mAcpiSmm.S5SoftOffEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS5))\r
735 ) {\r
736 //\r
737 // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN\r
738 // Enable the WOL bits in GPE0_EN reg here for PME\r
739 //\r
740 Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
741 Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);\r
742 Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
743\r
744 //\r
745 // Enable bit10 (RTC) in PM1E\r
746 //\r
747 Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
748 Data16 |= B_QNC_PM1BLK_PM1E_RTC;\r
749 Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
750\r
751 } else {\r
752\r
753 if ((DispatchHandle != mAcpiSmm.S3SleepEntryHandle) || (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type != SxS3)) {\r
754 return EFI_INVALID_PARAMETER;\r
755 }\r
756\r
757 Status = SaveRuntimeScriptTable (gSmst);\r
758 if (EFI_ERROR (Status)) {\r
759 return Status;\r
760 }\r
761\r
762 //\r
763 // Enable bit13 (EGPE), 14 (GPIO), 17 (PCIE) in GPE0_EN\r
764 // Enable the WOL bits in GPE0_EN reg here for PME\r
765 //\r
766 Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
767 Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);\r
768 Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r
769\r
770 //\r
771 // Enable bit10 (RTC) in PM1E\r
772 //\r
773 Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
774 Data16 |= B_QNC_PM1BLK_PM1E_RTC;\r
775 Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r
776 }\r
777\r
778 //\r
779 // When entering a power-managed state like S3,\r
780 // PERST# must be asserted in advance of power-off.\r
781 //\r
782 PlatformPERSTAssert (mPlatformType);\r
783\r
784 return EFI_SUCCESS;\r
785}\r
786\r
787EFI_STATUS\r
788GetAllQncPmBase (\r
789 IN EFI_SMM_SYSTEM_TABLE2 *Smst\r
790 )\r
791/*++\r
792\r
793Routine Description:\r
794\r
795 Get QNC chipset LPC Power Management I/O Base at runtime.\r
796\r
797Arguments:\r
798\r
799 Smst - The standard SMM system table.\r
800\r
801Returns:\r
802\r
803 EFI_SUCCESS - Successfully init the device.\r
804 Other - Error occured whening calling Dxe lib functions.\r
805\r
806--*/\r
807{\r
808 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
809 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
810\r
811 //\r
812 // Quark does not support Changing Primary SoC IOBARs from what was\r
813 // setup in SEC/PEI UEFI stages.\r
814 //\r
815 ASSERT (mAcpiSmm.QncPmBase == (UINT32) PcdGet16 (PcdPm1blkIoBaseAddress));\r
816 ASSERT (mAcpiSmm.QncGpe0Base == (UINT32) PcdGet16 (PcdGpe0blkIoBaseAddress));\r
817 return EFI_SUCCESS;\r
818}\r
819\r
820EFI_STATUS\r
821SaveRuntimeScriptTable (\r
822 IN EFI_SMM_SYSTEM_TABLE2 *Smst\r
823 )\r
824{\r
825 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r
826 UINT32 Data32;\r
827 UINT16 Data16;\r
828 UINT8 Mask;\r
829 UINTN Index;\r
830 UINTN Offset;\r
831 UINT16 DeviceId;\r
832\r
833 //\r
834 // Check what Soc we are running on (read Host bridge DeviceId)\r
835 //\r
836 DeviceId = QncGetSocDeviceId();\r
837\r
838 //\r
839 // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM\r
840 // and vital to S3 resume. That's why we put save code here\r
841 //\r
842 Index = 0;\r
843 while (mPciCfgRegTable[Index] != PCI_DEVICE_END) {\r
844\r
845 PciAddress.Bus = mPciCfgRegTable[Index++];\r
846 PciAddress.Device = mPciCfgRegTable[Index++];\r
847 PciAddress.Function = mPciCfgRegTable[Index++];\r
848 PciAddress.Register = 0;\r
849 PciAddress.ExtendedRegister = 0;\r
850\r
851 Data16 = PciRead16 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));\r
852 if (Data16 == 0xFFFF) {\r
853 Index += 8;\r
854 continue;\r
855 }\r
856\r
857 for (Offset = 0, Mask = 0x01; Offset < 256; Offset += 4, Mask <<= 1) {\r
858\r
859 if (Mask == 0x00) {\r
860 Mask = 0x01;\r
861 }\r
862\r
863 if (mPciCfgRegTable[Index + Offset / 32] & Mask) {\r
864\r
865 PciAddress.Register = (UINT8) Offset;\r
866 Data32 = PciRead32 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));\r
867\r
868\r
869 //\r
870 // Save latest settings to runtime script table\r
871 //\r
872 S3BootScriptSavePciCfgWrite (\r
873 S3BootScriptWidthUint32,\r
874 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)),\r
875 1,\r
876 &Data32\r
877 );\r
878 }\r
879 }\r
880\r
881 Index += 8;\r
882\r
883 }\r
884\r
885 //\r
886 // Save message bus registers\r
887 //\r
888 Index = 0;\r
889 while (QNCS3SaveExtReg[Index] != 0xFF) {\r
890 Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
891\r
892 //\r
893 // Save IMR settings with IMR protection disabled initially\r
894 // HMBOUND and IMRs will be locked just before jumping to the OS waking vector\r
895 //\r
896 if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {\r
897 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
898 Data32 &= ~IMR_LOCK;\r
899 if (DeviceId == QUARK2_MC_DEVICE_ID) {\r
900 Data32 &= ~IMR_EN;\r
901 }\r
902 }\r
903 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
904 Data32 = (UINT32)IMRX_ALL_ACCESS;\r
905 }\r
906 }\r
907\r
908 //\r
909 // Save latest settings to runtime script table\r
910 //\r
911 S3BootScriptSavePciCfgWrite (\r
912 S3BootScriptWidthUint32,\r
913 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),\r
914 1,\r
915 &Data32\r
916 );\r
917\r
918 Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
919\r
920 S3BootScriptSavePciCfgWrite (\r
921 S3BootScriptWidthUint32,\r
922 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r
923 1,\r
924 &Data32\r
925 );\r
926 Index += 2;\r
927 }\r
928\r
929 Index = 0;\r
930 while (QNCS3SaveExtReg[Index] != 0xFF) {\r
931 //\r
932 // Save IMR settings with IMR protection enabled (above script was to handle restoring all settings first - now we want to enable)\r
933 //\r
934 if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {\r
935 if (DeviceId == QUARK2_MC_DEVICE_ID) {\r
936 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
937 Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
938 Data32 &= ~IMR_LOCK;\r
939\r
940 //\r
941 // Save latest settings to runtime script table\r
942 //\r
943 S3BootScriptSavePciCfgWrite (\r
944 S3BootScriptWidthUint32,\r
945 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),\r
946 1,\r
947 &Data32\r
948 );\r
949\r
950 Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
951\r
952 S3BootScriptSavePciCfgWrite (\r
953 S3BootScriptWidthUint32,\r
954 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r
955 1,\r
956 &Data32\r
957 );\r
958 }\r
959 } else {\r
960 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
961 Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
962\r
963 //\r
964 // Save latest settings to runtime script table\r
965 //\r
966 S3BootScriptSavePciCfgWrite (\r
967 S3BootScriptWidthUint32,\r
968 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),\r
969 1,\r
970 &Data32\r
971 );\r
972\r
973 Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r
974\r
975 S3BootScriptSavePciCfgWrite (\r
976 S3BootScriptWidthUint32,\r
977 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r
978 1,\r
979 &Data32\r
980 );\r
981 }\r
982 }\r
983 }\r
984 Index += 2;\r
985 }\r
986\r
987 // Check if ECC scrub enabled and need re-enabling on resume\r
988 // All scrub related configuration registers are saved on suspend\r
989 // as part of QNCS3SaveExtReg configuration table script.\r
990 // The code below extends the S3 resume script with scrub reactivation\r
991 // message (if needed only)\r
992 Data32 = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG);\r
993 if( 0 != (Data32 & SCRUB_CFG_ACTIVE)) {\r
994\r
995 Data32 = SCRUB_RESUME_MSG();\r
996\r
997 S3BootScriptSavePciCfgWrite (\r
998 S3BootScriptWidthUint32,\r
999 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r
1000 1,\r
1001 &Data32\r
1002 );\r
1003 }\r
1004\r
1005 //\r
1006 // Save I/O ports to S3 script table\r
1007 //\r
1008\r
1009 //\r
1010 // Important to trap Sx for SMM\r
1011 //\r
1012 Data32 = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);\r
1013 S3BootScriptSaveIoWrite(S3BootScriptWidthUint32, (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE), 1, &Data32);\r
1014\r
1015 return EFI_SUCCESS;\r
1016}\r
1017\r