Runtime service is not supported yet.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jun Nie jun.nie@linaro.org --- .../Zx6718RealTimeClockLib/Zx296718RealTimeClock.c | 376 +++++++++++++++++++++ .../Zx6718RealTimeClockLib/Zx296718RealTimeClock.h | 102 ++++++ .../Zx296718RealTimeClock.inf | 42 +++ 3 files changed, 520 insertions(+) create mode 100644 Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.c create mode 100644 Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.h create mode 100644 Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.inf
diff --git a/Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.c b/Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.c new file mode 100644 index 0000000..af6e5bd --- /dev/null +++ b/Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.c @@ -0,0 +1,376 @@ +/** @file + Implement EFI RealTimeClock runtime services via RTC Lib. + + Currently this driver does not support runtime virtual calling. + + Copyright (C) 2017 Sanechips Technology Co., Ltd. + Copyright (c) 2017, Linaro Limited. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Based on the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf + +**/ + +#include <Uefi.h> +#include <PiDxe.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <Library/TimerLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +// Use EfiAtRuntime to check stage +#include <Library/UefiRuntimeLib.h> +#include <Protocol/RealTimeClock.h> +#include "Zx296718RealTimeClock.h" + +STATIC UINTN RtcBase; +STATIC BOOLEAN RTCInitialized = FALSE; + +BOOLEAN +EFIAPI +IsTimeValid( + IN EFI_TIME *Time + ) +{ + // Check the input parameters are within the range specified by UEFI + if ((Time->Year < 2000) || + (Time->Year > 2099) || + (Time->Month < 1 ) || + (Time->Month > 12 ) || + (Time->Day < 1 ) || + (Time->Day > 31 ) || + (Time->Hour > 23 ) || + (Time->Minute > 59 ) || + (Time->Second > 59 ) || + (Time->Nanosecond > 999999999) || + (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) || + (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) + ) { + return FALSE; + } + + return TRUE; +} + +VOID +Wait4Busy ( + VOID + ) +{ + UINT32 Val, Retry = 1000; + do { + MicroSecondDelay (200); + Val = MmioRead32 (RtcBase + RTCSTS); + } while(Val & RTC_BUSY && Retry--); + + if (!Retry) + DEBUG((DEBUG_ERROR, "%a Rtc busy retry timeout\n", __func__)); +} + +VOID +RTCWriteReg ( + IN UINT32 Reg, + IN UINT32 Val + ) +{ + Wait4Busy (); + MmioWrite32 (RtcBase + RTCCFGID, CONFIG_PARMETER); + Wait4Busy (); + MmioWrite32 (RtcBase + Reg, Val); +} + +UINT32 +RTCReadReg ( + IN UINT32 Reg + ) +{ + Wait4Busy (); + return MmioRead32 (RtcBase + Reg); +} + +VOID +InitializeRTC ( + VOID + ) +{ + UINTN Val = (UINTN)FixedPcdGet64 (PcdZxRtcClockFreq); + + RTCWriteReg (RTCCLKCNT, Val - 1); + Val = RTCReadReg (RTCPOWERINIT1); + if (RTC_POWER_INI1_PARA != Val) { + RTCWriteReg (RTCCTL, 0); + MicroSecondDelay (INIT_DELAY); + Val = RTCReadReg (RTCCTL); + Val |= RTC_CTRL_BIT6_1; + RTCWriteReg (RTCCTL, Val); + Val = RTCReadReg (RTCCTL); + Val &= RTC_CTRL_MODULE24 | RTC_CTRL_STOP; + RTCWriteReg (RTCCTL, Val); + } + Val = RTCReadReg (RTCINT); + Val &= ~RTC_IT_MASK; + RTCWriteReg (RTCINT, Val); + Val = RTCReadReg (RTCSTS); + Val |= (RTC_POWER_UP | RTC_ALARM | RTC_TIMER); + RTCWriteReg (RTCSTS, Val); + //Wait4Busy (); + // TODO: write 0x6 to AON int clear + RTCWriteReg (RTCPOWERINIT1, RTC_POWER_INI1_PARA); + RTCWriteReg (RTCPOWERINIT2, RTC_POWER_INI2_PARA); + Val = RTC_CTRL_MODULE24 | RTC_CTRL_RUN | RTC_CTRL_CLK_32K_OUTEN + | RTC_CTRL_BIT6_1; + RTCWriteReg (RTCCTL, Val); + + RTCInitialized = 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 + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + + // Ensure Time is a valid pointer + if (NULL == Time) { + return EFI_INVALID_PARAMETER; + } + + // Initialize the hardware if not already done + if (!RTCInitialized) { + InitializeRTC (); + } + +#if 0 + /* fake time */ + Time->Year = 2015; + Time->Month = 1; + Time->Day = 1; + Time->Hour = 0; + Time->Minute = 0; + Time->Second = 0; + Time->Nanosecond = 0; +#endif + + RTCWriteReg (RTCGETTIME, 0); + Time->Year = BCD4_2_BIN (RTCReadReg (RTCYEAR)); + Time->Year += TM_YEAR_START; + + Time->Month = BCD4_2_BIN (RTCReadReg (RTCMONT)); + Time->Day = BCD4_2_BIN (RTCReadReg (RTCDAY)); + Time->Hour = BCD4_2_BIN (RTCReadReg (RTCHOUR)); + Time->Minute = BCD4_2_BIN (RTCReadReg (RTCMIN)); + Time->Second = BCD4_2_BIN (RTCReadReg (RTCSEC)); + Time->Nanosecond = 0; + Time->Daylight = 0; + Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; + + if(!IsTimeValid (Time)) { + Status = EFI_UNSUPPORTED; + } + + return Status; + +} + + +/** + 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 + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + + // Check the input parameters are within the range specified by UEFI + if(!IsTimeValid (Time)){ + return EFI_INVALID_PARAMETER; + } + + // Initialize the hardware if not already done + if (!RTCInitialized) { + InitializeRTC (); + } + + RTCWriteReg (RTCSEC, BIN2BCD (Time->Second)); + RTCWriteReg (RTCMIN, BIN2BCD (Time->Minute)); + RTCWriteReg (RTCHOUR, BIN2BCD (Time->Hour)); + RTCWriteReg (RTCDAY, BIN2BCD (Time->Day)); + RTCWriteReg (RTCMONT, BIN2BCD (Time->Month)); + RTCWriteReg (RTCYEAR, BIN2BCD (Time->Year - TM_YEAR_START)); + return Status; +} + + +/** + 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; +} + + + +/** + 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; + + + EFI_TIME EfiTime; + + // Setup the setters and getters + gRT->GetTime = LibGetTime; + gRT->SetTime = LibSetTime; + gRT->GetWakeupTime = LibGetWakeupTime; + gRT->SetWakeupTime = LibSetWakeupTime; + + + RtcBase = (UINTN)FixedPcdGet64 (PcdZxRtcClockBase); + + (VOID)gRT->GetTime (&EfiTime, NULL); + if ((EfiTime.Year < 2015) || (EfiTime.Year > 2099)){ + EfiTime.Year = 2015; + EfiTime.Month = 1; + EfiTime.Day = 1; + EfiTime.Hour = 0; + EfiTime.Minute = 0; + EfiTime.Second = 0; + EfiTime.Nanosecond = 0; + Status = gRT->SetTime (&EfiTime); + if (EFI_ERROR (Status)) + { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Status : %r\n", __FUNCTION__, + __LINE__, Status)); + } + } + + // Install the protocol + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiRealTimeClockArchProtocolGuid, NULL, + NULL + ); + + return Status; +} + + +/** + 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. + // + return; +} diff --git a/Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.h b/Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.h new file mode 100644 index 0000000..3b5a4d4 --- /dev/null +++ b/Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.h @@ -0,0 +1,102 @@ +/** @file +* +* Copyright (C) 2017 Sanechips Technology Co., Ltd. +* Copyright (c) 2017, Linaro Ltd. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +* Based on the files under ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf +**/ + + +#ifndef __DS3231_REAL_TIME_CLOCK_H__ +#define __DS3231_REAL_TIME_CLOCK_H__ + +#define RTC_POWER_INI1_PARA (0xCDBC) +#define RTC_POWER_INI2_PARA (0xCFCC) +#define CONFIG_PARMETER (0xC1CD) + +#define ZX_RTC_CMP_VALUE (0x3FFF) +#define WAIT_FOR_COUNT (2000) +#define INIT_DELAY (100) + + +/* RTC Control register description */ +#define RTC_CTRL_STOP (~(0x1 << 0)) +#define RTC_CTRL_RUN (0x1 << 0) +#define RTC_CTRL_ROUND30S (0x1 << 1) +#define RTC_CTRL_AUTO_COMPENSATION (0x1 << 2) +#define RTC_CTRL_MODULE12 (0x1 << 3) +#define RTC_CTRL_MODULE24 (~(0x1 << 3)) +#define RTC_CTRL_SET_32_COUNTER (0x1 << 5) +#define RTC_CTRL_SOFT_RESET (0x1 << 6) +#define RTC_CTRL_CLK_32K_OUTEN (0x1 << 8) + +#define RTC_CTRL_BIT6_0 ( ~(0x1 << 6)) +#define RTC_CTRL_BIT6_1 (0x1 << 6) + + + +/* RTC Interrupt register description */ +#define RTC_EVERY_MASK (0x3 << 0) +#define RTC_EVERY_SEC 0x00 /* second periodic intrrupt */ +#define RTC_EVERY_MIN 0x01 /* minute periodic interrupt */ +#define RTC_EVERY_HR 0x02 /* hour periodic interrupt */ +#define RTC_EVERY_DAY 0x03 /* day periodic interrupt */ +#define RTC_IT_TIMER (0x1 << 2) /* Enable periodic interrupt */ +#define RTC_IT_ALARM (0x1 << 3) /* Enable alarm clock interrupt */ +#define RTC_IT_MASK (0x3 << 2) + +/* RTC Status register description */ +#define RTC_BUSY (0x1 << 0) /* Read-only, indicate refresh*/ +#define RTC_RUN (0x1 << 1) /* Read-only, RTC is running */ +#define RTC_ALARM (0x1 << 6) /* Read/Write, Alarm interrupt has been generated */ +#define RTC_TIMER (0x1 << 7) /* Read/Write, Timer interrupt has been generated */ +#define RTC_POWER_UP (0x1 << 8) /* Read/Write, Reset */ + +#define TM_YEAR_START 1900 + +#define TM_MONTH_OFFSET 1 + +#define TM_WDAY_SUNDAY 0 +#define ZX_RTC_SUNDAY 7 + +#define BCD2BIN(val) (((val) & 0x0f) + ((val) >> 4) * 10) +#define BIN2BCD(val) ((((val) / 10) << 4) + (val) % 10) + +#define BCD4_2_BIN(x) (( (x) & 0x0F) + \ + ((((x) & 0x0F0) >> 4) * 10) + \ + ((((x) & 0xF00) >> 8) * 100) + \ + ((((x) & 0xF000) >> 12) * 1000)) + + +#define BIN_2_BCD4(x) (((x % 10) & 0x0F) | \ + (((x /10 ) % 10) << 4) | \ + (((x /100) % 10) << 8) | \ + (((x /1000) % 10) << 12)) + +/* RTC register offset */ +#define RTCVER 0 +#define RTCSEC 4 +#define RTCMIN 8 +#define RTCHOUR 0xc +#define RTCDAY 0x10 +#define RTCMONT 0x14 +#define RTCYEAR 0x18 +#define RTCWEEK 0x1c +#define RTCCTL 0x38 +#define RTCSTS 0x3c +#define RTCINT 0x40 +#define RTCCFGID 0x48 +#define RTCPOWERINIT1 0x4c +#define RTCPOWERINIT2 0x50 +#define RTCGETTIME 0x54 +#define RTCCLKCNT 0x58 + +#endif diff --git a/Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.inf b/Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.inf new file mode 100644 index 0000000..0a6852b --- /dev/null +++ b/Silicon/Sanchip/Library/Zx6718RealTimeClockLib/Zx296718RealTimeClock.inf @@ -0,0 +1,42 @@ +#/** @file +# +# Copyright (c) 2017, Linaro Limited. All rights reserved.<BR> +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Zx296718RealTimeClockLib + FILE_GUID = 4e1aaa26-597c-4f01-a8fc-fdf1adc1400f + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RealTimeClockLib + +[Sources.common] + Zx296718RealTimeClock.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Silicon/Sanchip/SanchipPkg.dec + +[LibraryClasses] + IoLib + UefiLib + DebugLib + PcdLib + TimerLib +# Use EFiAtRuntime to check stage + UefiRuntimeLib + +[FixedPcd] + gSanchipTokenSpaceGuid.PcdZxRtcClockBase + gSanchipTokenSpaceGuid.PcdZxRtcClockFreq