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