Reviewed-by: Chao Li  <lichao@loongson.cn>


Thanks,
Chao
--------

On 11月 11 2022, at 5:12 δΈ‹εˆ, xianglai li <lixianglai@loongson.cn> wrote:
This library provides interfaces such as

real-time clock initialization

to get time and setting time.



REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054



Cc: 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.h

create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.c

create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClockLib.inf



diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClock.h b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealTimeClock.h

new file mode 100644

index 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.c

new file mode 100644

index 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.inf

new file mode 100644

index 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