diff options
author | Chen Lin Z <lin.z.chen@intel.com> | 2024-10-31 12:46:14 +0800 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-11-13 09:05:56 +0000 |
commit | 2839fed575f0eccae7f5a89f7252487dd058b462 (patch) | |
tree | 5806e14d099ea1d510ed82e656aa2e219dd3d264 /PcAtChipsetPkg | |
parent | df6b43f61b074a9c8c09471b586561ca35370408 (diff) | |
download | edk2-2839fed575f0eccae7f5a89f7252487dd058b462.tar.gz edk2-2839fed575f0eccae7f5a89f7252487dd058b462.tar.bz2 edk2-2839fed575f0eccae7f5a89f7252487dd058b462.zip |
PcAtChipsetPkg: Write RTC time in PcRtcInit() only when it is needed
In PcRtcInit(), it always read RTC time and then write it back. It could
potentially cause two issues:
1) There is time gap between read RTC and write RTC, writing RTC time on
every boot could cause RTC time drift after many reboot cycles
2) Writing RTC registers on every boot could cause some unnecessary delay,
slightly impact the boot performance.
The change is only writing RTC time when 1) the current RTC time is not
valid or 2) the RegisterB value is changed.
Signed-off-by: Chen Lin Z <lin.z.chen@intel.com>
Diffstat (limited to 'PcAtChipsetPkg')
-rw-r--r-- | PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c | 118 |
1 files changed, 81 insertions, 37 deletions
diff --git a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c index 5505f6da2e..fb3559dd29 100644 --- a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c +++ b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c @@ -189,6 +189,67 @@ RtcWrite ( }
/**
+ Sets the current local timezone & daylight information.
+
+ @param TimeZone Timezone info.
+ @param Daylight Daylight info.
+ @param Global For global use inside this module.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The variable could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+PcRtcSetTimeZone (
+ IN INT16 TimeZone,
+ IN UINT8 Daylight,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TimerVar;
+
+ ASSERT ((TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((TimeZone >= -1440) && (TimeZone <= 1440)));
+ ASSERT ((Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) == 0);
+
+ //
+ // Write timezone and daylight to RTC variable
+ //
+ if ((TimeZone == EFI_UNSPECIFIED_TIMEZONE) && (Daylight == 0)) {
+ Status = EfiSetVariable (
+ mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ 0,
+ 0,
+ NULL
+ );
+ if (Status == EFI_NOT_FOUND) {
+ Status = EFI_SUCCESS;
+ }
+ } else {
+ TimerVar = Daylight;
+ TimerVar = (UINT32)((TimerVar << 16) | (UINT16)(TimeZone));
+ Status = EfiSetVariable (
+ mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (TimerVar),
+ &TimerVar
+ );
+ }
+
+ //
+ // Set the variable that contains the TimeZone and Daylight fields
+ //
+ if (!EFI_ERROR (Status)) {
+ Global->SavedTimeZone = TimeZone;
+ Global->Daylight = Daylight;
+ }
+
+ return Status;
+}
+
+/**
Initialize RTC.
@param Global For global use inside this module.
@@ -211,6 +272,9 @@ PcRtcInit ( UINT32 TimerVar;
BOOLEAN Enabled;
BOOLEAN Pending;
+ BOOLEAN NeedRtcUpdate;
+
+ NeedRtcUpdate = FALSE;
//
// Acquire RTC Lock to make access to RTC atomic
@@ -324,21 +388,32 @@ PcRtcInit ( Time.Nanosecond = 0;
Time.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
Time.Daylight = 0;
+ NeedRtcUpdate = TRUE;
}
//
// Set RTC configuration after get original time
// The value of bit AIE should be reserved.
//
- RegisterB.Data = FixedPcdGet8 (PcdInitialValueRtcRegisterB) | (RegisterB.Data & BIT5);
- RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+ if ((RegisterB.Data | BIT5) != (FixedPcdGet8 (PcdInitialValueRtcRegisterB) | BIT5)) {
+ RegisterB.Data = FixedPcdGet8 (PcdInitialValueRtcRegisterB) | (RegisterB.Data & BIT5);
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+ NeedRtcUpdate = TRUE;
+ }
//
// Reset time value according to new RTC configuration
//
- Status = PcRtcSetTime (&Time, Global);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
+ if (NeedRtcUpdate) {
+ Status = PcRtcSetTime (&Time, Global);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ } else {
+ Status = PcRtcSetTimeZone (Time.TimeZone, Time.Daylight, Global);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
}
//
@@ -563,7 +638,6 @@ PcRtcSetTime ( EFI_TIME RtcTime;
RTC_REGISTER_A RegisterA;
RTC_REGISTER_B RegisterB;
- UINT32 TimerVar;
if (Time == NULL) {
return EFI_INVALID_PARAMETER;
@@ -598,31 +672,7 @@ PcRtcSetTime ( return Status;
}
- //
- // Write timezone and daylight to RTC variable
- //
- if ((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) && (Time->Daylight == 0)) {
- Status = EfiSetVariable (
- mTimeZoneVariableName,
- &gEfiCallerIdGuid,
- 0,
- 0,
- NULL
- );
- if (Status == EFI_NOT_FOUND) {
- Status = EFI_SUCCESS;
- }
- } else {
- TimerVar = Time->Daylight;
- TimerVar = (UINT32)((TimerVar << 16) | (UINT16)(Time->TimeZone));
- Status = EfiSetVariable (
- mTimeZoneVariableName,
- &gEfiCallerIdGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
- sizeof (TimerVar),
- &TimerVar
- );
- }
+ Status = PcRtcSetTimeZone (Time->TimeZone, Time->Daylight, Global);
if (EFI_ERROR (Status)) {
if (!EfiAtRuntime ()) {
@@ -677,12 +727,6 @@ PcRtcSetTime ( EfiReleaseLock (&Global->RtcLock);
}
- //
- // Set the variable that contains the TimeZone and Daylight fields
- //
- Global->SavedTimeZone = Time->TimeZone;
- Global->Daylight = Time->Daylight;
-
return EFI_SUCCESS;
}
|