Thanks,
Chao
--------
This library provides interfaces such asreal-time clock initializationto get time and setting time.REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054Cc: Bibo Mao <maobibo@loongson.cn>Cc: Chao Li <lichao@loongson.cn>Cc: Leif Lindholm <quic_llindhol@quicinc.com>Cc: Liming Gao <gaoliming@byosoft.com.cn>Cc: Michael D Kinney <michael.d.kinney@intel.com>Signed-off-by: xianglai li <lixianglai@loongson.cn>---.../LsRealTimeClockLib/LsRealTimeClock.h | 40 +++.../LsRealTimeClockLib/LsRealTimeClockLib.c | 335 ++++++++++++++++++.../LsRealTimeClockLib/LsRealTimeClockLib.inf | 44 +++3 files changed, 419 insertions(+)create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClock.hcreate mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.ccreate mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.infdiff --git a/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClock.h b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClock.hnew file mode 100644index 0000000000..6567ec80db--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClock.h@@ -0,0 +1,40 @@+/** @file+ Implement EFI RealTimeClock runtime services via RTC Lib.++ Copyright (c) 2022, Loongson Limited. All rights reserved.++ SPDX-License-Identifier: BSD-2-Clause-Patent++**/++#ifndef LS_REAL_TIME_CLOCK_H_+#define LS_REAL_TIME_CLOCK_H_++#define TOY_WRITE0_REG 0x24+#define TOY_WRITE1_REG 0x28+#define TOY_READ0_REG 0x2c+#define TOY_READ1_REG 0x30+#define RTC_CTRL_REG 0x40++/* TOY Enable bits */+#define RTC_ENABLE_BIT (1UL << 13)+#define TOY_ENABLE_BIT (1UL << 11)+#define OSC_ENABLE_BIT (1UL << 8)++/*+ * shift bits and filed mask+ */+#define TOY_MON_MASK 0x3f+#define TOY_DAY_MASK 0x1f+#define TOY_HOUR_MASK 0x1f+#define TOY_MIN_MASK 0x3f+#define TOY_SEC_MASK 0x3f+#define TOY_MSEC_MASK 0xf++#define TOY_MON_SHIFT 26+#define TOY_DAY_SHIFT 21+#define TOY_HOUR_SHIFT 16+#define TOY_MIN_SHIFT 10+#define TOY_SEC_SHIFT 4++#endif // LS_REAL_TIME_CLOCK_H_diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.cnew file mode 100644index 0000000000..dc651ccaaf--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.c@@ -0,0 +1,335 @@+/** @file+ Implement EFI RealTimeClock runtime services via RTC Lib.++ Copyright (c) 2022, Loongson Limited. All rights reserved.++ SPDX-License-Identifier: BSD-2-Clause-Patent++**/++#include <Uefi.h>+#include <PiDxe.h>++#include <Guid/EventGroup.h>+#include <Guid/GlobalVariable.h>++#include <Library/BaseLib.h>+#include <Library/DebugLib.h>+#include <Library/DxeServicesTableLib.h>+#include <Library/IoLib.h>+#include <Library/MemoryAllocationLib.h>+#include <Library/PcdLib.h>+#include <Library/RealTimeClockLib.h>+#include <Library/TimeBaseLib.h>+#include <Library/UefiBootServicesTableLib.h>+#include <Library/UefiRuntimeServicesTableLib.h>+#include <Library/UefiRuntimeLib.h>+#include <Protocol/RealTimeClock.h>+#include "LsRealTimeClock.h"++STATIC BOOLEAN mInitialized = FALSE;+STATIC EFI_EVENT mRtcVirtualAddrChangeEvent;+STATIC UINTN mRtcBase = 0x100d0100;+/*+ Enable Real-time clock.++ @param VOID++ @retval VOID+ */+VOID+InitRtc (+ VOID+ )+{+ UINTN Val;++ if (!mInitialized) {+ /* enable rtc */+ Val = MmioRead32 (mRtcBase + RTC_CTRL_REG);+ Val |= TOY_ENABLE_BIT | OSC_ENABLE_BIT;+ MmioWrite32 (mRtcBase + RTC_CTRL_REG, Val);+ mInitialized = TRUE;+ }+}++/**+ Returns the current time and date information, and the time-keeping capabilities+ of the hardware platform.++ @param Time A pointer to storage to receive a snapshot of the current time.+ @param Capabilities An optional pointer to a buffer to receive the real time clock+ device's capabilities.++ @retval EFI_SUCCESS The operation completed successfully.+ @retval EFI_INVALID_PARAMETER Time is NULL.+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.+ @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure.+**/+EFI_STATUS+EFIAPI+LibGetTime (+ OUT EFI_TIME *Time,+ OUT EFI_TIME_CAPABILITIES *Capabilities+ )+{+ UINT32 Val;++ // Ensure Time is a valid pointer+ if (Time == NULL) {+ return EFI_INVALID_PARAMETER;+ }++ InitRtc ();+ Val = MmioRead32 (mRtcBase + TOY_READ1_REG);+ Time->Year = Val + 1900;++ Val = MmioRead32 (mRtcBase + TOY_READ0_REG);+ Time->Month = (Val >> TOY_MON_SHIFT) & TOY_MON_MASK;+ Time->Day = (Val >> TOY_DAY_SHIFT) & TOY_DAY_MASK;+ Time->Hour = (Val >> TOY_HOUR_SHIFT) & TOY_HOUR_MASK;+ Time->Minute = (Val >> TOY_MIN_SHIFT) & TOY_MIN_MASK;+ Time->Second = (Val >> TOY_SEC_SHIFT) & TOY_SEC_MASK;+ Time->Nanosecond = 0;+ return EFI_SUCCESS;+}++/**+ Sets the current local time and date information.++ @param Time A pointer to the current time.++ @retval EFI_SUCCESS The operation completed successfully.+ @retval EFI_INVALID_PARAMETER A time field is out of range.+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.+**/+EFI_STATUS+EFIAPI+LibSetTime (+ IN EFI_TIME *Time+ )+{+ UINT32 Val;++ // Initialize the hardware if not already done+ InitRtc ();++ Val = 0;+ Val |= (Time->Second << TOY_SEC_SHIFT);+ Val |= (Time->Minute << TOY_MIN_SHIFT);+ Val |= (Time->Hour << TOY_HOUR_SHIFT);+ Val |= (Time->Day << TOY_DAY_SHIFT);+ Val |= (Time->Month << TOY_MON_SHIFT);+ MmioWrite32 (mRtcBase + TOY_WRITE0_REG, Val);++ Val = Time->Year - 1900;+ MmioWrite32 (mRtcBase + TOY_WRITE1_REG, Val);+ return EFI_SUCCESS;+}++/**+ Returns the current wakeup alarm clock setting.++ @param Enabled Indicates if the alarm is currently enabled or disabled.+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.+ @param Time The current alarm setting.++ @retval EFI_SUCCESS The alarm settings were returned.+ @retval EFI_INVALID_PARAMETER Any parameter is NULL.+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.+**/+EFI_STATUS+EFIAPI+LibGetWakeupTime (+ OUT BOOLEAN *Enabled,+ OUT BOOLEAN *Pending,+ OUT EFI_TIME *Time+ )+{+ // Not a required feature+ return EFI_UNSUPPORTED;+}++/**+ Sets the system wakeup alarm clock time.++ @param Enabled Enable or disable the wakeup alarm.+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.++ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If+ Enable is FALSE, then the wakeup alarm was disabled.+ @retval EFI_INVALID_PARAMETER A time field is out of range.+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.+**/+EFI_STATUS+EFIAPI+LibSetWakeupTime (+ IN BOOLEAN Enabled,+ OUT EFI_TIME *Time+ )+{+ // Not a required feature+ return EFI_UNSUPPORTED;+}++/**+ Fixup internal data so that EFI can be call in virtual mode.+ Call the passed in Child Notify event and convert any pointers in+ lib to virtual mode.++ @param[in] Event The Event that is being processed+ @param[in] Context Event Context+**/+VOID+EFIAPI+LibRtcVirtualNotifyEvent (+ IN EFI_EVENT Event,+ IN VOID *Context+ )+{+ //+ // Only needed if you are going to support the OS calling RTC functions in virtual mode.+ // You will need to call EfiConvertPointer (). To convert any stored physical addresses+ // to virtual address. After the OS transitions to calling in virtual mode, all future+ // runtime calls will be made in virtual mode.+ //+ EfiConvertPointer (0x0, (VOID**)&mRtcBase);+ return;+}++/** Add the RTC controller address range to the memory map.++ @param [in] ImageHandle The handle to the image.+ @param [in] RtcPageBase Base address of the RTC controller.++ @retval EFI_SUCCESS Success.+ @retval EFI_INVALID_PARAMETER A parameter is invalid.+ @retval EFI_NOT_FOUND Flash device not found.+**/+EFI_STATUS+KvmtoolRtcMapMemory (+ IN EFI_HANDLE ImageHandle,+ IN EFI_PHYSICAL_ADDRESS RtcPageBase+ )+{+ EFI_STATUS Status;++ Status = gDS->AddMemorySpace (+ EfiGcdMemoryTypeMemoryMappedIo,+ RtcPageBase,+ EFI_PAGE_SIZE,+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME+ );+ if (EFI_ERROR (Status)) {+ DEBUG ((+ DEBUG_ERROR, "Failed to add memory space. Status = %r\n",+ Status+ ));+ return Status;+ }++ Status = gDS->AllocateMemorySpace (+ EfiGcdAllocateAddress,+ EfiGcdMemoryTypeMemoryMappedIo,+ 0,+ EFI_PAGE_SIZE,+ &RtcPageBase,+ ImageHandle,+ NULL+ );+ if (EFI_ERROR (Status)) {+ DEBUG ((+ DEBUG_ERROR,+ "Failed to allocate memory space. Status = %r\n",+ Status+ ));+ gDS->RemoveMemorySpace (+ RtcPageBase,+ EFI_PAGE_SIZE+ );+ return Status;+ }++ Status = gDS->SetMemorySpaceAttributes (+ RtcPageBase,+ EFI_PAGE_SIZE,+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME+ );+ if (EFI_ERROR (Status)) {+ DEBUG ((+ DEBUG_ERROR,+ "Failed to set memory attributes. Status = %r\n",+ Status+ ));++ gDS->FreeMemorySpace (+ RtcPageBase,+ EFI_PAGE_SIZE+ );++ gDS->RemoveMemorySpace (+ RtcPageBase,+ EFI_PAGE_SIZE+ );+ }++ return Status;+}++/**+ This is the declaration of an EFI image entry point. This can be the entry point to an application+ written to this specification, an EFI boot service driver, or an EFI runtime driver.++ @param ImageHandle Handle that identifies the loaded image.+ @param SystemTable System Table for this image.++ @retval EFI_SUCCESS The operation completed successfully.+**/+EFI_STATUS+EFIAPI+LibRtcInitialize (+ IN EFI_HANDLE ImageHandle,+ IN EFI_SYSTEM_TABLE *SystemTable+ )+{+ EFI_STATUS Status;+ EFI_HANDLE Handle;++ Status = KvmtoolRtcMapMemory (ImageHandle, (mRtcBase & ~EFI_PAGE_MASK));+ if (EFI_ERROR (Status)) {+ DEBUG ((+ DEBUG_ERROR,+ "Failed to map memory for loongson 7A RTC. Status = %r\n",+ Status+ ));+ return Status;+ }++ // Setup the setters and getters+ gRT->GetTime = LibGetTime;+ gRT->SetTime = LibSetTime;++ // Install the protocol+ Handle = NULL;+ Status = gBS->InstallMultipleProtocolInterfaces (+ &Handle,+ &gEfiRealTimeClockArchProtocolGuid, NULL,+ NULL+ );+ ASSERT_EFI_ERROR (Status);++ //+ // Register for the virtual address change event+ //+ Status = gBS->CreateEventEx (+ EVT_NOTIFY_SIGNAL,+ TPL_NOTIFY,+ LibRtcVirtualNotifyEvent,+ NULL,+ &gEfiEventVirtualAddressChangeGuid,+ &mRtcVirtualAddrChangeEvent+ );+ ASSERT_EFI_ERROR (Status);+ return Status;+}diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.infnew file mode 100644index 0000000000..6f7bf467b9--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.inf@@ -0,0 +1,44 @@+## @file+#+# Copyright (c) 2022, Loongson Limited. All rights reserved.+#+# SPDX-License-Identifier: BSD-2-Clause-Patent+#+##++[Defines]+ INF_VERSION = 0x00010005+ BASE_NAME = LsRealTimeClockLib+ FILE_GUID = 9793a3da-1869-4fdf-88b1-c6484341f50b+ MODULE_TYPE = BASE+ VERSION_STRING = 1.0+ LIBRARY_CLASS = RealTimeClockLib++#+# VALID_ARCHITECTURES = LOONGARCH64+#++[Sources]+ LsRealTimeClockLib.c++[Packages]+ MdePkg/MdePkg.dec+ EmbeddedPkg/EmbeddedPkg.dec+ Platform/Loongson/LoongArchQemuPkg/Loongson.dec++[LibraryClasses]+ IoLib+ UefiLib+ DebugLib+ PcdLib+ DxeServicesTableLib+ UefiRuntimeLib++[Guids]+ gEfiEventVirtualAddressChangeGuid++[Protocols]+ gEfiRealTimeClockArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED++[Depex]+ TRUE--2.31.1