[Linaro-uefi,2/4] Platforms: Add ZX RTC driver for Sanchip SoC

Message ID 1502287959-16806-2-git-send-email-jun.nie@linaro.org
State New
Headers show
Series
  • [Linaro-uefi,1/4] Platforms: Add Sanchip Zx296718 basic library
Related show

Commit Message

Jun Nie Aug. 9, 2017, 2:12 p.m.
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

Comments

Ard Biesheuvel Aug. 9, 2017, 6:04 p.m. | #1
On 9 August 2017 at 15:12, Jun Nie <jun.nie@linaro.org> wrote:
> Runtime service is not supported yet.
>

Please resubmit when it is. It is not difficult to do, you can just
follow the existing examples.


> 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
> --
> 1.9.1
>
Jun Nie Aug. 17, 2017, 3:29 p.m. | #2
On 2017年08月10日 02:04, Ard Biesheuvel wrote:
> On 9 August 2017 at 15:12, Jun Nie <jun.nie@linaro.org> wrote:
>> Runtime service is not supported yet.
>>
> 
> Please resubmit when it is. It is not difficult to do, you can just
> follow the existing examples.

Done. Will send out later when all other code is ready.
> 
> 
>> 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
>> --
>> 1.9.1
>>

Patch

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