+++ /dev/null
-/** @file\r
-System reset Library Services. This library class provides a set of\r
-methods to reset whole system with manipulate QNC.\r
-\r
-Copyright (c) 2013-2019 Intel Corporation.\r
-\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <Base.h>\r
-#include <IntelQNCBase.h>\r
-#include <QNCAccess.h>\r
-\r
-#include <Uefi/UefiBaseType.h>\r
-\r
-#include <Library/ResetSystemLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/CpuLib.h>\r
-#include <Library/QNCAccessLib.h>\r
-\r
-//\r
-// Amount of time (seconds) before RTC alarm fires\r
-// This must be < BCD_BASE\r
-//\r
-#define PLATFORM_WAKE_SECONDS_BUFFER 0x06\r
-\r
-//\r
-// RTC 'seconds' above which we will not read to avoid potential rollover\r
-//\r
-#define PLATFORM_RTC_ROLLOVER_LIMIT 0x47\r
-\r
-//\r
-// BCD is base 10\r
-//\r
-#define BCD_BASE 0x0A\r
-\r
-#define PCAT_RTC_ADDRESS_REGISTER 0x70\r
-#define PCAT_RTC_DATA_REGISTER 0x71\r
-\r
-//\r
-// Dallas DS12C887 Real Time Clock\r
-//\r
-#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59\r
-#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59\r
-#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59\r
-#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59\r
-#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM\r
-#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM\r
-#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7\r
-#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31\r
-#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12\r
-#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99\r
-#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]\r
-#define RTC_ADDRESS_REGISTER_B 11 // R/W\r
-#define RTC_ADDRESS_REGISTER_C 12 // RO\r
-#define RTC_ADDRESS_REGISTER_D 13 // RO\r
-#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W\r
-\r
-/**\r
- Wait for an RTC update to happen\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-WaitForRTCUpdate (\r
-VOID\r
-)\r
-{\r
- UINT8 Data8;\r
-\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);\r
- Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
- if ((Data8 & BIT7) == BIT7) {\r
- while ((Data8 & BIT7) == BIT7) {\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);\r
- Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
- }\r
-\r
- } else {\r
- while ((Data8 & BIT7) == 0) {\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);\r
- Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
- }\r
-\r
- while ((Data8 & BIT7) == BIT7) {\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);\r
- Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Calling this function causes a system-wide reset. This sets\r
- all circuitry within the system to its initial state. This type of reset\r
- is asynchronous to system operation and operates without regard to\r
- cycle boundaries.\r
-\r
- System reset should not return, if it returns, it means the system does\r
- not support cold reset.\r
-**/\r
-VOID\r
-EFIAPI\r
-ResetCold (\r
-VOID\r
-)\r
-{\r
- //\r
- // Reference to QuarkNcSocId BWG\r
- // Setting bit 1 will generate a warm reset, driving only RSTRDY# low\r
- //\r
- IoWrite8 (RST_CNT, B_RST_CNT_COLD_RST);\r
-}\r
-\r
-/**\r
- Calling this function causes a system-wide initialization. The processors\r
- are set to their initial state, and pending cycles are not corrupted.\r
-\r
- System reset should not return, if it returns, it means the system does\r
- not support warm reset.\r
-**/\r
-VOID\r
-EFIAPI\r
-ResetWarm (\r
-VOID\r
-)\r
-{\r
- //\r
- // Reference to QuarkNcSocId BWG\r
- // Setting bit 1 will generate a warm reset, driving only RSTRDY# low\r
- //\r
- IoWrite8 (RST_CNT, B_RST_CNT_WARM_RST);\r
-}\r
-\r
-/**\r
- Calling this function causes the system to enter a power state equivalent\r
- to the ACPI G2/S5 or G3 states.\r
-\r
- System shutdown should not return, if it returns, it means the system does\r
- not support shut down reset.\r
-**/\r
-VOID\r
-EFIAPI\r
-ResetShutdown (\r
-VOID\r
-)\r
-{\r
- //\r
- // Reference to QuarkNcSocId BWG\r
- // Disable RTC Alarm : (RTC Enable at PM1BLK + 02h[10]))\r
- //\r
- IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, 0);\r
-\r
- //\r
- // Firstly, GPE0_EN should be disabled to\r
- // avoid any GPI waking up the system from S5\r
- //\r
- IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E, 0);\r
-\r
- //\r
- // Reference to QuarkNcSocId BWG\r
- // Disable Resume Well GPIO : (GPIO bits in GPIOBASE + 34h[8:0])\r
- //\r
- IoWrite32 (PcdGet16 (PcdGbaIoBaseAddress) + R_QNC_GPIO_RGGPE_RESUME_WELL, 0);\r
-\r
- //\r
- // No power button status bit to clear for our platform, go to next step.\r
- //\r
-\r
- //\r
- // Finally, transform system into S5 sleep state\r
- //\r
- IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, 0xffffc3ff, B_QNC_PM1BLK_PM1C_SLPEN | V_S5);\r
-}\r
-\r
-/**\r
- Calling this function causes the system to enter a power state for capsule\r
- update.\r
-\r
- Reset update should not return, if it returns, it means the system does\r
- not support capsule update.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-EnterS3WithImmediateWake (\r
-VOID\r
-)\r
-{\r
- UINT8 Data8;\r
- UINT16 Data16;\r
- UINT32 Data32;\r
- UINTN Eflags;\r
- UINTN RegCr0;\r
- EFI_TIME EfiTime;\r
- UINT32 SmiEnSave;\r
-\r
- Eflags = AsmReadEflags ();\r
- if ( (Eflags & 0x200) ) {\r
- DisableInterrupts ();\r
- }\r
-\r
- //\r
- // Write all cache data to memory because processor will lost power\r
- //\r
- AsmWbinvd();\r
- RegCr0 = AsmReadCr0();\r
- AsmWriteCr0 (RegCr0 | 0x060000000);\r
-\r
- SmiEnSave = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
- QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, (SmiEnSave & ~SMI_EN));\r
-\r
- //\r
- // Pogram RTC alarm for immediate WAKE\r
- //\r
-\r
- //\r
- // Disable SMI sources\r
- //\r
- IoWrite16 (PcdGet16 (PcdGpe0blkIoBaseAddress) + R_QNC_GPE0BLK_SMIE, 0);\r
-\r
- //\r
- // Disable RTC alarm interrupt\r
- //\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);\r
- Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
- IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 & ~BIT5));\r
-\r
- //\r
- // Clear RTC alarm if already set\r
- //\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_C);\r
- Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER); // Read clears alarm status\r
-\r
- //\r
- // Disable all WAKE events\r
- //\r
- IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, B_QNC_PM1BLK_PM1E_PWAKED);\r
-\r
- //\r
- // Clear all WAKE status bits\r
- //\r
- IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S, B_QNC_PM1BLK_PM1S_ALL);\r
-\r
- //\r
- // Avoid RTC rollover\r
- //\r
- do {\r
- WaitForRTCUpdate();\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);\r
- EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
- } while (EfiTime.Second > PLATFORM_RTC_ROLLOVER_LIMIT);\r
-\r
- //\r
- // Read RTC time\r
- //\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS);\r
- EfiTime.Hour = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES);\r
- EfiTime.Minute = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);\r
- EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
-\r
- //\r
- // Set RTC alarm\r
- //\r
-\r
- //\r
- // Add PLATFORM_WAKE_SECONDS_BUFFER to current EfiTime.Second\r
- // The maths is to allow for the fact we are adding to a BCD number and require the answer to be BCD (EfiTime.Second)\r
- //\r
- if ((BCD_BASE - (EfiTime.Second & 0x0F)) <= PLATFORM_WAKE_SECONDS_BUFFER) {\r
- Data8 = (((EfiTime.Second & 0xF0) + 0x10) + (PLATFORM_WAKE_SECONDS_BUFFER - (BCD_BASE - (EfiTime.Second & 0x0F))));\r
- } else {\r
- Data8 = EfiTime.Second + PLATFORM_WAKE_SECONDS_BUFFER;\r
- }\r
-\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS_ALARM);\r
- IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Hour);\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES_ALARM);\r
- IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Minute);\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS_ALARM);\r
- IoWrite8 (PCAT_RTC_DATA_REGISTER, Data8);\r
-\r
- //\r
- // Enable RTC alarm interrupt\r
- //\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);\r
- Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);\r
- IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 | BIT5));\r
-\r
- //\r
- // Enable RTC alarm as WAKE event\r
- //\r
- Data16 = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E);\r
- IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, (Data16 | B_QNC_PM1BLK_PM1E_RTC));\r
-\r
- //\r
- // Enter S3\r
- //\r
- Data32 = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
- Data32 = (UINT32) ((Data32 & 0xffffc3fe) | V_S3 | B_QNC_PM1BLK_PM1C_SCIEN);\r
- IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);\r
- Data32 = Data32 | B_QNC_PM1BLK_PM1C_SLPEN;\r
- IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);\r
-\r
- //\r
- // Enable Interrupt if it's enabled before\r
- //\r
- if ( (Eflags & 0x200) ) {\r
- EnableInterrupts ();\r
- }\r
-}\r
-\r
-/**\r
- This function causes a systemwide reset. The exact type of the reset is\r
- defined by the EFI_GUID that follows the Null-terminated Unicode string passed\r
- into ResetData. If the platform does not recognize the EFI_GUID in ResetData\r
- the platform must pick a supported reset type to perform.The platform may\r
- optionally log the parameters from any non-normal reset that occurs.\r
-\r
- @param[in] DataSize The size, in bytes, of ResetData.\r
- @param[in] ResetData The data buffer starts with a Null-terminated string,\r
- followed by the EFI_GUID.\r
-**/\r
-VOID\r
-EFIAPI\r
-ResetPlatformSpecific (\r
- IN UINTN DataSize,\r
- IN VOID *ResetData\r
- )\r
-{\r
- ResetCold ();\r
-}\r
-\r
-/**\r
- The ResetSystem function resets the entire platform.\r
-\r
- @param[in] ResetType The type of reset to perform.\r
- @param[in] ResetStatus The status code for the reset.\r
- @param[in] DataSize The size, in bytes, of ResetData.\r
- @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown\r
- the data buffer starts with a Null-terminated string, optionally\r
- followed by additional binary data. The string is a description\r
- that the caller may use to further indicate the reason for the\r
- system reset.\r
-**/\r
-VOID\r
-EFIAPI\r
-ResetSystem (\r
- IN EFI_RESET_TYPE ResetType,\r
- IN EFI_STATUS ResetStatus,\r
- IN UINTN DataSize,\r
- IN VOID *ResetData OPTIONAL\r
- )\r
-{\r
- switch (ResetType) {\r
- case EfiResetWarm:\r
- ResetWarm ();\r
- break;\r
-\r
- case EfiResetCold:\r
- ResetCold ();\r
- break;\r
-\r
- case EfiResetShutdown:\r
- ResetShutdown ();\r
- return;\r
-\r
- case EfiResetPlatformSpecific:\r
- ResetPlatformSpecific (DataSize, ResetData);\r
- return;\r
-\r
- default:\r
- return;\r
- }\r
-}\r