2 ACPISMM Driver implementation file.
4 This is QNC Smm platform driver
6 Copyright (c) 2013-2016 Intel Corporation.
8 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <AcpiSmmPlatform.h>
15 #define PCILIB_TO_COMMON_ADDRESS(Address) \
16 ((UINT64) ((((UINTN) ((Address>>20) & 0xff)) << 24) + (((UINTN) ((Address>>15) & 0x1f)) << 16) + (((UINTN) ((Address>>12) & 0x07)) << 8) + ((UINTN) (Address & 0xfff ))))
19 // Modular variables needed by this driver
21 EFI_ACPI_SMM_DEV mAcpiSmm
;
23 UINT8 mPciCfgRegTable
[] = {
25 // Logic to decode the table masks to arrive at the registers saved
26 // Dword Registers are saved. For a given mask, the Base+offset register
27 // will be saved as in the table below.
28 // (example) To save register 0x24, 0x28 the mask at the Base 0x20 will be 0x06
29 // Base 0x00 0x20 0x40 0x60 0x80 0xA0 0xC0 0xE0
43 // 00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
44 // Only Bus 0 device is supported now
48 // Quark South Cluster devices
50 PCI_DEVICE (0, 20, 0),
51 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
53 PCI_DEVICE (0, 20, 1),
54 PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
56 PCI_DEVICE (0, 20, 2),
57 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
59 PCI_DEVICE (0, 20, 3),
60 PCI_REG_MASK (0x18, 0x98, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00),
62 PCI_DEVICE (0, 20, 4),
63 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
65 PCI_DEVICE (0, 20, 5),
66 PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
68 PCI_DEVICE (0, 20, 6),
69 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
71 PCI_DEVICE (0, 20, 7),
72 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
74 PCI_DEVICE (0, 21, 0),
75 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
77 PCI_DEVICE (0, 21, 1),
78 PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
80 PCI_DEVICE (0, 21, 2),
81 PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
84 // Quark North Cluster devices
87 PCI_REG_MASK (0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
89 PCI_DEVICE (0, 23, 0),
90 PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),
92 PCI_DEVICE (0, 23, 1),
93 PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),
95 PCI_DEVICE (0, 31, 0),
96 PCI_REG_MASK (0x00, 0x08, 0x4E, 0x03, 0x02, 0x00, 0x60, 0x10),
101 EFI_PLATFORM_TYPE mPlatformType
;
103 // These registers have to set in byte order
104 const UINT8 QNCS3SaveExtReg
[] = {
105 QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HSMMC
, // SMRAM settings
107 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR0
+QUARK_NC_MEMORY_MANAGER_IMRXL
,
108 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR0
+QUARK_NC_MEMORY_MANAGER_IMRXH
,
109 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR0
+QUARK_NC_MEMORY_MANAGER_IMRXRM
,
110 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR0
+QUARK_NC_MEMORY_MANAGER_IMRXWM
,
112 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR1
+QUARK_NC_MEMORY_MANAGER_IMRXL
,
113 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR1
+QUARK_NC_MEMORY_MANAGER_IMRXH
,
114 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR1
+QUARK_NC_MEMORY_MANAGER_IMRXRM
,
115 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR1
+QUARK_NC_MEMORY_MANAGER_IMRXWM
,
117 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR2
+QUARK_NC_MEMORY_MANAGER_IMRXL
,
118 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR2
+QUARK_NC_MEMORY_MANAGER_IMRXH
,
119 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR2
+QUARK_NC_MEMORY_MANAGER_IMRXRM
,
120 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR2
+QUARK_NC_MEMORY_MANAGER_IMRXWM
,
122 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR3
+QUARK_NC_MEMORY_MANAGER_IMRXL
,
123 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR3
+QUARK_NC_MEMORY_MANAGER_IMRXH
,
124 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR3
+QUARK_NC_MEMORY_MANAGER_IMRXRM
,
125 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR3
+QUARK_NC_MEMORY_MANAGER_IMRXWM
,
127 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR4
+QUARK_NC_MEMORY_MANAGER_IMRXL
,
128 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR4
+QUARK_NC_MEMORY_MANAGER_IMRXH
,
129 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR4
+QUARK_NC_MEMORY_MANAGER_IMRXRM
,
130 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR4
+QUARK_NC_MEMORY_MANAGER_IMRXWM
,
132 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR5
+QUARK_NC_MEMORY_MANAGER_IMRXL
,
133 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR5
+QUARK_NC_MEMORY_MANAGER_IMRXH
,
134 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR5
+QUARK_NC_MEMORY_MANAGER_IMRXRM
,
135 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR5
+QUARK_NC_MEMORY_MANAGER_IMRXWM
,
137 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR6
+QUARK_NC_MEMORY_MANAGER_IMRXL
,
138 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR6
+QUARK_NC_MEMORY_MANAGER_IMRXH
,
139 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR6
+QUARK_NC_MEMORY_MANAGER_IMRXRM
,
140 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR6
+QUARK_NC_MEMORY_MANAGER_IMRXWM
,
142 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR7
+QUARK_NC_MEMORY_MANAGER_IMRXL
,
143 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR7
+QUARK_NC_MEMORY_MANAGER_IMRXH
,
144 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR7
+QUARK_NC_MEMORY_MANAGER_IMRXRM
,
145 QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
, QUARK_NC_MEMORY_MANAGER_IMR7
+QUARK_NC_MEMORY_MANAGER_IMRXWM
,
147 QUARK_NC_RMU_SB_PORT_ID
, QUARK_NC_ECC_SCRUB_END_MEM_REG
, // ECC Scrub settings
148 QUARK_NC_RMU_SB_PORT_ID
, QUARK_NC_ECC_SCRUB_START_MEM_REG
,
149 QUARK_NC_RMU_SB_PORT_ID
, QUARK_NC_ECC_SCRUB_NEXT_READ_REG
,
150 QUARK_NC_RMU_SB_PORT_ID
, QUARK_NC_ECC_SCRUB_CONFIG_REG
,
156 Allocate EfiACPIMemoryNVS below 4G memory address.
158 This function allocates EfiACPIMemoryNVS below 4G memory address.
160 @param Size Size of memory to allocate.
162 @return Allocated address for output.
166 AllocateAcpiNvsMemoryBelow4G (
171 EFI_PHYSICAL_ADDRESS Address
;
175 Pages
= EFI_SIZE_TO_PAGES (Size
);
176 Address
= 0xffffffff;
178 Status
= gBS
->AllocatePages (
184 if (EFI_ERROR (Status
)) {
188 Buffer
= (VOID
*) (UINTN
) Address
;
189 ZeroMem (Buffer
, Size
);
197 UINTN SystemMemoryLength
204 Reserved S3 memory for InstallS3Memory
211 EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.
212 EFI_SUCCESS - Function has completed successfully.
218 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK
*DescriptorBlock
;
219 VOID
*AcpiReservedBase
;
224 RESERVED_ACPI_S3_RANGE
*AcpiS3Range
;
226 // Get Hob list for SMRAM desc
228 GuidHob
= GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid
);
230 DescriptorBlock
= GET_GUID_HOB_DATA (GuidHob
);
231 ASSERT (DescriptorBlock
);
234 // Use the hob to get SMRAM capabilities
236 TsegIndex
= DescriptorBlock
->NumberOfSmmReservedRegions
- 1;
237 ASSERT (TsegIndex
<= (MAX_SMRAM_RANGES
- 1));
238 TsegBase
= (UINTN
)DescriptorBlock
->Descriptor
[TsegIndex
].PhysicalStart
;
239 TsegSize
= (UINTN
)DescriptorBlock
->Descriptor
[TsegIndex
].PhysicalSize
;
241 DEBUG ((EFI_D_INFO
, "SMM Base: %08X\n", TsegBase
));
242 DEBUG ((EFI_D_INFO
, "SMM Size: %08X\n", TsegSize
));
245 // Now find the location of the data structure that is used to store the address
246 // of the S3 reserved memory.
248 AcpiS3Range
= (RESERVED_ACPI_S3_RANGE
*) (UINTN
) (TsegBase
+ RESERVED_ACPI_S3_RANGE_OFFSET
);
251 // Allocate reserved ACPI memory for S3 resume. Pointer to this region is
252 // stored in SMRAM in the first page of TSEG.
254 AcpiReservedBase
= AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize
));
255 if (AcpiReservedBase
!= NULL
) {
256 AcpiS3Range
->AcpiReservedMemoryBase
= (UINT32
)(UINTN
) AcpiReservedBase
;
257 AcpiS3Range
->AcpiReservedMemorySize
= PcdGet32 (PcdS3AcpiReservedMemorySize
);
259 AcpiS3Range
->SystemMemoryLength
= (UINT32
)SystemMemoryLength
;
261 DEBUG ((EFI_D_INFO
, "S3 Memory Base: %08X\n", AcpiS3Range
->AcpiReservedMemoryBase
));
262 DEBUG ((EFI_D_INFO
, "S3 Memory Size: %08X\n", AcpiS3Range
->AcpiReservedMemorySize
));
263 DEBUG ((EFI_D_INFO
, "S3 SysMemoryLength: %08X\n", AcpiS3Range
->SystemMemoryLength
));
271 InitAcpiSmmPlatform (
272 IN EFI_HANDLE ImageHandle
,
273 IN EFI_SYSTEM_TABLE
*SystemTable
279 Initializes the SMM S3 Handler Driver.
283 ImageHandle - The image handle of Sleep State Wake driver.
284 SystemTable - The starndard EFI system table.
288 EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.
289 EFI_SUCCESS - Function has completed successfully.
290 Other - Error occured during execution.
295 EFI_GLOBAL_NVS_AREA_PROTOCOL
*AcpiNvsProtocol
= NULL
;
297 EFI_PEI_HOB_POINTERS Hob
;
299 Status
= gBS
->LocateProtocol (
300 &gEfiGlobalNvsAreaProtocolGuid
,
302 (VOID
**) &AcpiNvsProtocol
304 ASSERT_EFI_ERROR (Status
);
306 mAcpiSmm
.BootScriptSaved
= 0;
308 mPlatformType
= (EFI_PLATFORM_TYPE
)PcdGet16 (PcdPlatformType
);
311 // Calculate the system memory length by memory hobs
313 MemoryLength
= 0x100000;
314 Hob
.Raw
= GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
);
315 ASSERT (Hob
.Raw
!= NULL
);
316 while ((Hob
.Raw
!= NULL
) && (!END_OF_HOB_LIST (Hob
))) {
317 if (Hob
.ResourceDescriptor
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) {
319 // Skip the memory region below 1MB
321 if (Hob
.ResourceDescriptor
->PhysicalStart
>= 0x100000) {
322 MemoryLength
+= (UINTN
)Hob
.ResourceDescriptor
->ResourceLength
;
325 Hob
.Raw
= GET_NEXT_HOB (Hob
);
326 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
, Hob
.Raw
);
329 ReservedS3Memory(MemoryLength
);
332 // Locate and Register to Parent driver
334 Status
= RegisterToDispatchDriver ();
335 ASSERT_EFI_ERROR (Status
);
341 RegisterToDispatchDriver (
348 Register to dispatch driver.
356 EFI_SUCCESS - Successfully init the device.
357 Other - Error occured whening calling Dxe lib functions.
363 EFI_SMM_SX_DISPATCH2_PROTOCOL
*SxDispatch
;
364 EFI_SMM_SW_DISPATCH2_PROTOCOL
*SwDispatch
;
365 EFI_SMM_SX_REGISTER_CONTEXT
*EntryDispatchContext
;
366 EFI_SMM_SX_REGISTER_CONTEXT
*EntryS1DispatchContext
;
367 EFI_SMM_SX_REGISTER_CONTEXT
*EntryS3DispatchContext
;
368 EFI_SMM_SX_REGISTER_CONTEXT
*EntryS4DispatchContext
;
369 EFI_SMM_SX_REGISTER_CONTEXT
*EntryS5DispatchContext
;
370 EFI_SMM_SW_REGISTER_CONTEXT
*SwContext
;
371 EFI_SMM_SW_REGISTER_CONTEXT
*AcpiDisableSwContext
;
372 EFI_SMM_SW_REGISTER_CONTEXT
*AcpiEnableSwContext
;
374 Status
= gSmst
->SmmLocateProtocol (
375 &gEfiSmmSxDispatch2ProtocolGuid
,
377 (VOID
**) &SxDispatch
379 if (EFI_ERROR (Status
)) {
383 Status
= gSmst
->SmmLocateProtocol (
384 &gEfiSmmSwDispatch2ProtocolGuid
,
386 (VOID
**) &SwDispatch
388 if (EFI_ERROR (Status
)) {
392 Length
= sizeof (EFI_SMM_SX_REGISTER_CONTEXT
) * 4 + sizeof (EFI_SMM_SW_REGISTER_CONTEXT
) * 2;
393 Status
= gSmst
->SmmAllocatePool (
394 EfiRuntimeServicesData
,
396 (VOID
**) &EntryDispatchContext
398 if (EFI_ERROR (Status
)) {
402 SetMem (EntryDispatchContext
, Length
, 0);
404 EntryS1DispatchContext
= EntryDispatchContext
++;
405 EntryS3DispatchContext
= EntryDispatchContext
++;
406 EntryS4DispatchContext
= EntryDispatchContext
++;
407 EntryS5DispatchContext
= EntryDispatchContext
++;
409 SwContext
= (EFI_SMM_SW_REGISTER_CONTEXT
*)EntryDispatchContext
;
410 AcpiDisableSwContext
= SwContext
++;
411 AcpiEnableSwContext
= SwContext
++;
414 // Register the enable handler
416 AcpiEnableSwContext
->SwSmiInputValue
= EFI_ACPI_ACPI_ENABLE
;
417 Status
= SwDispatch
->Register (
421 &(mAcpiSmm
.DisableAcpiHandle
)
425 // Register the disable handler
427 AcpiDisableSwContext
->SwSmiInputValue
= EFI_ACPI_ACPI_DISABLE
;
428 Status
= SwDispatch
->Register (
431 AcpiDisableSwContext
,
432 &(mAcpiSmm
.EnableAcpiHandle
)
437 // Register entry phase call back function for S1
439 EntryS1DispatchContext
->Type
= SxS1
;
440 EntryS1DispatchContext
->Phase
= SxEntry
;
441 Status
= SxDispatch
->Register (
443 SxSleepEntryCallBack
,
444 EntryS1DispatchContext
,
445 &(mAcpiSmm
.S1SleepEntryHandle
)
449 // Register entry phase call back function
451 EntryS3DispatchContext
->Type
= SxS3
;
452 EntryS3DispatchContext
->Phase
= SxEntry
;
453 Status
= SxDispatch
->Register (
455 SxSleepEntryCallBack
,
456 EntryS3DispatchContext
,
457 &(mAcpiSmm
.S3SleepEntryHandle
)
461 // Register entry phase call back function for S4
463 EntryS4DispatchContext
->Type
= SxS4
;
464 EntryS4DispatchContext
->Phase
= SxEntry
;
465 Status
= SxDispatch
->Register (
467 SxSleepEntryCallBack
,
468 EntryS4DispatchContext
,
469 &(mAcpiSmm
.S4SleepEntryHandle
)
473 // Register callback for S5 in order to workaround the LAN shutdown issue
475 EntryS5DispatchContext
->Type
= SxS5
;
476 EntryS5DispatchContext
->Phase
= SxEntry
;
477 Status
= SxDispatch
->Register (
479 SxSleepEntryCallBack
,
480 EntryS5DispatchContext
,
481 &(mAcpiSmm
.S5SoftOffEntryHandle
)
489 RestoreQncS3SwCallback (
490 IN EFI_HANDLE DispatchHandle
,
491 IN CONST VOID
*DispatchContext
,
492 IN OUT VOID
*CommBuffer
,
493 IN OUT UINTN
*CommBufferSize
498 SMI handler to restore QncS3 code & context for S3 path
499 This will be only triggered when BootScript got executed during resume
502 DispatchHandle - EFI Handle
503 DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
511 // Restore to original address by default
513 RestoreLockBox(&gQncS3CodeInLockBoxGuid
, NULL
, NULL
);
514 RestoreLockBox(&gQncS3ContextInLockBoxGuid
, NULL
, NULL
);
519 DisableAcpiCallback (
520 IN EFI_HANDLE DispatchHandle
,
521 IN CONST VOID
*DispatchContext
,
522 IN OUT VOID
*CommBuffer
,
523 IN OUT UINTN
*CommBufferSize
528 SMI handler to disable ACPI mode
530 Dispatched on reads from APM port with value 0xA1
532 ACPI events are disabled and ACPI event status is cleared.
533 SCI mode is then disabled.
534 Clear all ACPI event status and disable all ACPI events
535 Disable PM sources except power button
544 DispatchHandle - EFI Handle
545 DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
555 Status
= GetAllQncPmBase (gSmst
);
556 ASSERT_EFI_ERROR (Status
);
557 Pm1Cnt
= IoRead16 (mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1C
);
562 Pm1Cnt
&= ~B_QNC_PM1BLK_PM1C_SCIEN
;
564 IoWrite16 (mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1C
, Pm1Cnt
);
571 IN EFI_HANDLE DispatchHandle
,
572 IN CONST VOID
*DispatchContext
,
573 IN OUT VOID
*CommBuffer
,
574 IN OUT UINTN
*CommBufferSize
579 SMI handler to enable ACPI mode
581 Dispatched on reads from APM port with value 0xA0
583 Disables the SW SMI Timer.
584 ACPI events are disabled and ACPI event status is cleared.
585 SCI mode is then enabled.
589 Clear all ACPI event status and disable all ACPI events
590 Disable PM sources except power button
599 Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
604 DispatchHandle - EFI Handle
605 DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
617 Status
= GetAllQncPmBase (gSmst
);
618 ASSERT_EFI_ERROR (Status
);
620 SmiEn
= IoRead32 (mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_SMIE
);
623 // Disable SW SMI Timer
625 SmiEn
&= ~(B_QNC_GPE0BLK_SMIE_SWT
);
626 IoWrite32 (mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_SMIE
, SmiEn
);
629 // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
631 Data8
= RTC_ADDRESS_REGISTER_D
;
632 IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX
, Data8
);
634 IoWrite8 (R_IOPORT_CMOS_STANDARD_DATA
, Data8
);
639 Pm1Cnt
= IoRead16 (mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1C
);
640 Pm1Cnt
|= B_QNC_PM1BLK_PM1C_SCIEN
;
641 IoWrite16 (mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1C
, Pm1Cnt
);
644 // Do platform specific stuff for ACPI enable SMI
652 SxSleepEntryCallBack (
653 IN EFI_HANDLE DispatchHandle
,
654 IN CONST VOID
*DispatchContext
,
655 IN OUT VOID
*CommBuffer
,
656 IN OUT UINTN
*CommBufferSize
662 Callback function entry for Sx sleep state.
666 DispatchHandle - The handle of this callback, obtained when registering.
667 DispatchContext - The predefined context which contained sleep type and phase.
671 EFI_SUCCESS - Operation successfully performed.
672 EFI_INVALID_PARAMETER - Invalid parameter passed in.
681 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, PcdGet32 (PcdProgressCodeS3SuspendStart
));
684 // Reget QNC power mgmr regs base in case of OS changing it at runtime
686 Status
= GetAllQncPmBase (gSmst
);
689 // Clear RTC Alarm (if set)
691 Data8
= RTC_ADDRESS_REGISTER_C
;
692 IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX
, Data8
);
693 Data8
= IoRead8 (R_IOPORT_CMOS_STANDARD_DATA
);
696 // Clear all ACPI status bits
698 Data32
= B_QNC_GPE0BLK_GPE0S_ALL
;
699 Status
= gSmst
->SmmIo
.Io
.Write( &gSmst
->SmmIo
, SMM_IO_UINT32
, mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_GPE0S
, 1, &Data32
);
700 Data16
= B_QNC_PM1BLK_PM1S_ALL
;
701 Status
= gSmst
->SmmIo
.Io
.Write( &gSmst
->SmmIo
, SMM_IO_UINT16
, mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1S
, 1, &Data16
);
704 // Handling S1 - setting appropriate wake bits in GPE0_EN
706 if ((DispatchHandle
== mAcpiSmm
.S1SleepEntryHandle
) && (((EFI_SMM_SX_REGISTER_CONTEXT
*)DispatchContext
)->Type
== SxS1
)) {
708 // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN
710 Status
= gSmst
->SmmIo
.Io
.Read( &gSmst
->SmmIo
, SMM_IO_UINT32
, mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_GPE0E
, 1, &Data32
);
711 Data32
|= (B_QNC_GPE0BLK_GPE0E_EGPE
| B_QNC_GPE0BLK_GPE0E_GPIO
| B_QNC_GPE0BLK_GPE0E_PCIE
);
712 Status
= gSmst
->SmmIo
.Io
.Write( &gSmst
->SmmIo
, SMM_IO_UINT32
, mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_GPE0E
, 1, &Data32
);
715 // Enable bit10 (RTC) in PM1E
717 Status
= gSmst
->SmmIo
.Io
.Read( &gSmst
->SmmIo
, SMM_IO_UINT16
, mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1E
, 1, &Data16
);
718 Data16
|= B_QNC_PM1BLK_PM1E_RTC
;
719 Status
= gSmst
->SmmIo
.Io
.Write( &gSmst
->SmmIo
, SMM_IO_UINT16
, mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1E
, 1, &Data16
);
725 // Handling S4, S5 and WOL - setting appropriate wake bits in GPE0_EN
727 if (((DispatchHandle
== mAcpiSmm
.S4SleepEntryHandle
) && (((EFI_SMM_SX_REGISTER_CONTEXT
*)DispatchContext
)->Type
== SxS4
)) ||
728 ((DispatchHandle
== mAcpiSmm
.S5SoftOffEntryHandle
) && (((EFI_SMM_SX_REGISTER_CONTEXT
*)DispatchContext
)->Type
== SxS5
))
731 // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN
732 // Enable the WOL bits in GPE0_EN reg here for PME
734 Status
= gSmst
->SmmIo
.Io
.Read( &gSmst
->SmmIo
, SMM_IO_UINT32
, mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_GPE0E
, 1, &Data32
);
735 Data32
|= (B_QNC_GPE0BLK_GPE0E_EGPE
| B_QNC_GPE0BLK_GPE0E_GPIO
| B_QNC_GPE0BLK_GPE0E_PCIE
);
736 Status
= gSmst
->SmmIo
.Io
.Write( &gSmst
->SmmIo
, SMM_IO_UINT32
, mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_GPE0E
, 1, &Data32
);
739 // Enable bit10 (RTC) in PM1E
741 Status
= gSmst
->SmmIo
.Io
.Read( &gSmst
->SmmIo
, SMM_IO_UINT16
, mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1E
, 1, &Data16
);
742 Data16
|= B_QNC_PM1BLK_PM1E_RTC
;
743 Status
= gSmst
->SmmIo
.Io
.Write( &gSmst
->SmmIo
, SMM_IO_UINT16
, mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1E
, 1, &Data16
);
747 if ((DispatchHandle
!= mAcpiSmm
.S3SleepEntryHandle
) || (((EFI_SMM_SX_REGISTER_CONTEXT
*)DispatchContext
)->Type
!= SxS3
)) {
748 return EFI_INVALID_PARAMETER
;
751 Status
= SaveRuntimeScriptTable (gSmst
);
752 if (EFI_ERROR (Status
)) {
757 // Enable bit13 (EGPE), 14 (GPIO), 17 (PCIE) in GPE0_EN
758 // Enable the WOL bits in GPE0_EN reg here for PME
760 Status
= gSmst
->SmmIo
.Io
.Read( &gSmst
->SmmIo
, SMM_IO_UINT32
, mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_GPE0E
, 1, &Data32
);
761 Data32
|= (B_QNC_GPE0BLK_GPE0E_EGPE
| B_QNC_GPE0BLK_GPE0E_GPIO
| B_QNC_GPE0BLK_GPE0E_PCIE
);
762 Status
= gSmst
->SmmIo
.Io
.Write( &gSmst
->SmmIo
, SMM_IO_UINT32
, mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_GPE0E
, 1, &Data32
);
765 // Enable bit10 (RTC) in PM1E
767 Status
= gSmst
->SmmIo
.Io
.Read( &gSmst
->SmmIo
, SMM_IO_UINT16
, mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1E
, 1, &Data16
);
768 Data16
|= B_QNC_PM1BLK_PM1E_RTC
;
769 Status
= gSmst
->SmmIo
.Io
.Write( &gSmst
->SmmIo
, SMM_IO_UINT16
, mAcpiSmm
.QncPmBase
+ R_QNC_PM1BLK_PM1E
, 1, &Data16
);
773 // When entering a power-managed state like S3,
774 // PERST# must be asserted in advance of power-off.
776 PlatformPERSTAssert (mPlatformType
);
783 IN EFI_SMM_SYSTEM_TABLE2
*Smst
789 Get QNC chipset LPC Power Management I/O Base at runtime.
793 Smst - The standard SMM system table.
797 EFI_SUCCESS - Successfully init the device.
798 Other - Error occured whening calling Dxe lib functions.
802 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
;
803 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
;
806 // Quark does not support Changing Primary SoC IOBARs from what was
807 // setup in SEC/PEI UEFI stages.
809 ASSERT (mAcpiSmm
.QncPmBase
== (UINT32
) PcdGet16 (PcdPm1blkIoBaseAddress
));
810 ASSERT (mAcpiSmm
.QncGpe0Base
== (UINT32
) PcdGet16 (PcdGpe0blkIoBaseAddress
));
815 SaveRuntimeScriptTable (
816 IN EFI_SMM_SYSTEM_TABLE2
*Smst
819 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
;
828 // Check what Soc we are running on (read Host bridge DeviceId)
830 DeviceId
= QncGetSocDeviceId();
833 // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
834 // and vital to S3 resume. That's why we put save code here
837 while (mPciCfgRegTable
[Index
] != PCI_DEVICE_END
) {
839 PciAddress
.Bus
= mPciCfgRegTable
[Index
++];
840 PciAddress
.Device
= mPciCfgRegTable
[Index
++];
841 PciAddress
.Function
= mPciCfgRegTable
[Index
++];
842 PciAddress
.Register
= 0;
843 PciAddress
.ExtendedRegister
= 0;
845 Data16
= PciRead16 (PCI_LIB_ADDRESS(PciAddress
.Bus
, PciAddress
.Device
, PciAddress
.Function
, PciAddress
.Register
));
846 if (Data16
== 0xFFFF) {
851 for (Offset
= 0, Mask
= 0x01; Offset
< 256; Offset
+= 4, Mask
<<= 1) {
857 if (mPciCfgRegTable
[Index
+ Offset
/ 32] & Mask
) {
859 PciAddress
.Register
= (UINT8
) Offset
;
860 Data32
= PciRead32 (PCI_LIB_ADDRESS(PciAddress
.Bus
, PciAddress
.Device
, PciAddress
.Function
, PciAddress
.Register
));
864 // Save latest settings to runtime script table
866 S3BootScriptSavePciCfgWrite (
867 S3BootScriptWidthUint32
,
868 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(PciAddress
.Bus
, PciAddress
.Device
, PciAddress
.Function
, PciAddress
.Register
)),
880 // Save message bus registers
883 while (QNCS3SaveExtReg
[Index
] != 0xFF) {
884 Data32
= QNCPortRead (QNCS3SaveExtReg
[Index
], QNCS3SaveExtReg
[Index
+ 1]);
887 // Save IMR settings with IMR protection disabled initially
888 // HMBOUND and IMRs will be locked just before jumping to the OS waking vector
890 if (QNCS3SaveExtReg
[Index
] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
) {
891 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
)) {
893 if (DeviceId
== QUARK2_MC_DEVICE_ID
) {
897 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
)) {
898 Data32
= (UINT32
)IMRX_ALL_ACCESS
;
903 // Save latest settings to runtime script table
905 S3BootScriptSavePciCfgWrite (
906 S3BootScriptWidthUint32
,
907 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR
)),
912 Data32
= MESSAGE_WRITE_DW (QNCS3SaveExtReg
[Index
], QNCS3SaveExtReg
[Index
+ 1]);
914 S3BootScriptSavePciCfgWrite (
915 S3BootScriptWidthUint32
,
916 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR
)),
924 while (QNCS3SaveExtReg
[Index
] != 0xFF) {
926 // Save IMR settings with IMR protection enabled (above script was to handle restoring all settings first - now we want to enable)
928 if (QNCS3SaveExtReg
[Index
] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID
) {
929 if (DeviceId
== QUARK2_MC_DEVICE_ID
) {
930 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
)) {
931 Data32
= QNCPortRead (QNCS3SaveExtReg
[Index
], QNCS3SaveExtReg
[Index
+ 1]);
935 // Save latest settings to runtime script table
937 S3BootScriptSavePciCfgWrite (
938 S3BootScriptWidthUint32
,
939 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR
)),
944 Data32
= MESSAGE_WRITE_DW (QNCS3SaveExtReg
[Index
], QNCS3SaveExtReg
[Index
+ 1]);
946 S3BootScriptSavePciCfgWrite (
947 S3BootScriptWidthUint32
,
948 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR
)),
954 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
)) {
955 Data32
= QNCPortRead (QNCS3SaveExtReg
[Index
], QNCS3SaveExtReg
[Index
+ 1]);
958 // Save latest settings to runtime script table
960 S3BootScriptSavePciCfgWrite (
961 S3BootScriptWidthUint32
,
962 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR
)),
967 Data32
= MESSAGE_WRITE_DW (QNCS3SaveExtReg
[Index
], QNCS3SaveExtReg
[Index
+ 1]);
969 S3BootScriptSavePciCfgWrite (
970 S3BootScriptWidthUint32
,
971 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR
)),
981 // Check if ECC scrub enabled and need re-enabling on resume
982 // All scrub related configuration registers are saved on suspend
983 // as part of QNCS3SaveExtReg configuration table script.
984 // The code below extends the S3 resume script with scrub reactivation
985 // message (if needed only)
986 Data32
= QNCPortRead (QUARK_NC_RMU_SB_PORT_ID
, QUARK_NC_ECC_SCRUB_CONFIG_REG
);
987 if( 0 != (Data32
& SCRUB_CFG_ACTIVE
)) {
989 Data32
= SCRUB_RESUME_MSG();
991 S3BootScriptSavePciCfgWrite (
992 S3BootScriptWidthUint32
,
993 PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR
)),
1000 // Save I/O ports to S3 script table
1004 // Important to trap Sx for SMM
1006 Data32
= IoRead32 (mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_SMIE
);
1007 S3BootScriptSaveIoWrite(S3BootScriptWidthUint32
, (mAcpiSmm
.QncGpe0Base
+ R_QNC_GPE0BLK_SMIE
), 1, &Data32
);