2 System reset Library Services. This library class provides a set of
3 methods to reset whole system with manipulate QNC.
5 Copyright (c) 2013-2016 Intel Corporation.
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <IntelQNCBase.h>
13 #include <QNCAccess.h>
15 #include <Uefi/UefiBaseType.h>
17 #include <Library/ResetSystemLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/IoLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/CpuLib.h>
22 #include <Library/QNCAccessLib.h>
25 // Amount of time (seconds) before RTC alarm fires
26 // This must be < BCD_BASE
28 #define PLATFORM_WAKE_SECONDS_BUFFER 0x06
31 // RTC 'seconds' above which we will not read to avoid potential rollover
33 #define PLATFORM_RTC_ROLLOVER_LIMIT 0x47
40 #define PCAT_RTC_ADDRESS_REGISTER 0x70
41 #define PCAT_RTC_DATA_REGISTER 0x71
44 // Dallas DS12C887 Real Time Clock
46 #define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59
47 #define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59
48 #define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59
49 #define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59
50 #define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
51 #define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
52 #define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7
53 #define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31
54 #define RTC_ADDRESS_MONTH 8 // R/W Range 1..12
55 #define RTC_ADDRESS_YEAR 9 // R/W Range 0..99
56 #define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]
57 #define RTC_ADDRESS_REGISTER_B 11 // R/W
58 #define RTC_ADDRESS_REGISTER_C 12 // RO
59 #define RTC_ADDRESS_REGISTER_D 13 // RO
60 #define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W
63 Wait for an RTC update to happen
74 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_A
);
75 Data8
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
76 if ((Data8
& BIT7
) == BIT7
) {
77 while ((Data8
& BIT7
) == BIT7
) {
78 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_A
);
79 Data8
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
83 while ((Data8
& BIT7
) == 0) {
84 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_A
);
85 Data8
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
88 while ((Data8
& BIT7
) == BIT7
) {
89 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_A
);
90 Data8
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
96 Calling this function causes a system-wide reset. This sets
97 all circuitry within the system to its initial state. This type of reset
98 is asynchronous to system operation and operates without regard to
101 System reset should not return, if it returns, it means the system does
102 not support cold reset.
111 // Reference to QuarkNcSocId BWG
112 // Setting bit 1 will generate a warm reset, driving only RSTRDY# low
114 IoWrite8 (RST_CNT
, B_RST_CNT_COLD_RST
);
118 Calling this function causes a system-wide initialization. The processors
119 are set to their initial state, and pending cycles are not corrupted.
121 System reset should not return, if it returns, it means the system does
122 not support warm reset.
131 // Reference to QuarkNcSocId BWG
132 // Setting bit 1 will generate a warm reset, driving only RSTRDY# low
134 IoWrite8 (RST_CNT
, B_RST_CNT_WARM_RST
);
138 Calling this function causes the system to enter a power state equivalent
139 to the ACPI G2/S5 or G3 states.
141 System shutdown should not return, if it returns, it means the system does
142 not support shut down reset.
151 // Reference to QuarkNcSocId BWG
152 // Disable RTC Alarm : (RTC Enable at PM1BLK + 02h[10]))
154 IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1E
, 0);
157 // Firstly, GPE0_EN should be disabled to
158 // avoid any GPI waking up the system from S5
160 IoWrite32 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E
, 0);
163 // Reference to QuarkNcSocId BWG
164 // Disable Resume Well GPIO : (GPIO bits in GPIOBASE + 34h[8:0])
166 IoWrite32 (PcdGet16 (PcdGbaIoBaseAddress
) + R_QNC_GPIO_RGGPE_RESUME_WELL
, 0);
169 // No power button status bit to clear for our platform, go to next step.
173 // Finally, transform system into S5 sleep state
175 IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1C
, 0xffffc3ff, B_QNC_PM1BLK_PM1C_SLPEN
| V_S5
);
179 Calling this function causes the system to enter a power state for capsule
182 Reset update should not return, if it returns, it means the system does
183 not support capsule update.
188 EnterS3WithImmediateWake (
200 Eflags
= AsmReadEflags ();
201 if ( (Eflags
& 0x200) ) {
202 DisableInterrupts ();
206 // Write all cache data to memory because processor will lost power
209 RegCr0
= AsmReadCr0();
210 AsmWriteCr0 (RegCr0
| 0x060000000);
212 SmiEnSave
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
213 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, (SmiEnSave
& ~SMI_EN
));
216 // Pogram RTC alarm for immediate WAKE
220 // Disable SMI sources
222 IoWrite16 (PcdGet16 (PcdGpe0blkIoBaseAddress
) + R_QNC_GPE0BLK_SMIE
, 0);
225 // Disable RTC alarm interrupt
227 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_B
);
228 Data8
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
229 IoWrite8 (PCAT_RTC_DATA_REGISTER
, (Data8
& ~BIT5
));
232 // Clear RTC alarm if already set
234 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_C
);
235 Data8
= IoRead8 (PCAT_RTC_DATA_REGISTER
); // Read clears alarm status
238 // Disable all WAKE events
240 IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1E
, B_QNC_PM1BLK_PM1E_PWAKED
);
243 // Clear all WAKE status bits
245 IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1S
, B_QNC_PM1BLK_PM1S_ALL
);
248 // Avoid RTC rollover
252 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_SECONDS
);
253 EfiTime
.Second
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
254 } while (EfiTime
.Second
> PLATFORM_RTC_ROLLOVER_LIMIT
);
259 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_HOURS
);
260 EfiTime
.Hour
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
261 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_MINUTES
);
262 EfiTime
.Minute
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
263 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_SECONDS
);
264 EfiTime
.Second
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
271 // Add PLATFORM_WAKE_SECONDS_BUFFER to current EfiTime.Second
272 // The maths is to allow for the fact we are adding to a BCD number and require the answer to be BCD (EfiTime.Second)
274 if ((BCD_BASE
- (EfiTime
.Second
& 0x0F)) <= PLATFORM_WAKE_SECONDS_BUFFER
) {
275 Data8
= (((EfiTime
.Second
& 0xF0) + 0x10) + (PLATFORM_WAKE_SECONDS_BUFFER
- (BCD_BASE
- (EfiTime
.Second
& 0x0F))));
277 Data8
= EfiTime
.Second
+ PLATFORM_WAKE_SECONDS_BUFFER
;
280 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_HOURS_ALARM
);
281 IoWrite8 (PCAT_RTC_DATA_REGISTER
, EfiTime
.Hour
);
282 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_MINUTES_ALARM
);
283 IoWrite8 (PCAT_RTC_DATA_REGISTER
, EfiTime
.Minute
);
284 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_SECONDS_ALARM
);
285 IoWrite8 (PCAT_RTC_DATA_REGISTER
, Data8
);
288 // Enable RTC alarm interrupt
290 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_B
);
291 Data8
= IoRead8 (PCAT_RTC_DATA_REGISTER
);
292 IoWrite8 (PCAT_RTC_DATA_REGISTER
, (Data8
| BIT5
));
295 // Enable RTC alarm as WAKE event
297 Data16
= IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1E
);
298 IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1E
, (Data16
| B_QNC_PM1BLK_PM1E_RTC
));
303 Data32
= IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1C
);
304 Data32
= (UINT32
) ((Data32
& 0xffffc3fe) | V_S3
| B_QNC_PM1BLK_PM1C_SCIEN
);
305 IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1C
, Data32
);
306 Data32
= Data32
| B_QNC_PM1BLK_PM1C_SLPEN
;
307 IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1C
, Data32
);
310 // Enable Interrupt if it's enabled before
312 if ( (Eflags
& 0x200) ) {
318 This function causes a systemwide reset. The exact type of the reset is
319 defined by the EFI_GUID that follows the Null-terminated Unicode string passed
320 into ResetData. If the platform does not recognize the EFI_GUID in ResetData
321 the platform must pick a supported reset type to perform.The platform may
322 optionally log the parameters from any non-normal reset that occurs.
324 @param[in] DataSize The size, in bytes, of ResetData.
325 @param[in] ResetData The data buffer starts with a Null-terminated string,
326 followed by the EFI_GUID.
330 ResetPlatformSpecific (