public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [RFC PATCH edk2-platforms 0/3] add I2C RTC support to DeveloperBox
@ 2017-11-03 10:16 Ard Biesheuvel
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP Ard Biesheuvel
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2017-11-03 10:16 UTC (permalink / raw)
  To: edk2-devel, leif.lindholm, daniel.thompson; +Cc: Ard Biesheuvel

This implements RTC support over I2C for the Socionext DeveloperBox platform.

Note that using the I2C protocol at runtime is not supported by the ordinary
I2C protocol stack, so we have to take special precautions to allow the RTC
driver to invoke the I2C master protocol directly. The same driver is able
to driver other controllers in the ordinary way in parallel.

Ard Biesheuvel (3):
  Silicon/NXP: add RTC support library for PCF8563 I2C IP
  Silicon/Socionext: implement I2C master protocol for SynQuacer I2C
  Platform/DeveloperBox: wire up RTC support

 Platform/Socionext/DeveloperBox/DeveloperBox.dsc                                          |   8 +-
 Platform/Socionext/DeveloperBox/DeveloperBox.fdf                                          |   5 +
 Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c                     | 385 ++++++++++++
 Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec                   |  29 +
 Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf                   |  52 ++
 Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c                             |  76 ++-
 Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf                           |   6 +-
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentName.c                       | 185 ++++++
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBinding.c                       | 238 ++++++++
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.c                     | 618 ++++++++++++++++++++
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.h                     | 162 +++++
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf                   |  59 ++
 Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h                                  |   8 +
 Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c |   4 +
 Silicon/Socionext/SynQuacer/SynQuacer.dec                                                 |   5 +
 15 files changed, 1829 insertions(+), 11 deletions(-)
 create mode 100644 Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
 create mode 100644 Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
 create mode 100644 Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
 create mode 100644 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentName.c
 create mode 100644 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBinding.c
 create mode 100644 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.c
 create mode 100644 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.h
 create mode 100644 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf

-- 
2.11.0



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP
  2017-11-03 10:16 [RFC PATCH edk2-platforms 0/3] add I2C RTC support to DeveloperBox Ard Biesheuvel
@ 2017-11-03 10:16 ` Ard Biesheuvel
  2017-11-06 11:09   ` Udit Kumar
                     ` (2 more replies)
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 2/3] Silicon/Socionext: implement I2C master protocol for SynQuacer I2C Ard Biesheuvel
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 3/3] Platform/DeveloperBox: wire up RTC support Ard Biesheuvel
  2 siblings, 3 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2017-11-03 10:16 UTC (permalink / raw)
  To: edk2-devel, leif.lindholm, daniel.thompson; +Cc: Ard Biesheuvel

Add a RealTimeClockLib implementation for the NXP PCF8563 as used on
the Socionext Developer Box board. Note that the standard I2C protocol
stack does not support runtime use, so this driver invokes the I2C master
protocol directly. This requires support from the platform side as well,
and so this driver will only attach to a I2C master that has the
gPcf8563RealTimeClockLibI2cMasterProtolGuid protocol installed on its
handle. It is up to the platform to ensure that the driver producing
the I2C master protocol in question is runtime capable, and is not
shared with the I2C protocol stack (i.e., it should not have the I2C
Bus Configuration Management protocol installed as well).

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c   | 385 ++++++++++++++++++++
 Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec |  29 ++
 Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf |  52 +++
 3 files changed, 466 insertions(+)

diff --git a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
new file mode 100644
index 000000000000..fea65a225d7f
--- /dev/null
+++ b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
@@ -0,0 +1,385 @@
+/** @file
+
+  Copyright (c) 2017, Linaro, Ltd. 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.
+
+**/
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/RealTimeClockLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Protocol/I2cMaster.h>
+
+#define SLAVE_ADDRESS             (FixedPcdGet8 (PcdI2cSlaveAddress))
+#define PCF8563_DATA_REG_OFFSET   0x2
+
+#define PCF8563_SECONDS_MASK      0x7f
+#define PCF8563_MINUTES_MASK      0x7f
+#define PCF8563_HOURS_MASK        0x3f
+#define PCF8563_DAYS_MASK         0x3f
+#define PCF8563_WEEKDAYS_MASK     0x07
+#define PCF8563_MONTHS_MASK       0x1f
+#define PCF8563_CENTURY_MASK      0x80
+
+#define EPOCH_BASE                2000
+
+STATIC EFI_HANDLE                 mI2cMasterHandle;
+STATIC VOID                       *mDriverEventRegistration;
+STATIC EFI_I2C_MASTER_PROTOCOL    *mI2cMaster;
+STATIC EFI_EVENT                  mRtcVirtualAddrChangeEvent;
+
+typedef struct {
+  UINTN                           OperationCount;
+  EFI_I2C_OPERATION               SetAddressOp;
+  EFI_I2C_OPERATION               GetSetDateTimeOp;
+} RTC_I2C_REQUEST;
+
+#pragma pack(1)
+typedef struct {
+  UINT8     VL_seconds;
+  UINT8     Minutes;
+  UINT8     Hours;
+  UINT8     Days;
+  UINT8     Weekdays;
+  UINT8     Century_months;
+  UINT8     Years;
+} RTC_DATETIME;
+#pragma pack()
+
+/**
+  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.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetTime (
+  OUT EFI_TIME                *Time,
+  OUT EFI_TIME_CAPABILITIES   *Capabilities
+  )
+{
+  RTC_I2C_REQUEST             Op;
+  RTC_DATETIME                DateTime;
+  EFI_STATUS                  Status;
+  UINT8                       Reg;
+
+  if (Time == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (mI2cMaster == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  Reg = PCF8563_DATA_REG_OFFSET;
+
+  Op.OperationCount = 2;
+
+  Op.SetAddressOp.Flags = 0;
+  Op.SetAddressOp.LengthInBytes = 1;
+  Op.SetAddressOp.Buffer = &Reg;
+
+  Op.GetSetDateTimeOp.Flags = I2C_FLAG_READ;
+  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
+  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
+
+  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
+                         (VOID *)&Op, NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  Time->Second  = BcdToDecimal8 (DateTime.VL_seconds & PCF8563_SECONDS_MASK);
+  Time->Minute  = BcdToDecimal8 (DateTime.Minutes & PCF8563_MINUTES_MASK);
+  Time->Hour    = BcdToDecimal8 (DateTime.Hours & PCF8563_HOURS_MASK);
+  Time->Day     = BcdToDecimal8 (DateTime.Days & PCF8563_DAYS_MASK);
+  Time->Month   = BcdToDecimal8 (DateTime.Century_months & PCF8563_MONTHS_MASK);
+  Time->Year    = BcdToDecimal8 (DateTime.Years) + EPOCH_BASE;
+
+  if (DateTime.Century_months & PCF8563_CENTURY_MASK) {
+    Time->Year += 100;
+  }
+
+  Time->Daylight  = EFI_TIME_ADJUST_DAYLIGHT;
+  Time->TimeZone  = 0; /* UTC */
+
+  if (Capabilities != NULL) {
+    Capabilities->Resolution = 1;
+    Capabilities->Accuracy = 0;
+    Capabilities->SetsToZero = TRUE;
+  }
+  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
+  )
+{
+  RTC_I2C_REQUEST             Op;
+  RTC_DATETIME                DateTime;
+  EFI_STATUS                  Status;
+  UINT8                       Reg;
+
+  if (mI2cMaster == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  DateTime.VL_seconds     = DecimalToBcd8 (Time->Second);
+  DateTime.Minutes        = DecimalToBcd8 (Time->Minute);
+  DateTime.Hours          = DecimalToBcd8 (Time->Hour);
+  DateTime.Days           = DecimalToBcd8 (Time->Day);
+  DateTime.Century_months = DecimalToBcd8 (Time->Month);
+  DateTime.Years          = DecimalToBcd8 (Time->Year % 100);
+  if (Time->Year >= EPOCH_BASE + 100) {
+    DateTime.Century_months |= PCF8563_CENTURY_MASK;
+  }
+
+  Reg = PCF8563_DATA_REG_OFFSET;
+
+  Op.OperationCount = 2;
+
+  Op.SetAddressOp.Flags = 0;
+  Op.SetAddressOp.LengthInBytes = 1;
+  Op.SetAddressOp.Buffer = &Reg;
+
+  Op.GetSetDateTimeOp.Flags = 0;
+  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
+  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
+
+  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
+                         (VOID *)&Op, NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+  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
+  )
+{
+  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
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+VOID
+DriverRegistrationEvent (
+  IN  EFI_EVENT       Event,
+  IN  VOID            *Context
+  )
+{
+  EFI_HANDLE                Handle[2];
+  UINTN                     BufferSize;
+  EFI_STATUS                Status;
+  EFI_I2C_MASTER_PROTOCOL   *I2cMaster;
+  UINTN                     BusFrequency;
+
+  //
+  // Try to connect the newly registered driver to our handle.
+  //
+  do {
+    BufferSize = sizeof (EFI_HANDLE);
+    Status = gBS->LocateHandle (ByRegisterNotify,
+                                &gEfiDriverBindingProtocolGuid,
+                                mDriverEventRegistration,
+                                &BufferSize,
+                                Handle);
+    if (EFI_ERROR (Status)) {
+      if (Status != EFI_NOT_FOUND) {
+        DEBUG ((DEBUG_WARN, "%a: gBS->LocateHandle () returned %r\n",
+          __FUNCTION__, Status));
+      }
+      break;
+    }
+
+    //
+    // Check if we can connect our handle to this driver.
+    //
+    Handle[1] = NULL;
+    Status = gBS->ConnectController (mI2cMasterHandle, Handle, NULL, FALSE);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    DEBUG ((DEBUG_INFO, "%a: found I2C master!\n", __FUNCTION__));
+
+    gBS->CloseEvent (Event);
+
+    Status = gBS->OpenProtocol (mI2cMasterHandle, &gEfiI2cMasterProtocolGuid,
+                    (VOID **)&I2cMaster, gImageHandle, NULL,
+                    EFI_OPEN_PROTOCOL_EXCLUSIVE);
+    ASSERT_EFI_ERROR (Status);
+
+    Status = I2cMaster->Reset (I2cMaster);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->Reset () failed - %r\n",
+        __FUNCTION__, Status));
+      break;
+    }
+
+    BusFrequency = FixedPcdGet16 (PcdI2cBusFrequency);
+    Status = I2cMaster->SetBusFrequency (I2cMaster, &BusFrequency);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->SetBusFrequency () failed - %r\n",
+        __FUNCTION__, Status));
+      break;
+    }
+
+    mI2cMaster = I2cMaster;
+    break;
+  } while (TRUE);
+}
+
+/**
+  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
+  )
+{
+  EfiConvertPointer (0x0, (VOID **)&mI2cMaster);
+}
+
+/**
+  Library entry point
+
+  @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;
+  UINTN               BufferSize;
+
+  //
+  // Find the handle that marks the controller
+  // that will provide the I2C master protocol.
+  //
+  BufferSize = sizeof (EFI_HANDLE);
+  Status = gBS->LocateHandle (ByProtocol,
+                  &gPcf8563RealTimeClockLibI2cMasterProtolGuid, NULL,
+                  &BufferSize, &mI2cMasterHandle);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register a protocol registration notification callback on the driver
+  // binding protocol so we can attempt to connect our I2C master to it
+  // as soon as it appears.
+  //
+  EfiCreateProtocolNotifyEvent (
+    &gEfiDriverBindingProtocolGuid,
+    TPL_CALLBACK,
+    DriverRegistrationEvent,
+    NULL,
+    &mDriverEventRegistration);
+
+  //
+  // Register for the virtual address change event
+  //
+  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
+                  LibRtcVirtualNotifyEvent, NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &mRtcVirtualAddrChangeEvent);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
new file mode 100644
index 000000000000..bc8fc60c0602
--- /dev/null
+++ b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
@@ -0,0 +1,29 @@
+#/** @file
+#
+#  Copyright (c) 2017, Linaro, Ltd. 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]
+  DEC_SPECIFICATION              = 0x0001001A
+  PACKAGE_NAME                   = Pcf8563RealTimeClockLib
+  PACKAGE_GUID                   = 44d63668-c86b-446a-b303-f3a5176702aa
+  PACKAGE_VERSION                = 0.1
+
+[Guids]
+  gPcf8563RealTimeClockLibTokenSpaceGuid = { 0xaaf5b169, 0x93a0, 0x4d60, { 0xba, 0xe4, 0x06, 0x07, 0x92, 0x8e, 0x63, 0xdd }}
+
+[Protocols]
+  gPcf8563RealTimeClockLibI2cMasterProtolGuid = { 0xa6af18ae, 0x3bd5, 0x4af9, { 0xbb, 0x6a, 0xdb, 0x85, 0x07, 0x62, 0x81, 0x38 }}
+
+[PcdsFixedAtBuild]
+  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress|0x51|UINT8|0x00000001
+  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency|400|UINT16|0x00000002
diff --git a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
new file mode 100644
index 000000000000..e1e001162144
--- /dev/null
+++ b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
@@ -0,0 +1,52 @@
+#/** @file
+#
+#  Copyright (c) 2017, Linaro, Ltd. 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                    = 0x0001001A
+  BASE_NAME                      = Pcf8563RealTimeClockLib
+  FILE_GUID                      = 1e3d33f3-a671-4116-bd81-6b435296c1e0
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = RealTimeClockLib
+
+[Sources.common]
+  Pcf8563RealTimeClockLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  IoLib
+  UefiBootServicesTableLib
+  UefiLib
+  UefiRuntimeLib
+
+[Guids]
+  gEfiEventVirtualAddressChangeGuid
+
+[Protocols]
+  gEfiDriverBindingProtocolGuid                   ## CONSUMES
+  gEfiI2cMasterProtocolGuid                       ## CONSUMES
+  gPcf8563RealTimeClockLibI2cMasterProtolGuid     ## CONSUMES
+
+[FixedPcd]
+  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress
+  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency
+
+[Depex]
+  gPcf8563RealTimeClockLibI2cMasterProtolGuid
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH edk2-platforms 2/3] Silicon/Socionext: implement I2C master protocol for SynQuacer I2C
  2017-11-03 10:16 [RFC PATCH edk2-platforms 0/3] add I2C RTC support to DeveloperBox Ard Biesheuvel
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP Ard Biesheuvel
@ 2017-11-03 10:16 ` Ard Biesheuvel
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 3/3] Platform/DeveloperBox: wire up RTC support Ard Biesheuvel
  2 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2017-11-03 10:16 UTC (permalink / raw)
  To: edk2-devel, leif.lindholm, daniel.thompson; +Cc: Ard Biesheuvel

Add a driver that produces the I2C master protocol on top of the I2C
controllers that are implemented in the SynQuacer Socionext SoC. Note
that this supports two modes simultaneously: I2C controllers that are
only usable at boot time, and usable via the I2C protocol stack, and
I2C controllers that are dedicated for the RTC or other runtime
components.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentName.c     | 185 ++++++
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBinding.c     | 238 ++++++++
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.c   | 618 ++++++++++++++++++++
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.h   | 162 +++++
 Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf |  59 ++
 Silicon/Socionext/SynQuacer/SynQuacer.dec                               |   5 +
 6 files changed, 1267 insertions(+)

diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentName.c b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentName.c
new file mode 100644
index 000000000000..8d7aa417505b
--- /dev/null
+++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/ComponentName.c
@@ -0,0 +1,185 @@
+/** @file
+
+  Copyright (c) 2017, Linaro Ltd. All rights reserved.
+
+  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.
+
+**/
+
+#include "SynQuacerI2cDxe.h"
+
+STATIC EFI_UNICODE_STRING_TABLE mSynQuacerI2cDriverNameTable[] = {
+  {
+    "en",
+    (CHAR16 *)L"Socionext SynQuacer I2C Driver"
+  },
+  { }
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mSynQuacerI2cControllerNameTable[] = {
+  {
+    "en",
+    (CHAR16 *)L"Socionext SynQuacer I2C Controller"
+  },
+  { }
+};
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SynQuacerI2cGetDriverName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **DriverName
+  )
+{
+  return LookupUnicodeString2 (Language,
+                               This->SupportedLanguages,
+                               mSynQuacerI2cDriverNameTable,
+                               DriverName,
+                               FALSE);
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SynQuacerI2cGetControllerName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL                    *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  )
+{
+  if (ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return LookupUnicodeString2 (Language,
+                               This->SupportedLanguages,
+                               mSynQuacerI2cControllerNameTable,
+                               ControllerName,
+                               FALSE);
+}
+
+//
+// EFI Component Name 2 Protocol
+//
+EFI_COMPONENT_NAME2_PROTOCOL gSynQuacerI2cDriverComponentName2 = {
+  SynQuacerI2cGetDriverName,
+  SynQuacerI2cGetControllerName,
+  "en"
+};
diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBinding.c b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBinding.c
new file mode 100644
index 000000000000..22e53408f419
--- /dev/null
+++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/DriverBinding.c
@@ -0,0 +1,238 @@
+/** @file
+
+  Copyright (c) 2017, Linaro Ltd. 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.
+
+**/
+
+#include "SynQuacerI2cDxe.h"
+
+/**
+  Tests to see if this driver supports a given controller.
+
+  @param  This[in]                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL
+                                   instance.
+  @param  ControllerHandle[in]     The handle of the controller to test.
+  @param  RemainingDevicePath[in]  The remaining device path.
+                                   (Ignored - this is not a bus driver.)
+
+  @retval EFI_SUCCESS              The driver supports this controller.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle is
+                                   already being managed by the driver specified
+                                   by This.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle is
+                                   not supported by the driver specified by This.
+
+**/
+EFI_STATUS
+EFIAPI
+SynQuacerI2cDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  NON_DISCOVERABLE_DEVICE    *Dev;
+  EFI_STATUS                 Status;
+
+  //
+  //  Connect to the USB stack
+  //
+  Status = gBS->OpenProtocol (ControllerHandle,
+                              &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                              (VOID **) &Dev,
+                              This->DriverBindingHandle,
+                              ControllerHandle,
+                              EFI_OPEN_PROTOCOL_BY_DRIVER);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (CompareGuid (Dev->Type, &gSynQuacerNonDiscoverableI2cMasterGuid) ||
+      CompareGuid (Dev->Type, &gSynQuacerNonDiscoverableRuntimeI2cMasterGuid)) {
+    Status = EFI_SUCCESS;
+  } else {
+    Status = EFI_UNSUPPORTED;
+  }
+
+  //
+  // Clean up.
+  //
+  gBS->CloseProtocol (ControllerHandle,
+                      &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                      This->DriverBindingHandle,
+                      ControllerHandle);
+
+  return Status;
+}
+
+
+/**
+  Starts a device controller or a bus controller.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL
+                                   instance.
+  @param[in]  ControllerHandle     The handle of the device to start. This
+                                   handle must support a protocol interface that
+                                   supplies an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  The remaining portion of the device path.
+                                   (Ignored - this is not a bus driver.)
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a
+                                   device error.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a
+                                   lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+SynQuacerI2cDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  )
+{
+  return SynQuacerI2cInit (This->DriverBindingHandle, ControllerHandle);
+}
+
+
+/**
+  Stops a device controller or a bus controller.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL
+                                instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The handle
+                                must support a bus specific I/O protocol for the
+                                driver to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in
+                                ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be
+                                NULL if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device
+                                error.
+
+**/
+EFI_STATUS
+EFIAPI
+SynQuacerI2cDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN  EFI_HANDLE                  ControllerHandle,
+  IN  UINTN                       NumberOfChildren,
+  IN  EFI_HANDLE                  *ChildHandleBuffer OPTIONAL
+  )
+{
+  return SynQuacerI2cRelease (This->DriverBindingHandle, ControllerHandle);
+}
+
+
+STATIC EFI_DRIVER_BINDING_PROTOCOL  gSynQuacerI2cDriverBinding = {
+  SynQuacerI2cDriverBindingSupported,
+  SynQuacerI2cDriverBindingStart,
+  SynQuacerI2cDriverBindingStop,
+  0xa,
+  NULL,
+  NULL
+};
+
+
+/**
+  The entry point of I2c UEFI Driver.
+
+  @param  ImageHandle                The image handle of the UEFI Driver.
+  @param  SystemTable                A pointer to the EFI System Table.
+
+  @retval  EFI_SUCCESS               The Driver or UEFI Driver exited normally.
+  @retval  EFI_INCOMPATIBLE_VERSION  _gUefiDriverRevision is greater than
+                                     SystemTable->Hdr.Revision.
+
+**/
+EFI_STATUS
+EFIAPI
+SynQuacerI2cDxeEntryPoint (
+  IN  EFI_HANDLE          ImageHandle,
+  IN  EFI_SYSTEM_TABLE    *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+
+  //
+  //  Add the driver to the list of drivers
+  //
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle, SystemTable, &gSynQuacerI2cDriverBinding, ImageHandle,
+             NULL, &gSynQuacerI2cDriverComponentName2);
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "*** Installed SynQuacer I2C UEFI driver! ***\n"));
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Unload function for the I2c UEFI Driver.
+
+  @param  ImageHandle[in]        The allocated handle for the EFI image
+
+  @retval EFI_SUCCESS            The driver was unloaded successfully
+  @retval EFI_INVALID_PARAMETER  ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+SynQuacerI2cDxeUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HANDLE  *HandleBuffer;
+  UINTN       HandleCount;
+  UINTN       Index;
+
+  //
+  // Retrieve all USB I/O handles in the handle database
+  //
+  Status = gBS->LocateHandleBuffer (ByProtocol,
+                                    &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                                    NULL,
+                                    &HandleCount,
+                                    &HandleBuffer);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Disconnect the driver from the handles in the handle database
+  //
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->DisconnectController (HandleBuffer[Index],
+                                        gImageHandle,
+                                        NULL);
+  }
+
+  //
+  // Free the handle array
+  //
+  gBS->FreePool (HandleBuffer);
+
+  //
+  // Uninstall protocols installed by the driver in its entrypoint
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (ImageHandle,
+                  &gEfiDriverBindingProtocolGuid,
+                  &gSynQuacerI2cDriverBinding,
+                  NULL
+                  );
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.c b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.c
new file mode 100644
index 000000000000..adc4813c7cd5
--- /dev/null
+++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.c
@@ -0,0 +1,618 @@
+/** @file
+
+  Copyright (c) 2017, Linaro, Ltd. 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.
+
+**/
+
+#include "SynQuacerI2cDxe.h"
+
+#define __DEBUG(x)        do { if (!EfiAtRuntime()) DEBUG (x); } while (0)
+
+/**
+  Set the frequency for the I2C clock line.
+
+  This routine must be called at or below TPL_NOTIFY.
+
+  The software and controller do a best case effort of using the specified
+  frequency for the I2C bus.  If the frequency does not match exactly then
+  the I2C master protocol selects the next lower frequency to avoid
+  exceeding the operating conditions for any of the I2C devices on the bus.
+  For example if 400 KHz was specified and the controller's divide network
+  only supports 402 KHz or 398 KHz then the I2C master protocol selects 398
+  KHz.  If there are not lower frequencies available, then return
+  EFI_UNSUPPORTED.
+
+  @param[in] This           Pointer to an EFI_I2C_MASTER_PROTOCOL structure
+  @param[in] BusClockHertz  Pointer to the requested I2C bus clock frequency
+                            in Hertz.  Upon return this value contains the
+                            actual frequency in use by the I2C controller.
+
+  @retval EFI_SUCCESS           The bus frequency was set successfully.
+  @retval EFI_ALREADY_STARTED   The controller is busy with another transaction.
+  @retval EFI_INVALID_PARAMETER BusClockHertz is NULL
+  @retval EFI_UNSUPPORTED       The controller does not support this frequency.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SynQuacerI2cSetBusFrequency (
+  IN CONST EFI_I2C_MASTER_PROTOCOL   *This,
+  IN OUT UINTN                       *BusClockHertz
+  )
+{
+  SYNQUACER_I2C_MASTER        *I2c;
+  UINT8                       Ccr, Csr;
+
+  I2c = SYNQUACER_I2C_FROM_THIS (This);
+
+  if (BusClockHertz == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  switch (*BusClockHertz) {
+  case F_I2C_SPEED_FM:
+    if (REFCLK_RATE <= F_I2C_CLK_RATE_18M) {
+      Ccr = F_I2C_CCR_CS_FAST_MAX_18M (REFCLK_RATE);
+      Csr = F_I2C_CSR_CS_FAST_MAX_18M (REFCLK_RATE);
+    } else {
+      Ccr = F_I2C_CCR_CS_FAST_MIN_18M (REFCLK_RATE);
+      Csr = F_I2C_CSR_CS_FAST_MIN_18M (REFCLK_RATE);
+    }
+
+    // Set Clock and enable, Set fast mode
+    MmioWrite8 (I2c->MmioBase + F_I2C_REG_CCR,
+      Ccr | F_I2C_CCR_FM | F_I2C_CCR_EN);
+    MmioWrite8 (I2c->MmioBase + F_I2C_REG_CSR, Csr);
+    break;
+
+  case F_I2C_SPEED_SM:
+    if (REFCLK_RATE <= F_I2C_CLK_RATE_18M) {
+      Ccr = F_I2C_CCR_CS_STANDARD_MAX_18M (REFCLK_RATE);
+      Csr = F_I2C_CSR_CS_STANDARD_MAX_18M (REFCLK_RATE);
+    } else {
+      Ccr = F_I2C_CCR_CS_STANDARD_MIN_18M (REFCLK_RATE);
+      Csr = F_I2C_CSR_CS_STANDARD_MIN_18M (REFCLK_RATE);
+    }
+
+    // Set Clock and enable, Set standard mode
+    MmioWrite8 (I2c->MmioBase + F_I2C_REG_CCR, Ccr | F_I2C_CCR_EN);
+    MmioWrite8 (I2c->MmioBase + F_I2C_REG_CSR, Csr);
+    break;
+
+  default:
+    return EFI_UNSUPPORTED;
+  }
+
+  MemoryFence ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Reset the I2C controller and configure it for use
+
+  This routine must be called at or below TPL_NOTIFY.
+
+  The I2C controller is reset.  The caller must call SetBusFrequench() after
+  calling Reset().
+
+  @param[in]     This       Pointer to an EFI_I2C_MASTER_PROTOCOL structure.
+
+  @retval EFI_SUCCESS         The reset completed successfully.
+  @retval EFI_ALREADY_STARTED The controller is busy with another transaction.
+  @retval EFI_DEVICE_ERROR    The reset operation failed.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SynQuacerI2cReset (
+  IN CONST EFI_I2C_MASTER_PROTOCOL *This
+  )
+{
+  SYNQUACER_I2C_MASTER        *I2c;
+
+  I2c = SYNQUACER_I2C_FROM_THIS (This);
+
+  // Disable the clock
+  MmioWrite8 (I2c->MmioBase + F_I2C_REG_CCR, 0);
+  MmioWrite8 (I2c->MmioBase + F_I2C_REG_CSR, 0);
+
+  MemoryFence ();
+
+  // Set own Address
+  MmioWrite8 (I2c->MmioBase + F_I2C_REG_ADR, 0);
+
+  // Set PCLK frequency
+  MmioWrite8 (I2c->MmioBase + F_I2C_REG_FSR, F_I2C_BUS_CLK_FR (REFCLK_RATE));
+
+  // clear IRQ (INT=0, BER=0), Interrupt Disable
+  MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, 0);
+  MmioWrite8 (I2c->MmioBase + F_I2C_REG_BC2R, 0);
+
+  MemoryFence ();
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+Stall (
+  IN  UINTN     Cycles
+  )
+{
+  while (Cycles--) {
+    MemoryFence ();
+  }
+}
+
+STATIC
+EFI_STATUS
+SynQuacerI2cMasterStart (
+  IN  SYNQUACER_I2C_MASTER        *I2c,
+  IN  UINTN                       SlaveAddress,
+  IN  EFI_I2C_OPERATION           *Op
+  )
+{
+  UINT8                       Bsr;
+  UINT8                       Bcr;
+
+  if (Op->Flags & I2C_FLAG_READ) {
+    MmioWrite8 (I2c->MmioBase + F_I2C_REG_DAR, (SlaveAddress << 1) | 1);
+  } else {
+    MmioWrite8 (I2c->MmioBase + F_I2C_REG_DAR, SlaveAddress << 1);
+  }
+
+  __DEBUG ((DEBUG_INFO, "%a: slave:0x%02x\n", __FUNCTION__, SlaveAddress));
+
+  Bsr = MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR);
+  Bcr = MmioRead8 (I2c->MmioBase + F_I2C_REG_BCR);
+
+  __DEBUG ((DEBUG_INFO, "%a: Bsr:0x%x, Bcr:0x%x\n", __FUNCTION__, Bsr, Bcr));
+
+  if ((Bsr & F_I2C_BSR_BB) && !(Bcr & F_I2C_BCR_MSS)) {
+    __DEBUG ((DEBUG_INFO, "%a: bus is busy\n", __FUNCTION__));
+    return EFI_ALREADY_STARTED;
+  }
+
+  if (Bsr & F_I2C_BSR_BB) { // Bus is busy
+    __DEBUG ((DEBUG_INFO, "%a: Continuous Start\n", __FUNCTION__));
+    MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, Bcr | F_I2C_BCR_SCC);
+  } else {
+    if (Bcr & F_I2C_BCR_MSS) {
+      __DEBUG ((DEBUG_WARN, "%a: is not in master mode\n", __FUNCTION__));
+      return EFI_DEVICE_ERROR;
+    }
+    __DEBUG ((DEBUG_INFO, "%a: Start Condition\n", __FUNCTION__));
+    MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR,
+                Bcr | F_I2C_BCR_MSS | F_I2C_BCR_INTE | F_I2C_BCR_BEIE);
+  }
+
+  Stall (1000);
+
+  Bsr = MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR);
+  Bcr = MmioRead8 (I2c->MmioBase + F_I2C_REG_BCR);
+
+  __DEBUG ((DEBUG_INFO, "%a: Bsr:0x%x, Bcr:0x%x\n", __FUNCTION__, Bsr, Bcr));
+
+  if ((Bsr & F_I2C_BSR_AL) || !(Bcr & F_I2C_BCR_MSS)) {
+    __DEBUG ((DEBUG_INFO, "%a: arbitration lost\n", __FUNCTION__));
+    return EFI_DEVICE_ERROR;
+  }
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+WaitForInt (
+  IN  SYNQUACER_I2C_MASTER        *I2c
+  )
+{
+  UINT8       Bsr;
+  UINTN       Timeout = 50000;
+
+  do {
+    MemoryFence ();
+
+    Bsr = MmioRead8 (I2c->MmioBase + F_I2C_REG_BCR);
+    if (Bsr & F_I2C_BCR_INT) {
+      return EFI_SUCCESS;
+    }
+  } while (Timeout--);
+
+  return EFI_DEVICE_ERROR;
+}
+
+//STATIC
+//EFI_STATUS
+//WaitForAck (
+//  IN  SYNQUACER_I2C_MASTER        *I2c
+//  )
+//{
+//  UINT8       Bsr;
+//  UINTN       Timeout = 50000;
+//
+//  do {
+//    MemoryFence ();
+//
+//    Bsr = MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR);
+//    if (!(Bsr & F_I2C_BSR_LRB)) {
+//      return EFI_SUCCESS;
+//    }
+//  } while (Timeout--);
+//
+//  return EFI_DEVICE_ERROR;
+//}
+
+/**
+  Start an I2C transaction on the host controller.
+
+  This routine must be called at or below TPL_NOTIFY.  For synchronous
+  requests this routine must be called at or below TPL_CALLBACK.
+
+  This function initiates an I2C transaction on the controller.  To
+  enable proper error handling by the I2C protocol stack, the I2C
+  master protocol does not support queuing but instead only manages
+  one I2C transaction at a time.  This API requires that the I2C bus
+  is in the correct configuration for the I2C transaction.
+
+  The transaction is performed by sending a start-bit and selecting the
+  I2C device with the specified I2C slave address and then performing
+  the specified I2C operations.  When multiple operations are requested
+  they are separated with a repeated start bit and the slave address.
+  The transaction is terminated with a stop bit.
+
+  When Event is NULL, StartRequest operates synchronously and returns
+  the I2C completion status as its return value.
+
+  When Event is not NULL, StartRequest synchronously returns EFI_SUCCESS
+  indicating that the I2C transaction was started asynchronously.  The
+  transaction status value is returned in the buffer pointed to by
+  I2cStatus upon the completion of the I2C transaction when I2cStatus
+  is not NULL.  After the transaction status is returned the Event is
+  signaled.
+
+  Note: The typical consumer of this API is the I2C host protocol.
+  Extreme care must be taken by other consumers of this API to prevent
+  confusing the third party I2C drivers due to a state change at the
+  I2C device which the third party I2C drivers did not initiate.  I2C
+  platform specific code may use this API within these guidelines.
+
+  @param[in] This           Pointer to an EFI_I2C_MASTER_PROTOCOL structure.
+  @param[in] SlaveAddress   Address of the device on the I2C bus.  Set the
+                            I2C_ADDRESSING_10_BIT when using 10-bit addresses,
+                            clear this bit for 7-bit addressing.  Bits 0-6
+                            are used for 7-bit I2C slave addresses and bits
+                            0-9 are used for 10-bit I2C slave addresses.
+  @param[in] RequestPacket  Pointer to an EFI_I2C_REQUEST_PACKET
+                            structure describing the I2C transaction.
+  @param[in] Event          Event to signal for asynchronous transactions,
+                            NULL for synchronous transactions
+  @param[out] I2cStatus     Optional buffer to receive the I2C transaction
+                            completion status
+
+  @retval EFI_SUCCESS           The asynchronous transaction was successfully
+                                started when Event is not NULL.
+  @retval EFI_SUCCESS           The transaction completed successfully when
+                                Event is NULL.
+  @retval EFI_ALREADY_STARTED   The controller is busy with another transaction.
+  @retval EFI_BAD_BUFFER_SIZE   The RequestPacket->LengthInBytes value is too
+                                large.
+  @retval EFI_DEVICE_ERROR      There was an I2C error (NACK) during the
+                                transaction.
+  @retval EFI_INVALID_PARAMETER RequestPacket is NULL
+  @retval EFI_NOT_FOUND         Reserved bit set in the SlaveAddress parameter
+  @retval EFI_NO_RESPONSE       The I2C device is not responding to the slave
+                                address.  EFI_DEVICE_ERROR will be returned if
+                                the controller cannot distinguish when the NACK
+                                occurred.
+  @retval EFI_OUT_OF_RESOURCES  Insufficient memory for I2C transaction
+  @retval EFI_UNSUPPORTED       The controller does not support the requested
+                                transaction.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SynQuacerI2cStartRequest (
+  IN  CONST EFI_I2C_MASTER_PROTOCOL   *This,
+  IN  UINTN                           SlaveAddress,
+  IN  EFI_I2C_REQUEST_PACKET          *RequestPacket,
+  IN  EFI_EVENT                       Event      OPTIONAL,
+  OUT EFI_STATUS                      *I2cStatus OPTIONAL
+  )
+{
+  SYNQUACER_I2C_MASTER        *I2c;
+  UINTN                       Idx;
+  EFI_I2C_OPERATION           *Op;
+  UINTN                       BufIdx;
+  EFI_STATUS                  Status;
+  EFI_TPL                     Tpl;
+  BOOLEAN                     AtRuntime;
+  UINT8                       Bsr;
+  UINT8                       Bcr;
+
+  I2c = SYNQUACER_I2C_FROM_THIS (This);
+
+  //
+  // We can only do synchronous operations at runtime
+  //
+  AtRuntime = EfiAtRuntime ();
+  if (AtRuntime && Event != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (!AtRuntime) {
+    Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+  }
+
+  for (Idx = 0, Op = RequestPacket->Operation, Status = EFI_SUCCESS;
+       Idx < RequestPacket->OperationCount && !EFI_ERROR (Status);
+       Idx++, Op++) {
+
+    Status = SynQuacerI2cMasterStart (I2c, SlaveAddress, Op);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Status = WaitForInt (I2c);
+    if (EFI_ERROR (Status)) {
+        __DEBUG ((DEBUG_WARN, "%a: Timeout waiting for interrupt - %r\n",
+        Status));
+      break;
+    }
+
+    if (MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR) & F_I2C_BSR_LRB) {
+      __DEBUG ((DEBUG_WARN, "%a: No ack received - %r\n", __FUNCTION__));
+      Status = EFI_DEVICE_ERROR;
+      break;
+    }
+
+    BufIdx = 0;
+    do {
+      Bsr = MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR);
+      Bcr = MmioRead8 (I2c->MmioBase + F_I2C_REG_BCR);
+
+      __DEBUG ((DEBUG_INFO, "%a: Bcr:0x%x\n", __FUNCTION__, Bcr));
+
+      if (Bcr & F_I2C_BCR_BER) {
+        __DEBUG ((DEBUG_WARN, "%a: Bus error detected\n", __FUNCTION__));
+        Status = EFI_DEVICE_ERROR;
+        break;
+      }
+
+      if ((Bsr & F_I2C_BSR_AL) || !(Bcr & F_I2C_BCR_MSS)) {
+        __DEBUG ((DEBUG_WARN, "%a: Arbitration lost\n", __FUNCTION__));
+        Status = EFI_DEVICE_ERROR;
+        break;
+      }
+
+      if (Op->Flags & I2C_FLAG_READ) {
+        if (BufIdx == Op->LengthInBytes - 1) {
+          MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR,
+            F_I2C_BCR_MSS | F_I2C_BCR_INTE | F_I2C_BCR_BEIE);
+        } else {
+          MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR,
+            F_I2C_BCR_MSS | F_I2C_BCR_INTE | F_I2C_BCR_BEIE | F_I2C_BCR_ACK);
+        }
+
+        Status = WaitForInt (I2c);
+        if (EFI_ERROR (Status)) {
+          __DEBUG ((DEBUG_WARN, "%a: Timeout waiting for interrupt - %r\n",
+            __FUNCTION__, Status));
+          break;
+        }
+
+        if (!(MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR) & F_I2C_BSR_FBT)) {
+          Op->Buffer [BufIdx++] = MmioRead8 (I2c->MmioBase + F_I2C_REG_DAR);
+        }
+      } else {
+        MmioWrite8 (I2c->MmioBase + F_I2C_REG_DAR, Op->Buffer [BufIdx++]);
+        MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR,
+          F_I2C_BCR_MSS | F_I2C_BCR_INTE | F_I2C_BCR_BEIE);
+
+        Status = WaitForInt (I2c);
+        if (EFI_ERROR (Status)) {
+          __DEBUG ((DEBUG_WARN, "%a: Timeout waiting for interrupt - %r\n",
+            __FUNCTION__, Status));
+          break;
+        }
+
+        if (MmioRead8 (I2c->MmioBase + F_I2C_REG_BSR) & F_I2C_BSR_LRB) {
+          __DEBUG ((DEBUG_WARN, "%a: No ack received\n", __FUNCTION__));
+          Status = EFI_DEVICE_ERROR;
+          break;
+        }
+      }
+    } while (BufIdx < Op->LengthInBytes);
+  }
+
+  // Stop the transfer
+  MmioWrite8 (I2c->MmioBase + F_I2C_REG_BCR, 0);
+
+  if (!AtRuntime) {
+    gBS->RestoreTPL (Tpl);
+  }
+
+  if (Event) {
+    *I2cStatus = Status;
+    gBS->SignalEvent (Event);
+  }
+  return Status;
+}
+
+STATIC
+VOID
+EFIAPI
+SynQuacerI2cVirtualNotifyEvent (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  SYNQUACER_I2C_MASTER    *I2c = Context;
+
+  EfiConvertPointer (0x0, (VOID **)&I2c->I2cMaster.SetBusFrequency);
+  EfiConvertPointer (0x0, (VOID **)&I2c->I2cMaster.Reset);
+  EfiConvertPointer (0x0, (VOID **)&I2c->I2cMaster.StartRequest);
+  EfiConvertPointer (0x0, (VOID **)&I2c->I2cMaster.I2cControllerCapabilities);
+  EfiConvertPointer (0x0, (VOID **)&I2c->MmioBase);
+}
+
+EFI_STATUS
+SynQuacerI2cInit (
+  IN      EFI_HANDLE        DriverBindingHandle,
+  IN      EFI_HANDLE        ControllerHandle
+  )
+{
+  EFI_STATUS                        Status;
+  NON_DISCOVERABLE_DEVICE           *Dev;
+  SYNQUACER_I2C_MASTER              *I2c;
+  BOOLEAN                           Runtime;
+
+  Status = gBS->OpenProtocol (ControllerHandle,
+                              &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                              (VOID **)&Dev, DriverBindingHandle,
+                              ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Runtime = CompareGuid (Dev->Type,
+                         &gSynQuacerNonDiscoverableRuntimeI2cMasterGuid);
+
+  // Allocate Resources
+  if (Runtime) {
+    I2c = AllocateRuntimeZeroPool (sizeof (SYNQUACER_I2C_MASTER));
+  } else {
+    I2c = AllocateZeroPool (sizeof (SYNQUACER_I2C_MASTER));
+  }
+  if (I2c == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto CloseProtocol;
+  }
+
+  I2c->Signature                  = SYNQUACER_I2C_SIGNATURE;
+  I2c->I2cMaster.SetBusFrequency  = SynQuacerI2cSetBusFrequency;
+  I2c->I2cMaster.Reset            = SynQuacerI2cReset;
+  I2c->I2cMaster.StartRequest     = SynQuacerI2cStartRequest;
+  I2c->MmioBase                   = Dev->Resources[0].AddrRangeMin;
+  I2c->Dev                        = Dev;
+
+  if (Runtime) {
+    I2c->Runtime = TRUE;
+
+    // Declare the controller as EFI_MEMORY_RUNTIME
+    Status = gDS->AddMemorySpace (
+                    EfiGcdMemoryTypeMemoryMappedIo,
+                    Dev->Resources[0].AddrRangeMin,
+                    Dev->Resources[0].AddrLen,
+                    EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
+    if (EFI_ERROR (Status)) {
+      __DEBUG ((DEBUG_WARN, "%a: failed to add memory space - %r\n",
+        __FUNCTION__, Status));
+    }
+
+    Status = gDS->SetMemorySpaceAttributes (
+                    Dev->Resources[0].AddrRangeMin,
+                    Dev->Resources[0].AddrLen,
+                    EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
+    if (EFI_ERROR (Status)) {
+      goto FreeDevice;
+    }
+
+    //
+    // Register for the virtual address change event
+    //
+    Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
+                    SynQuacerI2cVirtualNotifyEvent, I2c,
+                    &gEfiEventVirtualAddressChangeGuid,
+                    &I2c->VirtualAddressChangeEvent);
+    if (EFI_ERROR (Status)) {
+      goto FreeDevice;
+    }
+  }
+
+  CopyGuid (&I2c->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);
+  I2c->DevicePath.MmioBase = I2c->MmioBase;
+  SetDevicePathNodeLength (&I2c->DevicePath.Vendor,
+    sizeof (I2c->DevicePath) - sizeof (I2c->DevicePath.End));
+  SetDevicePathEndNode (&I2c->DevicePath.End);
+
+  Status = gBS->InstallMultipleProtocolInterfaces (&ControllerHandle,
+                  &gEfiI2cMasterProtocolGuid, &I2c->I2cMaster,
+                  &gEfiDevicePathProtocolGuid, &I2c->DevicePath,
+                  NULL);
+  if (EFI_ERROR (Status)) {
+    goto CloseEvent;
+  }
+  return EFI_SUCCESS;
+
+CloseEvent:
+  if (Runtime) {
+    gBS->CloseEvent (I2c->VirtualAddressChangeEvent);
+  }
+
+FreeDevice:
+  FreePool (I2c);
+
+CloseProtocol:
+  gBS->CloseProtocol (ControllerHandle,
+                      &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                      DriverBindingHandle,
+                      ControllerHandle);
+  return Status;
+}
+
+EFI_STATUS
+SynQuacerI2cRelease (
+  IN      EFI_HANDLE        DriverBindingHandle,
+  IN      EFI_HANDLE        ControllerHandle
+  )
+{
+  EFI_I2C_MASTER_PROTOCOL       *I2cMaster;
+  SYNQUACER_I2C_MASTER          *I2c;
+  EFI_STATUS                    Status;
+
+  Status = gBS->HandleProtocol (ControllerHandle,
+                                &gEfiI2cMasterProtocolGuid,
+                                (VOID **)&I2cMaster);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  I2c = SYNQUACER_I2C_FROM_THIS (I2cMaster);
+
+  Status = gBS->UninstallMultipleProtocolInterfaces (ControllerHandle,
+                  &gEfiI2cMasterProtocolGuid, I2cMaster,
+                  &gEfiDevicePathProtocolGuid, &I2c->DevicePath,
+                  NULL);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (I2c->Runtime) {
+    gBS->CloseEvent (I2c->VirtualAddressChangeEvent);
+  }
+
+  Status = gBS->CloseProtocol (ControllerHandle,
+                               &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                               DriverBindingHandle,
+                               ControllerHandle);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->FreePool (I2c);
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.h b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.h
new file mode 100644
index 000000000000..dac02e951bb2
--- /dev/null
+++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.h
@@ -0,0 +1,162 @@
+/** @file
+
+  Copyright (c) 2017, Linaro, Ltd. 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.
+
+**/
+
+#ifndef __SYNQUACER_I2C_DXE_H__
+#define __SYNQUACER_I2C_DXE_H__
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+#include <Protocol/I2cMaster.h>
+#include <Protocol/NonDiscoverableDevice.h>
+
+extern EFI_COMPONENT_NAME2_PROTOCOL gSynQuacerI2cDriverComponentName2;
+
+#define SYNQUACER_I2C_SIGNATURE         SIGNATURE_32 ('S', 'I', '2', 'C')
+#define SYNQUACER_I2C_FROM_THIS(a)      CR (a, SYNQUACER_I2C_MASTER, \
+                                            I2cMaster, SYNQUACER_I2C_SIGNATURE)
+
+#pragma pack(1)
+typedef struct {
+  VENDOR_DEVICE_PATH              Vendor;
+  UINT64                          MmioBase;
+  EFI_DEVICE_PATH_PROTOCOL        End;
+} SYNQUACER_I2C_DEVICE_PATH;
+#pragma pack()
+
+typedef struct {
+  UINT32                          Signature;
+  EFI_I2C_MASTER_PROTOCOL         I2cMaster;
+  EFI_PHYSICAL_ADDRESS            MmioBase;
+  SYNQUACER_I2C_DEVICE_PATH       DevicePath;
+  NON_DISCOVERABLE_DEVICE         *Dev;
+  EFI_EVENT                       VirtualAddressChangeEvent;
+  BOOLEAN                         Runtime;
+} SYNQUACER_I2C_MASTER;
+
+EFI_STATUS
+SynQuacerI2cInit (
+  IN      EFI_HANDLE              DriverBindingHandle,
+  IN      EFI_HANDLE              ControllerHandle
+  );
+
+EFI_STATUS
+SynQuacerI2cRelease (
+  IN      EFI_HANDLE              DriverBindingHandle,
+  IN      EFI_HANDLE              ControllerHandle
+  );
+
+#define REFCLK_RATE         FixedPcdGet32 (PcdI2cReferenceClock)
+
+#define DIV_ROUND_UP(n, d)  (((n) + (d) - 1) / (d))
+
+#define F_I2C_SPEED_SM      100
+#define F_I2C_SPEED_FM      400
+
+// I2C register adress definitions
+#define F_I2C_REG_BSR       (0x00 << 2) // Bus Status Regster
+#define F_I2C_REG_BCR       (0x01 << 2) // Bus Control Register
+#define F_I2C_REG_CCR       (0x02 << 2) // Clock Control Register
+#define F_I2C_REG_ADR       (0x03 << 2) // Address Register
+#define F_I2C_REG_DAR       (0x04 << 2) // Data Register
+#define F_I2C_REG_CSR       (0x05 << 2) // Expansion CS Register
+#define F_I2C_REG_FSR       (0x06 << 2) // Bus Clock Frequency Register
+#define F_I2C_REG_BC2R      (0x07 << 2) // Bus Control 2 Register
+
+// I2C register bit definitions
+#define F_I2C_BSR_FBT       BIT0        // First Byte Transfer
+#define F_I2C_BSR_GCA       BIT1        // General Call Address
+#define F_I2C_BSR_AAS       BIT2        // Address as Slave
+#define F_I2C_BSR_TRX       BIT3        // Transfer/Receive
+#define F_I2C_BSR_LRB       BIT4        // Last Received Bit
+#define F_I2C_BSR_AL        BIT5        // Arbitration Lost
+#define F_I2C_BSR_RSC       BIT6        // Repeated Start Condition
+#define F_I2C_BSR_BB        BIT7        // Bus Busy
+
+#define F_I2C_BCR_INT       BIT0        // Interrupt
+#define F_I2C_BCR_INTE      BIT1        // Interrupt Enable
+#define F_I2C_BCR_GCAA      BIT2        // General Call Access Acknowledge
+#define F_I2C_BCR_ACK       BIT3        // Acknowledge
+#define F_I2C_BCR_MSS       BIT4        // Master Slave Select
+#define F_I2C_BCR_SCC       BIT5        // Start Condition Continue
+#define F_I2C_BCR_BEIE      BIT6        // Bus Error Interrupt Enable
+#define F_I2C_BCR_BER       BIT7        // Bus Error
+
+#define F_I2C_CCR_CS_MASK   0x1f        // CCR Clock Period Select
+#define F_I2C_CCR_EN        BIT5        // Enable
+#define F_I2C_CCR_FM        BIT6        // Speed Mode Select
+
+#define F_I2C_CSR_CS_MASK   0x3f        // CSR Clock Period Select
+
+#define F_I2C_BC2R_SCLL     BIT0        // SCL Low Drive
+#define F_I2C_BC2R_SDAL     BIT1        // SDA Low Drive
+#define F_I2C_BC2R_SCLS     BIT4        // SCL Status
+#define F_I2C_BC2R_SDAS     BIT5        // SDA Status
+
+// PCLK frequency
+#define F_I2C_BUS_CLK_FR(rate)          ((rate) / 20000000 + 1)
+
+#define F_I2C_MIN_CLK_RATE              (14 * 1000000)  // min frequency 14 MHz
+#define F_I2C_MAX_CLK_RATE              (200 * 1000000) // max frequency 200 MHz
+#define F_I2C_CLK_RATE_18M              (18 * 1000000)  // threshold freq 18 MHz
+
+// STANDARD MODE frequency
+#define F_I2C_CLK_MASTER_STANDARD(rate) \
+            DIV_ROUND_UP (DIV_ROUND_UP ((rate), 100000) - 2, 2)
+
+// FAST MODE frequency
+#define F_I2C_CLK_MASTER_FAST(rate) \
+            DIV_ROUND_UP ((DIV_ROUND_UP ((rate), 400000) - 2) * 2, 3)
+
+// (clkrate <= 18000000)
+// calculate the value of CS bits in CCR register in standard mode
+#define F_I2C_CCR_CS_STANDARD_MAX_18M(rate) \
+            ((F_I2C_CLK_MASTER_STANDARD (rate) - 65) & F_I2C_CCR_CS_MASK)
+
+// calculate the value of CS bits in CSR register in standard mode
+#define F_I2C_CSR_CS_STANDARD_MAX_18M(rate) 0x00
+
+// calculate the value of CS bits in CCR register in fast mode
+#define F_I2C_CCR_CS_FAST_MAX_18M(rate) \
+            ((F_I2C_CLK_MASTER_FAST (rate) - 1)  & F_I2C_CCR_CS_MASK)
+
+// calculate the value of CS bits in CSR register in fast mode
+#define F_I2C_CSR_CS_FAST_MAX_18M(rate) 0x00
+
+// (clkrate > 18000000)
+// calculate the value of CS bits in CCR register in standard mode */
+#define F_I2C_CCR_CS_STANDARD_MIN_18M(rate) \
+            ((F_I2C_CLK_MASTER_STANDARD (rate) - 1) & F_I2C_CCR_CS_MASK)
+
+// calculate the value of CS bits in CSR register in standard mode
+#define F_I2C_CSR_CS_STANDARD_MIN_18M(rate) \
+            (((F_I2C_CLK_MASTER_STANDARD (rate) - 1) >> 5) & F_I2C_CSR_CS_MASK)
+
+// calculate the value of CS bits in CCR register in fast mode
+#define F_I2C_CCR_CS_FAST_MIN_18M(rate) \
+            ((F_I2C_CLK_MASTER_FAST (rate) - 1) & F_I2C_CCR_CS_MASK)
+
+/* calculate the value of CS bits in CSR register in fast mode */
+#define F_I2C_CSR_CS_FAST_MIN_18M(rate) \
+            (((F_I2C_CLK_MASTER_FAST (rate) - 1) >> 5) & F_I2C_CSR_CS_MASK)
+
+#endif
diff --git a/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf
new file mode 100644
index 000000000000..fa715366878c
--- /dev/null
+++ b/Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf
@@ -0,0 +1,59 @@
+#/** @file
+#
+#  Copyright (c) 2017, Linaro, Ltd. 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                    = 0x0001001A
+  BASE_NAME                      = SynQuacerI2cDxe
+  FILE_GUID                      = ab5ed376-dd38-4d22-ae89-b645a4a3236e
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SynQuacerI2cDxeEntryPoint
+  UNLOAD                         = SynQuacerI2cDxeUnload
+
+[Sources.common]
+  ComponentName.c
+  DriverBinding.c
+  SynQuacerI2cDxe.c
+  SynQuacerI2cDxe.h
+
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/Socionext/SynQuacer/SynQuacer.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  DevicePathLib
+  DxeServicesTableLib
+  IoLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiLib
+  UefiDriverEntryPoint
+  UefiRuntimeLib
+
+[Guids]
+  gEfiEventVirtualAddressChangeGuid
+  gSynQuacerNonDiscoverableI2cMasterGuid
+  gSynQuacerNonDiscoverableRuntimeI2cMasterGuid
+
+[Protocols]
+  gEdkiiNonDiscoverableDeviceProtocolGuid     ## TO_START
+  gEfiI2cMasterProtocolGuid                   ## BY_START
+
+[FixedPcd]
+  gSynQuacerTokenSpaceGuid.PcdI2cReferenceClock
+
+[Depex]
+  TRUE
diff --git a/Silicon/Socionext/SynQuacer/SynQuacer.dec b/Silicon/Socionext/SynQuacer/SynQuacer.dec
index a48338c4693a..6f2849efe026 100644
--- a/Silicon/Socionext/SynQuacer/SynQuacer.dec
+++ b/Silicon/Socionext/SynQuacer/SynQuacer.dec
@@ -22,6 +22,9 @@ [Includes]
 [Guids]
   gSynQuacerTokenSpaceGuid = { 0x4d04555b, 0xdfdc, 0x418a, { 0x8a, 0xab, 0x07, 0xce, 0xef, 0x46, 0x82, 0xbb } }
 
+  gSynQuacerNonDiscoverableI2cMasterGuid = { 0x364ee675, 0x9e44, 0x42b7, { 0xa5, 0xe4, 0x92, 0x84, 0xdb, 0x85, 0xda, 0x09 } }
+  gSynQuacerNonDiscoverableRuntimeI2cMasterGuid = { 0x5f35aa9b, 0x8c6f, 0x4828, { 0xbd, 0x44, 0x7c, 0xc0, 0xeb, 0x2d, 0xfe, 0xb9 } }
+
 [Ppis]
   gSynQuacerDramInfoPpiGuid = { 0x3e1d7356, 0xdda4, 0x4b1a, { 0x93, 0x46, 0xbf, 0x89, 0x1c, 0x86, 0x46, 0xcc } }
 
@@ -35,3 +38,5 @@ [PcdsFixedAtBuild]
   gSynQuacerTokenSpaceGuid.PcdNetsecPhyAddress|0|UINT8|0x00000005
 
   gSynQuacerTokenSpaceGuid.PcdClearSettingsGpioPin|0|UINT32|0x00000006
+
+  gSynQuacerTokenSpaceGuid.PcdI2cReferenceClock|62500000|UINT32|0x00000007
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH edk2-platforms 3/3] Platform/DeveloperBox: wire up RTC support
  2017-11-03 10:16 [RFC PATCH edk2-platforms 0/3] add I2C RTC support to DeveloperBox Ard Biesheuvel
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP Ard Biesheuvel
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 2/3] Silicon/Socionext: implement I2C master protocol for SynQuacer I2C Ard Biesheuvel
@ 2017-11-03 10:16 ` Ard Biesheuvel
  2017-11-08 16:47   ` Leif Lindholm
  2 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2017-11-03 10:16 UTC (permalink / raw)
  To: edk2-devel, leif.lindholm, daniel.thompson; +Cc: Ard Biesheuvel

Add the drivers, library resolutions and PCD settings to enable RTC
support on DeveloperBox. Also, update PlatformDxe to register the
non-discoverable device handles for both I2C controllers.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 Platform/Socionext/DeveloperBox/DeveloperBox.dsc                                          |  8 ++-
 Platform/Socionext/DeveloperBox/DeveloperBox.fdf                                          |  5 ++
 Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c                             | 76 +++++++++++++++++---
 Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf                           |  6 +-
 Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h                                  |  8 +++
 Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c |  4 ++
 6 files changed, 96 insertions(+), 11 deletions(-)

diff --git a/Platform/Socionext/DeveloperBox/DeveloperBox.dsc b/Platform/Socionext/DeveloperBox/DeveloperBox.dsc
index b558b1f805b4..91898faa6ecc 100644
--- a/Platform/Socionext/DeveloperBox/DeveloperBox.dsc
+++ b/Platform/Socionext/DeveloperBox/DeveloperBox.dsc
@@ -446,8 +446,7 @@ [Components.common]
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
   EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf {
     <LibraryClasses>
-      ## TODO
-      RealTimeClockLib|EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf
+      RealTimeClockLib|Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
   }
   MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
   MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
@@ -627,6 +626,11 @@ [Components.common]
 
   Platform/Socionext/DeveloperBox/OsInstallerMenuDxe/OsInstallerMenuDxe.inf
 
+  #
+  # I2C
+  #
+  Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf
+
 !if $(DO_X86EMU) == TRUE
   #
   # x86 emulator
diff --git a/Platform/Socionext/DeveloperBox/DeveloperBox.fdf b/Platform/Socionext/DeveloperBox/DeveloperBox.fdf
index 19dbcf17c1e1..368bf801e036 100644
--- a/Platform/Socionext/DeveloperBox/DeveloperBox.fdf
+++ b/Platform/Socionext/DeveloperBox/DeveloperBox.fdf
@@ -236,6 +236,11 @@ [FV.FvMain]
 
   INF Platform/Socionext/DeveloperBox/OsInstallerMenuDxe/OsInstallerMenuDxe.inf
 
+  #
+  # I2C
+  #
+  INF Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf
+
 !if $(DO_X86EMU) == TRUE
   #
   # x86 emulator
diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c
index 1d300b15e25b..b39cbc5f5291 100644
--- a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c
+++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c
@@ -62,27 +62,61 @@ STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mNetsecDesc[] = {
   }
 };
 
+STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mI2c0Desc[] = {
+  {
+    ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
+    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,   // Len
+    ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
+    0,                                                // GenFlag
+    0,                                                // SpecificFlag
+    32,                                               // AddrSpaceGranularity
+    SYNQUACER_I2C0_BASE,                              // AddrRangeMin
+    SYNQUACER_I2C0_BASE + SYNQUACER_I2C0_SIZE - 1,    // AddrRangeMax
+    0,                                                // AddrTranslationOffset
+    SYNQUACER_I2C0_SIZE,                              // AddrLen
+  }, {
+    ACPI_END_TAG_DESCRIPTOR                           // Desc
+  }
+};
+
+STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mI2c1Desc[] = {
+  {
+    ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
+    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,   // Len
+    ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
+    0,                                                // GenFlag
+    0,                                                // SpecificFlag
+    32,                                               // AddrSpaceGranularity
+    SYNQUACER_I2C1_BASE,                              // AddrRangeMin
+    SYNQUACER_I2C1_BASE + SYNQUACER_I2C1_SIZE - 1,    // AddrRangeMax
+    0,                                                // AddrTranslationOffset
+    SYNQUACER_I2C1_SIZE,                              // AddrLen
+  }, {
+    ACPI_END_TAG_DESCRIPTOR                           // Desc
+  }
+};
+
 STATIC
 EFI_STATUS
-RegisterNetsec (
-  VOID
+RegisterDevice (
+  IN  EFI_GUID                            *TypeGuid,
+  IN  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc,
+  OUT EFI_HANDLE                          *Handle
   )
 {
   NON_DISCOVERABLE_DEVICE             *Device;
   EFI_STATUS                          Status;
-  EFI_HANDLE                          Handle;
 
   Device = (NON_DISCOVERABLE_DEVICE *)AllocateZeroPool (sizeof (*Device));
   if (Device == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
 
-  Device->Type = &gNetsecNonDiscoverableDeviceGuid;
+  Device->Type = TypeGuid;
   Device->DmaType = NonDiscoverableDeviceDmaTypeNonCoherent;
-  Device->Resources = mNetsecDesc;
+  Device->Resources = Desc;
 
-  Handle = NULL;
-  Status = gBS->InstallMultipleProtocolInterfaces (&Handle,
+  Status = gBS->InstallMultipleProtocolInterfaces (Handle,
                   &gEdkiiNonDiscoverableDeviceProtocolGuid, Device,
                   NULL);
   if (EFI_ERROR (Status)) {
@@ -106,6 +140,7 @@ PlatformDxeEntryPoint (
   EFI_STATUS                      Status;
   VOID                            *Dtb;
   UINTN                           DtbSize;
+  EFI_HANDLE                      Handle;
 
   Dtb = NULL;
   Status = DtPlatformLoadDtb (&Dtb, &DtbSize);
@@ -118,5 +153,30 @@ PlatformDxeEntryPoint (
       Status));
   }
 
-  return RegisterNetsec ();
+  Handle = NULL;
+  Status = RegisterDevice (&gNetsecNonDiscoverableDeviceGuid, mNetsecDesc,
+             &Handle);
+  ASSERT_EFI_ERROR (Status);
+
+  Handle = NULL;
+  Status = RegisterDevice (&gSynQuacerNonDiscoverableRuntimeI2cMasterGuid,
+             mI2c0Desc, &Handle);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Install the PCF8563 I2C Master protocol on this handle so the RTC driver
+  // can identify it as the I2C master it can invoke directly, rather than
+  // through the I2C driver stack (which cannot be used at runtime)
+  //
+  Status = gBS->InstallProtocolInterface (&Handle,
+                  &gPcf8563RealTimeClockLibI2cMasterProtolGuid,
+                  EFI_NATIVE_INTERFACE, NULL);
+  ASSERT_EFI_ERROR (Status);
+
+  Handle = NULL;
+  Status = RegisterDevice (&gSynQuacerNonDiscoverableI2cMasterGuid, mI2c1Desc,
+             &Handle);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
 }
diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf
index 25e6248f1c61..478e0c7d33e9 100644
--- a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf
+++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf
@@ -29,6 +29,7 @@ [Packages]
   EmbeddedPkg/EmbeddedPkg.dec
   MdeModulePkg/MdeModulePkg.dec
   MdePkg/MdePkg.dec
+  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
   Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.dec
   Silicon/Socionext/SynQuacer/SynQuacer.dec
 
@@ -43,9 +44,12 @@ [LibraryClasses]
 [Guids]
   gFdtTableGuid
   gNetsecNonDiscoverableDeviceGuid
+  gSynQuacerNonDiscoverableI2cMasterGuid
+  gSynQuacerNonDiscoverableRuntimeI2cMasterGuid
 
 [Protocols]
-  gEdkiiNonDiscoverableDeviceProtocolGuid     ## PRODUCES
+  gEdkiiNonDiscoverableDeviceProtocolGuid         ## PRODUCES
+  gPcf8563RealTimeClockLibI2cMasterProtolGuid     ## PRODUCES
 
 [FixedPcd]
   gSynQuacerTokenSpaceGuid.PcdNetsecEepromBase
diff --git a/Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h b/Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h
index 1ccd3122cdda..49795f97602c 100644
--- a/Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h
+++ b/Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h
@@ -42,6 +42,14 @@
 #define SYNQUACER_GPIO_BASE             0x51000000
 #define SYNQUACER_GPIO_SIZE             SIZE_4KB
 
+// I2C0 block
+#define SYNQUACER_I2C0_BASE             0x51200000
+#define SYNQUACER_I2C0_SIZE             SIZE_4KB
+
+// I2C1 block
+#define SYNQUACER_I2C1_BASE             0x51210000
+#define SYNQUACER_I2C1_SIZE             SIZE_4KB
+
 // eMMC(SDH30)
 #define SYNQUACER_EMMC_BASE             0x52300000
 #define SYNQUACER_EMMC_BASE_SZ          SIZE_4KB
diff --git a/Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c b/Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c
index be9e28d2ff49..c8c940f27917 100644
--- a/Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c
+++ b/Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c
@@ -82,6 +82,10 @@ STATIC CONST ARM_MEMORY_REGION_DESCRIPTOR mVirtualMemoryTable[] = {
   ARM_DEVICE_REGION (FixedPcdGet32 (PcdNetsecEepromBase),
                      SYNQUACER_EEPROM_BASE_SZ),
 
+  // SynQuacer I2C
+  ARM_DEVICE_REGION (SYNQUACER_I2C0_BASE, SYNQUACER_I2C0_SIZE),
+  ARM_DEVICE_REGION (SYNQUACER_I2C1_BASE, SYNQUACER_I2C1_SIZE),
+
   // SynQuacer NETSEC
   ARM_DEVICE_REGION (SYNQUACER_NETSEC_BASE, SYNQUACER_NETSEC_BASE_SZ),
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP Ard Biesheuvel
@ 2017-11-06 11:09   ` Udit Kumar
  2017-11-06 11:11     ` Ard Biesheuvel
  2017-11-08 16:43   ` Leif Lindholm
  2017-11-08 16:47   ` Leif Lindholm
  2 siblings, 1 reply; 13+ messages in thread
From: Udit Kumar @ 2017-11-06 11:09 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel@lists.01.org, leif.lindholm@linaro.org,
	daniel.thompson@linaro.org

Thanks Ard. 
This will allow to use PCF8563 on any platform not limiting to targeted platform. 
Few comments are inline.

Regards
Udit 

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ard
> Biesheuvel
> Sent: Friday, November 03, 2017 3:47 PM
> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org;
> daniel.thompson@linaro.org
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Subject: [edk2] [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support
> library for PCF8563 I2C IP
> 
> Add a RealTimeClockLib implementation for the NXP PCF8563 as used on
> the Socionext Developer Box board. Note that the standard I2C protocol
> stack does not support runtime use, so this driver invokes the I2C master
> protocol directly. This requires support from the platform side as well,
> and so this driver will only attach to a I2C master that has the
> gPcf8563RealTimeClockLibI2cMasterProtolGuid protocol installed on its
> handle. It is up to the platform to ensure that the driver producing
> the I2C master protocol in question is runtime capable, and is not
> shared with the I2C protocol stack (i.e., it should not have the I2C
> Bus Configuration Management protocol installed as well).
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c   |
> 385 ++++++++++++++++++++
>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec |
> 29 ++
>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf |
> 52 +++
>  3 files changed, 466 insertions(+)
> 
> diff --git
> a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
> new file mode 100644
> index 000000000000..fea65a225d7f
> --- /dev/null
> +++
> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
> @@ -0,0 +1,385 @@
> +/** @file
> +
> +  Copyright (c) 2017, Linaro, Ltd. 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
> +
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed07
> 25208d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636
> 453010374642660&sdata=vDhroHNG20VCsMtj7%2FggWcWRG8hwt5fbV1Kv4R
> Na98Q%3D&reserved=0
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/RealTimeClockLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiRuntimeLib.h>
> +#include <Protocol/I2cMaster.h>
> +
> +#define SLAVE_ADDRESS             (FixedPcdGet8 (PcdI2cSlaveAddress))
> +#define PCF8563_DATA_REG_OFFSET   0x2
> +
> +#define PCF8563_SECONDS_MASK      0x7f
> +#define PCF8563_MINUTES_MASK      0x7f
> +#define PCF8563_HOURS_MASK        0x3f
> +#define PCF8563_DAYS_MASK         0x3f
> +#define PCF8563_WEEKDAYS_MASK     0x07
> +#define PCF8563_MONTHS_MASK       0x1f
> +#define PCF8563_CENTURY_MASK      0x80
> +
> +#define EPOCH_BASE                2000
> +
> +STATIC EFI_HANDLE                 mI2cMasterHandle;
> +STATIC VOID                       *mDriverEventRegistration;
> +STATIC EFI_I2C_MASTER_PROTOCOL    *mI2cMaster;
> +STATIC EFI_EVENT                  mRtcVirtualAddrChangeEvent;
> +
> +typedef struct {
> +  UINTN                           OperationCount;
> +  EFI_I2C_OPERATION               SetAddressOp;
> +  EFI_I2C_OPERATION               GetSetDateTimeOp;
> +} RTC_I2C_REQUEST;
> +
> +#pragma pack(1)
> +typedef struct {
> +  UINT8     VL_seconds;
> +  UINT8     Minutes;
> +  UINT8     Hours;
> +  UINT8     Days;
> +  UINT8     Weekdays;
> +  UINT8     Century_months;
> +  UINT8     Years;
> +} RTC_DATETIME;
> +#pragma pack()
> +
> +/**
> +  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.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibGetTime (
> +  OUT EFI_TIME                *Time,
> +  OUT EFI_TIME_CAPABILITIES   *Capabilities
> +  )
> +{
> +  RTC_I2C_REQUEST             Op;
> +  RTC_DATETIME                DateTime;
> +  EFI_STATUS                  Status;
> +  UINT8                       Reg;
> +
> +  if (Time == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (mI2cMaster == NULL) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  Reg = PCF8563_DATA_REG_OFFSET;
> +
> +  Op.OperationCount = 2;
> +
> +  Op.SetAddressOp.Flags = 0;
> +  Op.SetAddressOp.LengthInBytes = 1;
> +  Op.SetAddressOp.Buffer = &Reg;
> +
> +  Op.GetSetDateTimeOp.Flags = I2C_FLAG_READ;
> +  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
> +  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
> +
> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
> +                         (VOID *)&Op, NULL, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  Time->Second  = BcdToDecimal8 (DateTime.VL_seconds &
> PCF8563_SECONDS_MASK);
> +  Time->Minute  = BcdToDecimal8 (DateTime.Minutes &
> PCF8563_MINUTES_MASK);
> +  Time->Hour    = BcdToDecimal8 (DateTime.Hours & PCF8563_HOURS_MASK);
> +  Time->Day     = BcdToDecimal8 (DateTime.Days & PCF8563_DAYS_MASK);
> +  Time->Month   = BcdToDecimal8 (DateTime.Century_months &
> PCF8563_MONTHS_MASK);
> +  Time->Year    = BcdToDecimal8 (DateTime.Years) + EPOCH_BASE;
> +
> +  if (DateTime.Century_months & PCF8563_CENTURY_MASK) {
> +    Time->Year += 100;
> +  }
> +
> +  Time->Daylight  = EFI_TIME_ADJUST_DAYLIGHT;
> +  Time->TimeZone  = 0; /* UTC */

Need to take care of time-zone as well. 

> +
> +  if (Capabilities != NULL) {
> +    Capabilities->Resolution = 1;
> +    Capabilities->Accuracy = 0;
> +    Capabilities->SetsToZero = TRUE;
> +  }
> +  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
> +  )
> +{
> +  RTC_I2C_REQUEST             Op;
> +  RTC_DATETIME                DateTime;
> +  EFI_STATUS                  Status;
> +  UINT8                       Reg;
> +
> +  if (mI2cMaster == NULL) {
> +    return EFI_DEVICE_ERROR;
> +  }

Please see, if check can be added for time validity 

> +
> +  DateTime.VL_seconds     = DecimalToBcd8 (Time->Second);
> +  DateTime.Minutes        = DecimalToBcd8 (Time->Minute);
> +  DateTime.Hours          = DecimalToBcd8 (Time->Hour);
> +  DateTime.Days           = DecimalToBcd8 (Time->Day);
> +  DateTime.Century_months = DecimalToBcd8 (Time->Month);
> +  DateTime.Years          = DecimalToBcd8 (Time->Year % 100);
> +  if (Time->Year >= EPOCH_BASE + 100) {
> +    DateTime.Century_months |= PCF8563_CENTURY_MASK;
> +  }
> +
> +  Reg = PCF8563_DATA_REG_OFFSET;
> +
> +  Op.OperationCount = 2;
> +
> +  Op.SetAddressOp.Flags = 0;
> +  Op.SetAddressOp.LengthInBytes = 1;
> +  Op.SetAddressOp.Buffer = &Reg;
> +
> +  Op.GetSetDateTimeOp.Flags = 0;
> +  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
> +  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
> +
> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
> +                         (VOID *)&Op, NULL, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +  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
> +  )
> +{
> +  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
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +STATIC
> +VOID
> +DriverRegistrationEvent (
> +  IN  EFI_EVENT       Event,
> +  IN  VOID            *Context
> +  )
> +{
> +  EFI_HANDLE                Handle[2];
> +  UINTN                     BufferSize;
> +  EFI_STATUS                Status;
> +  EFI_I2C_MASTER_PROTOCOL   *I2cMaster;
> +  UINTN                     BusFrequency;
> +
> +  //
> +  // Try to connect the newly registered driver to our handle.
> +  //
> +  do {
> +    BufferSize = sizeof (EFI_HANDLE);
> +    Status = gBS->LocateHandle (ByRegisterNotify,
> +                                &gEfiDriverBindingProtocolGuid,
> +                                mDriverEventRegistration,
> +                                &BufferSize,
> +                                Handle);
> +    if (EFI_ERROR (Status)) {
> +      if (Status != EFI_NOT_FOUND) {
> +        DEBUG ((DEBUG_WARN, "%a: gBS->LocateHandle () returned %r\n",
> +          __FUNCTION__, Status));
> +      }
> +      break;
> +    }
> +
> +    //
> +    // Check if we can connect our handle to this driver.
> +    //
> +    Handle[1] = NULL;
> +    Status = gBS->ConnectController (mI2cMasterHandle, Handle, NULL, FALSE);
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +
> +    DEBUG ((DEBUG_INFO, "%a: found I2C master!\n", __FUNCTION__));
> +
> +    gBS->CloseEvent (Event);
> +
> +    Status = gBS->OpenProtocol (mI2cMasterHandle,
> &gEfiI2cMasterProtocolGuid,
> +                    (VOID **)&I2cMaster, gImageHandle, NULL,
> +                    EFI_OPEN_PROTOCOL_EXCLUSIVE);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = I2cMaster->Reset (I2cMaster);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->Reset () failed - %r\n",
> +        __FUNCTION__, Status));
> +      break;
> +    }
> +
> +    BusFrequency = FixedPcdGet16 (PcdI2cBusFrequency);
> +    Status = I2cMaster->SetBusFrequency (I2cMaster, &BusFrequency);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->SetBusFrequency () failed -
> %r\n",
> +        __FUNCTION__, Status));
> +      break;
> +    }
> +
> +    mI2cMaster = I2cMaster;
> +    break;
> +  } while (TRUE);
> +}
> +
> +/**
> +  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
> +  )
> +{
> +  EfiConvertPointer (0x0, (VOID **)&mI2cMaster);
> +}
> +
> +/**
> +  Library entry point
> +
> +  @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;
> +  UINTN               BufferSize;
> +
> +  //
> +  // Find the handle that marks the controller
> +  // that will provide the I2C master protocol.
> +  //
> +  BufferSize = sizeof (EFI_HANDLE);
> +  Status = gBS->LocateHandle (ByProtocol,
> +                  &gPcf8563RealTimeClockLibI2cMasterProtolGuid, NULL,
> +                  &BufferSize, &mI2cMasterHandle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Register a protocol registration notification callback on the driver
> +  // binding protocol so we can attempt to connect our I2C master to it
> +  // as soon as it appears.
> +  //
> +  EfiCreateProtocolNotifyEvent (
> +    &gEfiDriverBindingProtocolGuid,
> +    TPL_CALLBACK,
> +    DriverRegistrationEvent,
> +    NULL,
> +    &mDriverEventRegistration);
> +
> +  //
> +  // Register for the virtual address change event
> +  //
> +  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
> +                  LibRtcVirtualNotifyEvent, NULL,
> +                  &gEfiEventVirtualAddressChangeGuid,
> +                  &mRtcVirtualAddrChangeEvent);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
> new file mode 100644
> index 000000000000..bc8fc60c0602
> --- /dev/null
> +++
> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
> @@ -0,0 +1,29 @@
> +#/** @file
> +#
> +#  Copyright (c) 2017, Linaro, Ltd. 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
> +#
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed07
> 25208d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636
> 453010374642660&sdata=vDhroHNG20VCsMtj7%2FggWcWRG8hwt5fbV1Kv4R
> Na98Q%3D&reserved=0
> +#  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]
> +  DEC_SPECIFICATION              = 0x0001001A
> +  PACKAGE_NAME                   = Pcf8563RealTimeClockLib
> +  PACKAGE_GUID                   = 44d63668-c86b-446a-b303-f3a5176702aa
> +  PACKAGE_VERSION                = 0.1
> +
> +[Guids]
> +  gPcf8563RealTimeClockLibTokenSpaceGuid = { 0xaaf5b169, 0x93a0, 0x4d60, {
> 0xba, 0xe4, 0x06, 0x07, 0x92, 0x8e, 0x63, 0xdd }}
> +
> +[Protocols]
> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid = { 0xa6af18ae, 0x3bd5,
> 0x4af9, { 0xbb, 0x6a, 0xdb, 0x85, 0x07, 0x62, 0x81, 0x38 }}
> +
> +[PcdsFixedAtBuild]
> +
> gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress|0x51|UINT8|0
> x00000001
> +
> gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency|400|UINT16|0
> x00000002
> diff --git
> a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
> new file mode 100644
> index 000000000000..e1e001162144
> --- /dev/null
> +++
> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
> @@ -0,0 +1,52 @@
> +#/** @file
> +#
> +#  Copyright (c) 2017, Linaro, Ltd. 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
> +#
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
> urce.org%2Flicenses%2Fbsd-
> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed07
> 25208d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636
> 453010374642660&sdata=vDhroHNG20VCsMtj7%2FggWcWRG8hwt5fbV1Kv4R
> Na98Q%3D&reserved=0
> +#  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                    = 0x0001001A
> +  BASE_NAME                      = Pcf8563RealTimeClockLib
> +  FILE_GUID                      = 1e3d33f3-a671-4116-bd81-6b435296c1e0
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = RealTimeClockLib
> +
> +[Sources.common]
> +  Pcf8563RealTimeClockLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  IoLib
> +  UefiBootServicesTableLib
> +  UefiLib
> +  UefiRuntimeLib
> +
> +[Guids]
> +  gEfiEventVirtualAddressChangeGuid
> +
> +[Protocols]
> +  gEfiDriverBindingProtocolGuid                   ## CONSUMES
> +  gEfiI2cMasterProtocolGuid                       ## CONSUMES
> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid     ## CONSUMES
> +
> +[FixedPcd]
> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress
> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency
> +
> +[Depex]
> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid
> --
> 2.11.0
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01
> .org%2Fmailman%2Flistinfo%2Fedk2-
> devel&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed072520
> 8d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6364530
> 10374642660&sdata=vr4qAgDuDX0M7MGeuS%2FKAY%2B%2FqhVmz0%2FMrEx
> K42tQIbM%3D&reserved=0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP
  2017-11-06 11:09   ` Udit Kumar
@ 2017-11-06 11:11     ` Ard Biesheuvel
  2017-11-07  4:37       ` Udit Kumar
  0 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2017-11-06 11:11 UTC (permalink / raw)
  To: Udit Kumar
  Cc: edk2-devel@lists.01.org, leif.lindholm@linaro.org,
	daniel.thompson@linaro.org

On 6 November 2017 at 11:09, Udit Kumar <udit.kumar@nxp.com> wrote:
> Thanks Ard.
> This will allow to use PCF8563 on any platform not limiting to targeted platform.

Yes, that was the intention.

> Few comments are inline.
>

Thanks.

>
>> -----Original Message-----
>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ard
>> Biesheuvel
>> Sent: Friday, November 03, 2017 3:47 PM
>> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org;
>> daniel.thompson@linaro.org
>> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Subject: [edk2] [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support
>> library for PCF8563 I2C IP
>>
>> Add a RealTimeClockLib implementation for the NXP PCF8563 as used on
>> the Socionext Developer Box board. Note that the standard I2C protocol
>> stack does not support runtime use, so this driver invokes the I2C master
>> protocol directly. This requires support from the platform side as well,
>> and so this driver will only attach to a I2C master that has the
>> gPcf8563RealTimeClockLibI2cMasterProtolGuid protocol installed on its
>> handle. It is up to the platform to ensure that the driver producing
>> the I2C master protocol in question is runtime capable, and is not
>> shared with the I2C protocol stack (i.e., it should not have the I2C
>> Bus Configuration Management protocol installed as well).
>>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c   |
>> 385 ++++++++++++++++++++
>>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec |
>> 29 ++
>>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf |
>> 52 +++
>>  3 files changed, 466 insertions(+)
>>
>> diff --git
>> a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
>> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
>> new file mode 100644
>> index 000000000000..fea65a225d7f
>> --- /dev/null
>> +++
>> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
>> @@ -0,0 +1,385 @@
>> +/** @file
>> +
>> +  Copyright (c) 2017, Linaro, Ltd. 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
>> +
>> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
>> urce.org%2Flicenses%2Fbsd-
>> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed07
>> 25208d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636
>> 453010374642660&sdata=vDhroHNG20VCsMtj7%2FggWcWRG8hwt5fbV1Kv4R
>> Na98Q%3D&reserved=0
>> +
>> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
>> BASIS,
>> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
>> EXPRESS OR IMPLIED.
>> +
>> +**/
>> +
>> +#include <PiDxe.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/IoLib.h>
>> +#include <Library/RealTimeClockLib.h>
>> +#include <Library/UefiBootServicesTableLib.h>
>> +#include <Library/UefiLib.h>
>> +#include <Library/UefiRuntimeLib.h>
>> +#include <Protocol/I2cMaster.h>
>> +
>> +#define SLAVE_ADDRESS             (FixedPcdGet8 (PcdI2cSlaveAddress))
>> +#define PCF8563_DATA_REG_OFFSET   0x2
>> +
>> +#define PCF8563_SECONDS_MASK      0x7f
>> +#define PCF8563_MINUTES_MASK      0x7f
>> +#define PCF8563_HOURS_MASK        0x3f
>> +#define PCF8563_DAYS_MASK         0x3f
>> +#define PCF8563_WEEKDAYS_MASK     0x07
>> +#define PCF8563_MONTHS_MASK       0x1f
>> +#define PCF8563_CENTURY_MASK      0x80
>> +
>> +#define EPOCH_BASE                2000
>> +
>> +STATIC EFI_HANDLE                 mI2cMasterHandle;
>> +STATIC VOID                       *mDriverEventRegistration;
>> +STATIC EFI_I2C_MASTER_PROTOCOL    *mI2cMaster;
>> +STATIC EFI_EVENT                  mRtcVirtualAddrChangeEvent;
>> +
>> +typedef struct {
>> +  UINTN                           OperationCount;
>> +  EFI_I2C_OPERATION               SetAddressOp;
>> +  EFI_I2C_OPERATION               GetSetDateTimeOp;
>> +} RTC_I2C_REQUEST;
>> +
>> +#pragma pack(1)
>> +typedef struct {
>> +  UINT8     VL_seconds;
>> +  UINT8     Minutes;
>> +  UINT8     Hours;
>> +  UINT8     Days;
>> +  UINT8     Weekdays;
>> +  UINT8     Century_months;
>> +  UINT8     Years;
>> +} RTC_DATETIME;
>> +#pragma pack()
>> +
>> +/**
>> +  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.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +LibGetTime (
>> +  OUT EFI_TIME                *Time,
>> +  OUT EFI_TIME_CAPABILITIES   *Capabilities
>> +  )
>> +{
>> +  RTC_I2C_REQUEST             Op;
>> +  RTC_DATETIME                DateTime;
>> +  EFI_STATUS                  Status;
>> +  UINT8                       Reg;
>> +
>> +  if (Time == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  if (mI2cMaster == NULL) {
>> +    return EFI_DEVICE_ERROR;
>> +  }
>> +
>> +  Reg = PCF8563_DATA_REG_OFFSET;
>> +
>> +  Op.OperationCount = 2;
>> +
>> +  Op.SetAddressOp.Flags = 0;
>> +  Op.SetAddressOp.LengthInBytes = 1;
>> +  Op.SetAddressOp.Buffer = &Reg;
>> +
>> +  Op.GetSetDateTimeOp.Flags = I2C_FLAG_READ;
>> +  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
>> +  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
>> +
>> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
>> +                         (VOID *)&Op, NULL, NULL);
>> +  if (EFI_ERROR (Status)) {
>> +    return EFI_DEVICE_ERROR;
>> +  }
>> +
>> +  Time->Second  = BcdToDecimal8 (DateTime.VL_seconds &
>> PCF8563_SECONDS_MASK);
>> +  Time->Minute  = BcdToDecimal8 (DateTime.Minutes &
>> PCF8563_MINUTES_MASK);
>> +  Time->Hour    = BcdToDecimal8 (DateTime.Hours & PCF8563_HOURS_MASK);
>> +  Time->Day     = BcdToDecimal8 (DateTime.Days & PCF8563_DAYS_MASK);
>> +  Time->Month   = BcdToDecimal8 (DateTime.Century_months &
>> PCF8563_MONTHS_MASK);
>> +  Time->Year    = BcdToDecimal8 (DateTime.Years) + EPOCH_BASE;
>> +
>> +  if (DateTime.Century_months & PCF8563_CENTURY_MASK) {
>> +    Time->Year += 100;
>> +  }
>> +
>> +  Time->Daylight  = EFI_TIME_ADJUST_DAYLIGHT;
>> +  Time->TimeZone  = 0; /* UTC */
>
> Need to take care of time-zone as well.
>

No, this does not belong in this library, I have posted patches to add
timezone handling and input validation to the core driver.

>> +
>> +  if (Capabilities != NULL) {
>> +    Capabilities->Resolution = 1;
>> +    Capabilities->Accuracy = 0;
>> +    Capabilities->SetsToZero = TRUE;
>> +  }
>> +  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
>> +  )
>> +{
>> +  RTC_I2C_REQUEST             Op;
>> +  RTC_DATETIME                DateTime;
>> +  EFI_STATUS                  Status;
>> +  UINT8                       Reg;
>> +
>> +  if (mI2cMaster == NULL) {
>> +    return EFI_DEVICE_ERROR;
>> +  }
>
> Please see, if check can be added for time validity
>

Same here.

>> +
>> +  DateTime.VL_seconds     = DecimalToBcd8 (Time->Second);
>> +  DateTime.Minutes        = DecimalToBcd8 (Time->Minute);
>> +  DateTime.Hours          = DecimalToBcd8 (Time->Hour);
>> +  DateTime.Days           = DecimalToBcd8 (Time->Day);
>> +  DateTime.Century_months = DecimalToBcd8 (Time->Month);
>> +  DateTime.Years          = DecimalToBcd8 (Time->Year % 100);
>> +  if (Time->Year >= EPOCH_BASE + 100) {
>> +    DateTime.Century_months |= PCF8563_CENTURY_MASK;
>> +  }
>> +
>> +  Reg = PCF8563_DATA_REG_OFFSET;
>> +
>> +  Op.OperationCount = 2;
>> +
>> +  Op.SetAddressOp.Flags = 0;
>> +  Op.SetAddressOp.LengthInBytes = 1;
>> +  Op.SetAddressOp.Buffer = &Reg;
>> +
>> +  Op.GetSetDateTimeOp.Flags = 0;
>> +  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
>> +  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
>> +
>> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
>> +                         (VOID *)&Op, NULL, NULL);
>> +  if (EFI_ERROR (Status)) {
>> +    return EFI_DEVICE_ERROR;
>> +  }
>> +  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
>> +  )
>> +{
>> +  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
>> +  )
>> +{
>> +  return EFI_UNSUPPORTED;
>> +}
>> +
>> +STATIC
>> +VOID
>> +DriverRegistrationEvent (
>> +  IN  EFI_EVENT       Event,
>> +  IN  VOID            *Context
>> +  )
>> +{
>> +  EFI_HANDLE                Handle[2];
>> +  UINTN                     BufferSize;
>> +  EFI_STATUS                Status;
>> +  EFI_I2C_MASTER_PROTOCOL   *I2cMaster;
>> +  UINTN                     BusFrequency;
>> +
>> +  //
>> +  // Try to connect the newly registered driver to our handle.
>> +  //
>> +  do {
>> +    BufferSize = sizeof (EFI_HANDLE);
>> +    Status = gBS->LocateHandle (ByRegisterNotify,
>> +                                &gEfiDriverBindingProtocolGuid,
>> +                                mDriverEventRegistration,
>> +                                &BufferSize,
>> +                                Handle);
>> +    if (EFI_ERROR (Status)) {
>> +      if (Status != EFI_NOT_FOUND) {
>> +        DEBUG ((DEBUG_WARN, "%a: gBS->LocateHandle () returned %r\n",
>> +          __FUNCTION__, Status));
>> +      }
>> +      break;
>> +    }
>> +
>> +    //
>> +    // Check if we can connect our handle to this driver.
>> +    //
>> +    Handle[1] = NULL;
>> +    Status = gBS->ConnectController (mI2cMasterHandle, Handle, NULL, FALSE);
>> +    if (EFI_ERROR (Status)) {
>> +      continue;
>> +    }
>> +
>> +    DEBUG ((DEBUG_INFO, "%a: found I2C master!\n", __FUNCTION__));
>> +
>> +    gBS->CloseEvent (Event);
>> +
>> +    Status = gBS->OpenProtocol (mI2cMasterHandle,
>> &gEfiI2cMasterProtocolGuid,
>> +                    (VOID **)&I2cMaster, gImageHandle, NULL,
>> +                    EFI_OPEN_PROTOCOL_EXCLUSIVE);
>> +    ASSERT_EFI_ERROR (Status);
>> +
>> +    Status = I2cMaster->Reset (I2cMaster);
>> +    if (EFI_ERROR (Status)) {
>> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->Reset () failed - %r\n",
>> +        __FUNCTION__, Status));
>> +      break;
>> +    }
>> +
>> +    BusFrequency = FixedPcdGet16 (PcdI2cBusFrequency);
>> +    Status = I2cMaster->SetBusFrequency (I2cMaster, &BusFrequency);
>> +    if (EFI_ERROR (Status)) {
>> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->SetBusFrequency () failed -
>> %r\n",
>> +        __FUNCTION__, Status));
>> +      break;
>> +    }
>> +
>> +    mI2cMaster = I2cMaster;
>> +    break;
>> +  } while (TRUE);
>> +}
>> +
>> +/**
>> +  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
>> +  )
>> +{
>> +  EfiConvertPointer (0x0, (VOID **)&mI2cMaster);
>> +}
>> +
>> +/**
>> +  Library entry point
>> +
>> +  @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;
>> +  UINTN               BufferSize;
>> +
>> +  //
>> +  // Find the handle that marks the controller
>> +  // that will provide the I2C master protocol.
>> +  //
>> +  BufferSize = sizeof (EFI_HANDLE);
>> +  Status = gBS->LocateHandle (ByProtocol,
>> +                  &gPcf8563RealTimeClockLibI2cMasterProtolGuid, NULL,
>> +                  &BufferSize, &mI2cMasterHandle);
>> +  ASSERT_EFI_ERROR (Status);
>> +
>> +  //
>> +  // Register a protocol registration notification callback on the driver
>> +  // binding protocol so we can attempt to connect our I2C master to it
>> +  // as soon as it appears.
>> +  //
>> +  EfiCreateProtocolNotifyEvent (
>> +    &gEfiDriverBindingProtocolGuid,
>> +    TPL_CALLBACK,
>> +    DriverRegistrationEvent,
>> +    NULL,
>> +    &mDriverEventRegistration);
>> +
>> +  //
>> +  // Register for the virtual address change event
>> +  //
>> +  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
>> +                  LibRtcVirtualNotifyEvent, NULL,
>> +                  &gEfiEventVirtualAddressChangeGuid,
>> +                  &mRtcVirtualAddrChangeEvent);
>> +  ASSERT_EFI_ERROR (Status);
>> +
>> +  return EFI_SUCCESS;
>> +}
>> diff --git
>> a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
>> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
>> new file mode 100644
>> index 000000000000..bc8fc60c0602
>> --- /dev/null
>> +++
>> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
>> @@ -0,0 +1,29 @@
>> +#/** @file
>> +#
>> +#  Copyright (c) 2017, Linaro, Ltd. 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
>> +#
>> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
>> urce.org%2Flicenses%2Fbsd-
>> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed07
>> 25208d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636
>> 453010374642660&sdata=vDhroHNG20VCsMtj7%2FggWcWRG8hwt5fbV1Kv4R
>> Na98Q%3D&reserved=0
>> +#  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]
>> +  DEC_SPECIFICATION              = 0x0001001A
>> +  PACKAGE_NAME                   = Pcf8563RealTimeClockLib
>> +  PACKAGE_GUID                   = 44d63668-c86b-446a-b303-f3a5176702aa
>> +  PACKAGE_VERSION                = 0.1
>> +
>> +[Guids]
>> +  gPcf8563RealTimeClockLibTokenSpaceGuid = { 0xaaf5b169, 0x93a0, 0x4d60, {
>> 0xba, 0xe4, 0x06, 0x07, 0x92, 0x8e, 0x63, 0xdd }}
>> +
>> +[Protocols]
>> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid = { 0xa6af18ae, 0x3bd5,
>> 0x4af9, { 0xbb, 0x6a, 0xdb, 0x85, 0x07, 0x62, 0x81, 0x38 }}
>> +
>> +[PcdsFixedAtBuild]
>> +
>> gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress|0x51|UINT8|0
>> x00000001
>> +
>> gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency|400|UINT16|0
>> x00000002
>> diff --git
>> a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
>> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
>> new file mode 100644
>> index 000000000000..e1e001162144
>> --- /dev/null
>> +++
>> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
>> @@ -0,0 +1,52 @@
>> +#/** @file
>> +#
>> +#  Copyright (c) 2017, Linaro, Ltd. 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
>> +#
>> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopenso
>> urce.org%2Flicenses%2Fbsd-
>> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed07
>> 25208d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636
>> 453010374642660&sdata=vDhroHNG20VCsMtj7%2FggWcWRG8hwt5fbV1Kv4R
>> Na98Q%3D&reserved=0
>> +#  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                    = 0x0001001A
>> +  BASE_NAME                      = Pcf8563RealTimeClockLib
>> +  FILE_GUID                      = 1e3d33f3-a671-4116-bd81-6b435296c1e0
>> +  MODULE_TYPE                    = DXE_DRIVER
>> +  VERSION_STRING                 = 1.0
>> +  LIBRARY_CLASS                  = RealTimeClockLib
>> +
>> +[Sources.common]
>> +  Pcf8563RealTimeClockLib.c
>> +
>> +[Packages]
>> +  MdePkg/MdePkg.dec
>> +  EmbeddedPkg/EmbeddedPkg.dec
>> +  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
>> +
>> +[LibraryClasses]
>> +  BaseMemoryLib
>> +  DebugLib
>> +  IoLib
>> +  UefiBootServicesTableLib
>> +  UefiLib
>> +  UefiRuntimeLib
>> +
>> +[Guids]
>> +  gEfiEventVirtualAddressChangeGuid
>> +
>> +[Protocols]
>> +  gEfiDriverBindingProtocolGuid                   ## CONSUMES
>> +  gEfiI2cMasterProtocolGuid                       ## CONSUMES
>> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid     ## CONSUMES
>> +
>> +[FixedPcd]
>> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress
>> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency
>> +
>> +[Depex]
>> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid
>> --
>> 2.11.0
>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.01
>> .org%2Fmailman%2Flistinfo%2Fedk2-
>> devel&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed072520
>> 8d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6364530
>> 10374642660&sdata=vr4qAgDuDX0M7MGeuS%2FKAY%2B%2FqhVmz0%2FMrEx
>> K42tQIbM%3D&reserved=0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP
  2017-11-06 11:11     ` Ard Biesheuvel
@ 2017-11-07  4:37       ` Udit Kumar
  0 siblings, 0 replies; 13+ messages in thread
From: Udit Kumar @ 2017-11-07  4:37 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: edk2-devel@lists.01.org, leif.lindholm@linaro.org,
	daniel.thompson@linaro.org

Thanks Ard, 
Your another patch set is addressing my concern 

Regards
Udit

> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Monday, November 06, 2017 4:41 PM
> To: Udit Kumar <udit.kumar@nxp.com>
> Cc: edk2-devel@lists.01.org; leif.lindholm@linaro.org;
> daniel.thompson@linaro.org
> Subject: Re: [edk2] [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC
> support library for PCF8563 I2C IP
> 
> On 6 November 2017 at 11:09, Udit Kumar <udit.kumar@nxp.com> wrote:
> > Thanks Ard.
> > This will allow to use PCF8563 on any platform not limiting to targeted
> platform.
> 
> Yes, that was the intention.
> 
> > Few comments are inline.
> >
> 
> Thanks.
> 
> >
> >> -----Original Message-----
> >> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf
> >> Of Ard Biesheuvel
> >> Sent: Friday, November 03, 2017 3:47 PM
> >> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org;
> >> daniel.thompson@linaro.org
> >> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> Subject: [edk2] [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC
> >> support library for PCF8563 I2C IP
> >>
> >> Add a RealTimeClockLib implementation for the NXP PCF8563 as used on
> >> the Socionext Developer Box board. Note that the standard I2C
> >> protocol stack does not support runtime use, so this driver invokes
> >> the I2C master protocol directly. This requires support from the
> >> platform side as well, and so this driver will only attach to a I2C
> >> master that has the gPcf8563RealTimeClockLibI2cMasterProtolGuid
> >> protocol installed on its handle. It is up to the platform to ensure
> >> that the driver producing the I2C master protocol in question is
> >> runtime capable, and is not shared with the I2C protocol stack (i.e.,
> >> it should not have the I2C Bus Configuration Management protocol installed
> as well).
> >>
> >> Contributed-under: TianoCore Contribution Agreement 1.1
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> ---
> >>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
> |
> >> 385 ++++++++++++++++++++
> >>
> >> Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.d
> >> ec |
> >> 29 ++
> >>
> >> Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.i
> >> nf |
> >> 52 +++
> >>  3 files changed, 466 insertions(+)
> >>
> >> diff --git
> >> a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib
> >> .c
> >> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib
> >> .c
> >> new file mode 100644
> >> index 000000000000..fea65a225d7f
> >> --- /dev/null
> >> +++
> >> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib
> >> .c
> >> @@ -0,0 +1,385 @@
> >> +/** @file
> >> +
> >> +  Copyright (c) 2017, Linaro, Ltd. 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
> >> +
> >> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fope
> >> nso
> >> urce.org%2Flicenses%2Fbsd-
> >>
> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed07
> >>
> 25208d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636
> >>
> 453010374642660&sdata=vDhroHNG20VCsMtj7%2FggWcWRG8hwt5fbV1Kv4R
> >> Na98Q%3D&reserved=0
> >> +
> >> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> >> BASIS,
> >> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> >> EXPRESS OR IMPLIED.
> >> +
> >> +**/
> >> +
> >> +#include <PiDxe.h>
> >> +#include <Library/DebugLib.h>
> >> +#include <Library/IoLib.h>
> >> +#include <Library/RealTimeClockLib.h> #include
> >> +<Library/UefiBootServicesTableLib.h>
> >> +#include <Library/UefiLib.h>
> >> +#include <Library/UefiRuntimeLib.h>
> >> +#include <Protocol/I2cMaster.h>
> >> +
> >> +#define SLAVE_ADDRESS             (FixedPcdGet8 (PcdI2cSlaveAddress))
> >> +#define PCF8563_DATA_REG_OFFSET   0x2
> >> +
> >> +#define PCF8563_SECONDS_MASK      0x7f
> >> +#define PCF8563_MINUTES_MASK      0x7f
> >> +#define PCF8563_HOURS_MASK        0x3f
> >> +#define PCF8563_DAYS_MASK         0x3f
> >> +#define PCF8563_WEEKDAYS_MASK     0x07
> >> +#define PCF8563_MONTHS_MASK       0x1f
> >> +#define PCF8563_CENTURY_MASK      0x80
> >> +
> >> +#define EPOCH_BASE                2000
> >> +
> >> +STATIC EFI_HANDLE                 mI2cMasterHandle;
> >> +STATIC VOID                       *mDriverEventRegistration;
> >> +STATIC EFI_I2C_MASTER_PROTOCOL    *mI2cMaster;
> >> +STATIC EFI_EVENT                  mRtcVirtualAddrChangeEvent;
> >> +
> >> +typedef struct {
> >> +  UINTN                           OperationCount;
> >> +  EFI_I2C_OPERATION               SetAddressOp;
> >> +  EFI_I2C_OPERATION               GetSetDateTimeOp;
> >> +} RTC_I2C_REQUEST;
> >> +
> >> +#pragma pack(1)
> >> +typedef struct {
> >> +  UINT8     VL_seconds;
> >> +  UINT8     Minutes;
> >> +  UINT8     Hours;
> >> +  UINT8     Days;
> >> +  UINT8     Weekdays;
> >> +  UINT8     Century_months;
> >> +  UINT8     Years;
> >> +} RTC_DATETIME;
> >> +#pragma pack()
> >> +
> >> +/**
> >> +  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.
> >> +
> >> +**/
> >> +EFI_STATUS
> >> +EFIAPI
> >> +LibGetTime (
> >> +  OUT EFI_TIME                *Time,
> >> +  OUT EFI_TIME_CAPABILITIES   *Capabilities
> >> +  )
> >> +{
> >> +  RTC_I2C_REQUEST             Op;
> >> +  RTC_DATETIME                DateTime;
> >> +  EFI_STATUS                  Status;
> >> +  UINT8                       Reg;
> >> +
> >> +  if (Time == NULL) {
> >> +    return EFI_INVALID_PARAMETER;
> >> +  }
> >> +
> >> +  if (mI2cMaster == NULL) {
> >> +    return EFI_DEVICE_ERROR;
> >> +  }
> >> +
> >> +  Reg = PCF8563_DATA_REG_OFFSET;
> >> +
> >> +  Op.OperationCount = 2;
> >> +
> >> +  Op.SetAddressOp.Flags = 0;
> >> +  Op.SetAddressOp.LengthInBytes = 1;  Op.SetAddressOp.Buffer = &Reg;
> >> +
> >> +  Op.GetSetDateTimeOp.Flags = I2C_FLAG_READ;
> >> + Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
> >> + Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
> >> +
> >> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
> >> +                         (VOID *)&Op, NULL, NULL);  if (EFI_ERROR
> >> + (Status)) {
> >> +    return EFI_DEVICE_ERROR;
> >> +  }
> >> +
> >> +  Time->Second  = BcdToDecimal8 (DateTime.VL_seconds &
> >> PCF8563_SECONDS_MASK);
> >> +  Time->Minute  = BcdToDecimal8 (DateTime.Minutes &
> >> PCF8563_MINUTES_MASK);
> >> +  Time->Hour    = BcdToDecimal8 (DateTime.Hours &
> PCF8563_HOURS_MASK);
> >> +  Time->Day     = BcdToDecimal8 (DateTime.Days & PCF8563_DAYS_MASK);
> >> +  Time->Month   = BcdToDecimal8 (DateTime.Century_months &
> >> PCF8563_MONTHS_MASK);
> >> +  Time->Year    = BcdToDecimal8 (DateTime.Years) + EPOCH_BASE;
> >> +
> >> +  if (DateTime.Century_months & PCF8563_CENTURY_MASK) {
> >> +    Time->Year += 100;
> >> +  }
> >> +
> >> +  Time->Daylight  = EFI_TIME_ADJUST_DAYLIGHT;  Time->TimeZone  = 0;
> >> + /* UTC */
> >
> > Need to take care of time-zone as well.
> >
> 
> No, this does not belong in this library, I have posted patches to add timezone
> handling and input validation to the core driver.
> 
> >> +
> >> +  if (Capabilities != NULL) {
> >> +    Capabilities->Resolution = 1;
> >> +    Capabilities->Accuracy = 0;
> >> +    Capabilities->SetsToZero = TRUE;
> >> +  }
> >> +  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
> >> +  )
> >> +{
> >> +  RTC_I2C_REQUEST             Op;
> >> +  RTC_DATETIME                DateTime;
> >> +  EFI_STATUS                  Status;
> >> +  UINT8                       Reg;
> >> +
> >> +  if (mI2cMaster == NULL) {
> >> +    return EFI_DEVICE_ERROR;
> >> +  }
> >
> > Please see, if check can be added for time validity
> >
> 
> Same here.
> 
> >> +
> >> +  DateTime.VL_seconds     = DecimalToBcd8 (Time->Second);
> >> +  DateTime.Minutes        = DecimalToBcd8 (Time->Minute);
> >> +  DateTime.Hours          = DecimalToBcd8 (Time->Hour);
> >> +  DateTime.Days           = DecimalToBcd8 (Time->Day);
> >> +  DateTime.Century_months = DecimalToBcd8 (Time->Month);
> >> +  DateTime.Years          = DecimalToBcd8 (Time->Year % 100);
> >> +  if (Time->Year >= EPOCH_BASE + 100) {
> >> +    DateTime.Century_months |= PCF8563_CENTURY_MASK;  }
> >> +
> >> +  Reg = PCF8563_DATA_REG_OFFSET;
> >> +
> >> +  Op.OperationCount = 2;
> >> +
> >> +  Op.SetAddressOp.Flags = 0;
> >> +  Op.SetAddressOp.LengthInBytes = 1;  Op.SetAddressOp.Buffer = &Reg;
> >> +
> >> +  Op.GetSetDateTimeOp.Flags = 0;
> >> +  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
> >> + Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
> >> +
> >> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
> >> +                         (VOID *)&Op, NULL, NULL);
> >> +  if (EFI_ERROR (Status)) {
> >> +    return EFI_DEVICE_ERROR;
> >> +  }
> >> +  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
> >> +  )
> >> +{
> >> +  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
> >> +  )
> >> +{
> >> +  return EFI_UNSUPPORTED;
> >> +}
> >> +
> >> +STATIC
> >> +VOID
> >> +DriverRegistrationEvent (
> >> +  IN  EFI_EVENT       Event,
> >> +  IN  VOID            *Context
> >> +  )
> >> +{
> >> +  EFI_HANDLE                Handle[2];
> >> +  UINTN                     BufferSize;
> >> +  EFI_STATUS                Status;
> >> +  EFI_I2C_MASTER_PROTOCOL   *I2cMaster;
> >> +  UINTN                     BusFrequency;
> >> +
> >> +  //
> >> +  // Try to connect the newly registered driver to our handle.
> >> +  //
> >> +  do {
> >> +    BufferSize = sizeof (EFI_HANDLE);
> >> +    Status = gBS->LocateHandle (ByRegisterNotify,
> >> +                                &gEfiDriverBindingProtocolGuid,
> >> +                                mDriverEventRegistration,
> >> +                                &BufferSize,
> >> +                                Handle);
> >> +    if (EFI_ERROR (Status)) {
> >> +      if (Status != EFI_NOT_FOUND) {
> >> +        DEBUG ((DEBUG_WARN, "%a: gBS->LocateHandle () returned %r\n",
> >> +          __FUNCTION__, Status));
> >> +      }
> >> +      break;
> >> +    }
> >> +
> >> +    //
> >> +    // Check if we can connect our handle to this driver.
> >> +    //
> >> +    Handle[1] = NULL;
> >> +    Status = gBS->ConnectController (mI2cMasterHandle, Handle, NULL,
> FALSE);
> >> +    if (EFI_ERROR (Status)) {
> >> +      continue;
> >> +    }
> >> +
> >> +    DEBUG ((DEBUG_INFO, "%a: found I2C master!\n", __FUNCTION__));
> >> +
> >> +    gBS->CloseEvent (Event);
> >> +
> >> +    Status = gBS->OpenProtocol (mI2cMasterHandle,
> >> &gEfiI2cMasterProtocolGuid,
> >> +                    (VOID **)&I2cMaster, gImageHandle, NULL,
> >> +                    EFI_OPEN_PROTOCOL_EXCLUSIVE);
> >> +    ASSERT_EFI_ERROR (Status);
> >> +
> >> +    Status = I2cMaster->Reset (I2cMaster);
> >> +    if (EFI_ERROR (Status)) {
> >> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->Reset () failed - %r\n",
> >> +        __FUNCTION__, Status));
> >> +      break;
> >> +    }
> >> +
> >> +    BusFrequency = FixedPcdGet16 (PcdI2cBusFrequency);
> >> +    Status = I2cMaster->SetBusFrequency (I2cMaster, &BusFrequency);
> >> +    if (EFI_ERROR (Status)) {
> >> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->SetBusFrequency () failed
> >> + -
> >> %r\n",
> >> +        __FUNCTION__, Status));
> >> +      break;
> >> +    }
> >> +
> >> +    mI2cMaster = I2cMaster;
> >> +    break;
> >> +  } while (TRUE);
> >> +}
> >> +
> >> +/**
> >> +  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
> >> +  )
> >> +{
> >> +  EfiConvertPointer (0x0, (VOID **)&mI2cMaster); }
> >> +
> >> +/**
> >> +  Library entry point
> >> +
> >> +  @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;
> >> +  UINTN               BufferSize;
> >> +
> >> +  //
> >> +  // Find the handle that marks the controller  // that will provide
> >> + the I2C master protocol.
> >> +  //
> >> +  BufferSize = sizeof (EFI_HANDLE);
> >> +  Status = gBS->LocateHandle (ByProtocol,
> >> +                  &gPcf8563RealTimeClockLibI2cMasterProtolGuid, NULL,
> >> +                  &BufferSize, &mI2cMasterHandle);  ASSERT_EFI_ERROR
> >> + (Status);
> >> +
> >> +  //
> >> +  // Register a protocol registration notification callback on the
> >> + driver  // binding protocol so we can attempt to connect our I2C
> >> + master to it  // as soon as it appears.
> >> +  //
> >> +  EfiCreateProtocolNotifyEvent (
> >> +    &gEfiDriverBindingProtocolGuid,
> >> +    TPL_CALLBACK,
> >> +    DriverRegistrationEvent,
> >> +    NULL,
> >> +    &mDriverEventRegistration);
> >> +
> >> +  //
> >> +  // Register for the virtual address change event  //  Status =
> >> + gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
> >> +                  LibRtcVirtualNotifyEvent, NULL,
> >> +                  &gEfiEventVirtualAddressChangeGuid,
> >> +                  &mRtcVirtualAddrChangeEvent);  ASSERT_EFI_ERROR
> >> + (Status);
> >> +
> >> +  return EFI_SUCCESS;
> >> +}
> >> diff --git
> >> a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib
> >> .dec
> >> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib
> >> .dec
> >> new file mode 100644
> >> index 000000000000..bc8fc60c0602
> >> --- /dev/null
> >> +++
> >> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib
> >> .dec
> >> @@ -0,0 +1,29 @@
> >> +#/** @file
> >> +#
> >> +#  Copyright (c) 2017, Linaro, Ltd. 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
> >> +#
> >> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fope
> >> nso
> >> urce.org%2Flicenses%2Fbsd-
> >>
> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed07
> >>
> 25208d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636
> >>
> 453010374642660&sdata=vDhroHNG20VCsMtj7%2FggWcWRG8hwt5fbV1Kv4R
> >> Na98Q%3D&reserved=0
> >> +#  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]
> >> +  DEC_SPECIFICATION              = 0x0001001A
> >> +  PACKAGE_NAME                   = Pcf8563RealTimeClockLib
> >> +  PACKAGE_GUID                   = 44d63668-c86b-446a-b303-f3a5176702aa
> >> +  PACKAGE_VERSION                = 0.1
> >> +
> >> +[Guids]
> >> +  gPcf8563RealTimeClockLibTokenSpaceGuid = { 0xaaf5b169, 0x93a0,
> >> +0x4d60, {
> >> 0xba, 0xe4, 0x06, 0x07, 0x92, 0x8e, 0x63, 0xdd }}
> >> +
> >> +[Protocols]
> >> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid = { 0xa6af18ae,
> >> +0x3bd5,
> >> 0x4af9, { 0xbb, 0x6a, 0xdb, 0x85, 0x07, 0x62, 0x81, 0x38 }}
> >> +
> >> +[PcdsFixedAtBuild]
> >> +
> >>
> gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress|0x51|UINT8|
> >> 0
> >> x00000001
> >> +
> >>
> gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency|400|UINT16|
> >> 0
> >> x00000002
> >> diff --git
> >> a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib
> >> .inf
> >> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib
> >> .inf
> >> new file mode 100644
> >> index 000000000000..e1e001162144
> >> --- /dev/null
> >> +++
> >> b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib
> >> .inf
> >> @@ -0,0 +1,52 @@
> >> +#/** @file
> >> +#
> >> +#  Copyright (c) 2017, Linaro, Ltd. 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
> >> +#
> >> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fope
> >> nso
> >> urce.org%2Flicenses%2Fbsd-
> >>
> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed07
> >>
> 25208d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636
> >>
> 453010374642660&sdata=vDhroHNG20VCsMtj7%2FggWcWRG8hwt5fbV1Kv4R
> >> Na98Q%3D&reserved=0
> >> +#  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                    = 0x0001001A
> >> +  BASE_NAME                      = Pcf8563RealTimeClockLib
> >> +  FILE_GUID                      = 1e3d33f3-a671-4116-bd81-6b435296c1e0
> >> +  MODULE_TYPE                    = DXE_DRIVER
> >> +  VERSION_STRING                 = 1.0
> >> +  LIBRARY_CLASS                  = RealTimeClockLib
> >> +
> >> +[Sources.common]
> >> +  Pcf8563RealTimeClockLib.c
> >> +
> >> +[Packages]
> >> +  MdePkg/MdePkg.dec
> >> +  EmbeddedPkg/EmbeddedPkg.dec
> >> +
> >> +Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.
> >> +dec
> >> +
> >> +[LibraryClasses]
> >> +  BaseMemoryLib
> >> +  DebugLib
> >> +  IoLib
> >> +  UefiBootServicesTableLib
> >> +  UefiLib
> >> +  UefiRuntimeLib
> >> +
> >> +[Guids]
> >> +  gEfiEventVirtualAddressChangeGuid
> >> +
> >> +[Protocols]
> >> +  gEfiDriverBindingProtocolGuid                   ## CONSUMES
> >> +  gEfiI2cMasterProtocolGuid                       ## CONSUMES
> >> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid     ## CONSUMES
> >> +
> >> +[FixedPcd]
> >> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress
> >> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency
> >> +
> >> +[Depex]
> >> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid
> >> --
> >> 2.11.0
> >>
> >> _______________________________________________
> >> edk2-devel mailing list
> >> edk2-devel@lists.01.org
> >> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fli
> >> sts.01
> >> .org%2Fmailman%2Flistinfo%2Fedk2-
> >>
> devel&data=02%7C01%7Cudit.kumar%40nxp.com%7C6faa68073eef4ed072520
> >>
> 8d522a40d65%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6364530
> >>
> 10374642660&sdata=vr4qAgDuDX0M7MGeuS%2FKAY%2B%2FqhVmz0%2FMrEx
> >> K42tQIbM%3D&reserved=0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP Ard Biesheuvel
  2017-11-06 11:09   ` Udit Kumar
@ 2017-11-08 16:43   ` Leif Lindholm
  2017-11-08 17:44     ` Ard Biesheuvel
  2017-11-08 16:47   ` Leif Lindholm
  2 siblings, 1 reply; 13+ messages in thread
From: Leif Lindholm @ 2017-11-08 16:43 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: edk2-devel, daniel.thompson

On Fri, Nov 03, 2017 at 10:16:52AM +0000, Ard Biesheuvel wrote:
> Add a RealTimeClockLib implementation for the NXP PCF8563 as used on
> the Socionext Developer Box board. Note that the standard I2C protocol
> stack does not support runtime use, so this driver invokes the I2C master
> protocol directly. This requires support from the platform side as well,
> and so this driver will only attach to a I2C master that has the
> gPcf8563RealTimeClockLibI2cMasterProtolGuid protocol installed on its
> handle. It is up to the platform to ensure that the driver producing
> the I2C master protocol in question is runtime capable, and is not
> shared with the I2C protocol stack (i.e., it should not have the I2C
> Bus Configuration Management protocol installed as well).
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c   | 385 ++++++++++++++++++++
>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec |  29 ++
>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf |  52 +++
>  3 files changed, 466 insertions(+)
> 
> diff --git a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
> new file mode 100644
> index 000000000000..fea65a225d7f
> --- /dev/null
> +++ b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
> @@ -0,0 +1,385 @@
> +/** @file
> +
> +  Copyright (c) 2017, Linaro, Ltd. 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.
> +
> +**/
> +
> +#include <PiDxe.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/RealTimeClockLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiRuntimeLib.h>
> +#include <Protocol/I2cMaster.h>
> +
> +#define SLAVE_ADDRESS             (FixedPcdGet8 (PcdI2cSlaveAddress))
> +#define PCF8563_DATA_REG_OFFSET   0x2
> +
> +#define PCF8563_SECONDS_MASK      0x7f
> +#define PCF8563_MINUTES_MASK      0x7f
> +#define PCF8563_HOURS_MASK        0x3f
> +#define PCF8563_DAYS_MASK         0x3f
> +#define PCF8563_WEEKDAYS_MASK     0x07
> +#define PCF8563_MONTHS_MASK       0x1f
> +#define PCF8563_CENTURY_MASK      0x80
> +
> +#define EPOCH_BASE                2000
> +
> +STATIC EFI_HANDLE                 mI2cMasterHandle;
> +STATIC VOID                       *mDriverEventRegistration;
> +STATIC EFI_I2C_MASTER_PROTOCOL    *mI2cMaster;
> +STATIC EFI_EVENT                  mRtcVirtualAddrChangeEvent;
> +
> +typedef struct {
> +  UINTN                           OperationCount;
> +  EFI_I2C_OPERATION               SetAddressOp;
> +  EFI_I2C_OPERATION               GetSetDateTimeOp;
> +} RTC_I2C_REQUEST;
> +
> +#pragma pack(1)
> +typedef struct {
> +  UINT8     VL_seconds;
> +  UINT8     Minutes;
> +  UINT8     Hours;
> +  UINT8     Days;
> +  UINT8     Weekdays;
> +  UINT8     Century_months;
> +  UINT8     Years;
> +} RTC_DATETIME;
> +#pragma pack()
> +
> +/**
> +  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.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibGetTime (
> +  OUT EFI_TIME                *Time,
> +  OUT EFI_TIME_CAPABILITIES   *Capabilities
> +  )
> +{
> +  RTC_I2C_REQUEST             Op;
> +  RTC_DATETIME                DateTime;
> +  EFI_STATUS                  Status;
> +  UINT8                       Reg;
> +
> +  if (Time == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (mI2cMaster == NULL) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  Reg = PCF8563_DATA_REG_OFFSET;
> +
> +  Op.OperationCount = 2;
> +
> +  Op.SetAddressOp.Flags = 0;
> +  Op.SetAddressOp.LengthInBytes = 1;
> +  Op.SetAddressOp.Buffer = &Reg;
> +
> +  Op.GetSetDateTimeOp.Flags = I2C_FLAG_READ;
> +  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
> +  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
> +
> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
> +                         (VOID *)&Op, NULL, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  Time->Second  = BcdToDecimal8 (DateTime.VL_seconds & PCF8563_SECONDS_MASK);
> +  Time->Minute  = BcdToDecimal8 (DateTime.Minutes & PCF8563_MINUTES_MASK);
> +  Time->Hour    = BcdToDecimal8 (DateTime.Hours & PCF8563_HOURS_MASK);
> +  Time->Day     = BcdToDecimal8 (DateTime.Days & PCF8563_DAYS_MASK);
> +  Time->Month   = BcdToDecimal8 (DateTime.Century_months & PCF8563_MONTHS_MASK);
> +  Time->Year    = BcdToDecimal8 (DateTime.Years) + EPOCH_BASE;
> +
> +  if (DateTime.Century_months & PCF8563_CENTURY_MASK) {
> +    Time->Year += 100;

Guess we'd better retire all these platforms before the year 2100
then... (Or, given EPOCH_BASE, is it 2070? (Or given EPOCH_BASE being
set to 2000, is it 2200?))

Could you add a small comment next to the EPOCH_BASE definition
explaining the constrainst?

> +  }
> +
> +  Time->Daylight  = EFI_TIME_ADJUST_DAYLIGHT;
> +  Time->TimeZone  = 0; /* UTC */
> +
> +  if (Capabilities != NULL) {
> +    Capabilities->Resolution = 1;
> +    Capabilities->Accuracy = 0;
> +    Capabilities->SetsToZero = TRUE;
> +  }
> +  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
> +  )
> +{
> +  RTC_I2C_REQUEST             Op;
> +  RTC_DATETIME                DateTime;
> +  EFI_STATUS                  Status;
> +  UINT8                       Reg;
> +
> +  if (mI2cMaster == NULL) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  DateTime.VL_seconds     = DecimalToBcd8 (Time->Second);
> +  DateTime.Minutes        = DecimalToBcd8 (Time->Minute);
> +  DateTime.Hours          = DecimalToBcd8 (Time->Hour);
> +  DateTime.Days           = DecimalToBcd8 (Time->Day);
> +  DateTime.Century_months = DecimalToBcd8 (Time->Month);
> +  DateTime.Years          = DecimalToBcd8 (Time->Year % 100);
> +  if (Time->Year >= EPOCH_BASE + 100) {
> +    DateTime.Century_months |= PCF8563_CENTURY_MASK;

Are you going to slap me if I ask for this to return error if
Time->Year >= EPOCH_BASE + 200?

> +  }
> +
> +  Reg = PCF8563_DATA_REG_OFFSET;
> +
> +  Op.OperationCount = 2;
> +
> +  Op.SetAddressOp.Flags = 0;
> +  Op.SetAddressOp.LengthInBytes = 1;
> +  Op.SetAddressOp.Buffer = &Reg;
> +
> +  Op.GetSetDateTimeOp.Flags = 0;
> +  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
> +  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
> +
> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
> +                         (VOID *)&Op, NULL, NULL);
> +  if (EFI_ERROR (Status)) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +  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
> +  )
> +{
> +  return EFI_UNSUPPORTED;

For now, unsupported by current platforms, or unsupportable by this
RTC device?

> +}
> +
> +
> +/**
> +  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
> +  )
> +{
> +  return EFI_UNSUPPORTED;

Same question.

> +}
> +
> +STATIC
> +VOID
> +DriverRegistrationEvent (
> +  IN  EFI_EVENT       Event,
> +  IN  VOID            *Context
> +  )
> +{
> +  EFI_HANDLE                Handle[2];
> +  UINTN                     BufferSize;
> +  EFI_STATUS                Status;
> +  EFI_I2C_MASTER_PROTOCOL   *I2cMaster;
> +  UINTN                     BusFrequency;
> +
> +  //
> +  // Try to connect the newly registered driver to our handle.
> +  //
> +  do {
> +    BufferSize = sizeof (EFI_HANDLE);
> +    Status = gBS->LocateHandle (ByRegisterNotify,
> +                                &gEfiDriverBindingProtocolGuid,
> +                                mDriverEventRegistration,
> +                                &BufferSize,
> +                                Handle);
> +    if (EFI_ERROR (Status)) {
> +      if (Status != EFI_NOT_FOUND) {
> +        DEBUG ((DEBUG_WARN, "%a: gBS->LocateHandle () returned %r\n",
> +          __FUNCTION__, Status));
> +      }
> +      break;
> +    }
> +
> +    //
> +    // Check if we can connect our handle to this driver.
> +    //
> +    Handle[1] = NULL;
> +    Status = gBS->ConnectController (mI2cMasterHandle, Handle, NULL, FALSE);
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +
> +    DEBUG ((DEBUG_INFO, "%a: found I2C master!\n", __FUNCTION__));
> +
> +    gBS->CloseEvent (Event);
> +
> +    Status = gBS->OpenProtocol (mI2cMasterHandle, &gEfiI2cMasterProtocolGuid,
> +                    (VOID **)&I2cMaster, gImageHandle, NULL,
> +                    EFI_OPEN_PROTOCOL_EXCLUSIVE);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = I2cMaster->Reset (I2cMaster);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->Reset () failed - %r\n",
> +        __FUNCTION__, Status));
> +      break;
> +    }
> +
> +    BusFrequency = FixedPcdGet16 (PcdI2cBusFrequency);
> +    Status = I2cMaster->SetBusFrequency (I2cMaster, &BusFrequency);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->SetBusFrequency () failed - %r\n",
> +        __FUNCTION__, Status));
> +      break;
> +    }
> +
> +    mI2cMaster = I2cMaster;
> +    break;
> +  } while (TRUE);
> +}
> +
> +/**
> +  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
> +  )
> +{
> +  EfiConvertPointer (0x0, (VOID **)&mI2cMaster);
> +}
> +
> +/**
> +  Library entry point
> +
> +  @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;
> +  UINTN               BufferSize;
> +
> +  //
> +  // Find the handle that marks the controller
> +  // that will provide the I2C master protocol.
> +  //
> +  BufferSize = sizeof (EFI_HANDLE);
> +  Status = gBS->LocateHandle (ByProtocol,
> +                  &gPcf8563RealTimeClockLibI2cMasterProtolGuid, NULL,
> +                  &BufferSize, &mI2cMasterHandle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Register a protocol registration notification callback on the driver
> +  // binding protocol so we can attempt to connect our I2C master to it
> +  // as soon as it appears.
> +  //
> +  EfiCreateProtocolNotifyEvent (
> +    &gEfiDriverBindingProtocolGuid,
> +    TPL_CALLBACK,
> +    DriverRegistrationEvent,
> +    NULL,
> +    &mDriverEventRegistration);
> +
> +  //
> +  // Register for the virtual address change event
> +  //
> +  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
> +                  LibRtcVirtualNotifyEvent, NULL,
> +                  &gEfiEventVirtualAddressChangeGuid,
> +                  &mRtcVirtualAddrChangeEvent);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
> new file mode 100644
> index 000000000000..bc8fc60c0602
> --- /dev/null
> +++ b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
> @@ -0,0 +1,29 @@
> +#/** @file
> +#
> +#  Copyright (c) 2017, Linaro, Ltd. 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]
> +  DEC_SPECIFICATION              = 0x0001001A
> +  PACKAGE_NAME                   = Pcf8563RealTimeClockLib
> +  PACKAGE_GUID                   = 44d63668-c86b-446a-b303-f3a5176702aa
> +  PACKAGE_VERSION                = 0.1
> +
> +[Guids]
> +  gPcf8563RealTimeClockLibTokenSpaceGuid = { 0xaaf5b169, 0x93a0, 0x4d60, { 0xba, 0xe4, 0x06, 0x07, 0x92, 0x8e, 0x63, 0xdd }}
> +
> +[Protocols]
> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid = { 0xa6af18ae, 0x3bd5, 0x4af9, { 0xbb, 0x6a, 0xdb, 0x85, 0x07, 0x62, 0x81, 0x38 }}
> +
> +[PcdsFixedAtBuild]
> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress|0x51|UINT8|0x00000001
> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency|400|UINT16|0x00000002

Could you add a comment clarifying unit?

/
    Leif

> diff --git a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
> new file mode 100644
> index 000000000000..e1e001162144
> --- /dev/null
> +++ b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
> @@ -0,0 +1,52 @@
> +#/** @file
> +#
> +#  Copyright (c) 2017, Linaro, Ltd. 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                    = 0x0001001A
> +  BASE_NAME                      = Pcf8563RealTimeClockLib
> +  FILE_GUID                      = 1e3d33f3-a671-4116-bd81-6b435296c1e0
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = RealTimeClockLib
> +
> +[Sources.common]
> +  Pcf8563RealTimeClockLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  IoLib
> +  UefiBootServicesTableLib
> +  UefiLib
> +  UefiRuntimeLib
> +
> +[Guids]
> +  gEfiEventVirtualAddressChangeGuid
> +
> +[Protocols]
> +  gEfiDriverBindingProtocolGuid                   ## CONSUMES
> +  gEfiI2cMasterProtocolGuid                       ## CONSUMES
> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid     ## CONSUMES
> +
> +[FixedPcd]
> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress
> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency
> +
> +[Depex]
> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid
> -- 
> 2.11.0
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH edk2-platforms 3/3] Platform/DeveloperBox: wire up RTC support
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 3/3] Platform/DeveloperBox: wire up RTC support Ard Biesheuvel
@ 2017-11-08 16:47   ` Leif Lindholm
  0 siblings, 0 replies; 13+ messages in thread
From: Leif Lindholm @ 2017-11-08 16:47 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: edk2-devel, daniel.thompson

On Fri, Nov 03, 2017 at 10:16:54AM +0000, Ard Biesheuvel wrote:
> Add the drivers, library resolutions and PCD settings to enable RTC
> support on DeveloperBox. Also, update PlatformDxe to register the
> non-discoverable device handles for both I2C controllers.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>

> ---
>  Platform/Socionext/DeveloperBox/DeveloperBox.dsc                                          |  8 ++-
>  Platform/Socionext/DeveloperBox/DeveloperBox.fdf                                          |  5 ++
>  Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c                             | 76 +++++++++++++++++---
>  Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf                           |  6 +-
>  Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h                                  |  8 +++
>  Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c |  4 ++
>  6 files changed, 96 insertions(+), 11 deletions(-)
> 
> diff --git a/Platform/Socionext/DeveloperBox/DeveloperBox.dsc b/Platform/Socionext/DeveloperBox/DeveloperBox.dsc
> index b558b1f805b4..91898faa6ecc 100644
> --- a/Platform/Socionext/DeveloperBox/DeveloperBox.dsc
> +++ b/Platform/Socionext/DeveloperBox/DeveloperBox.dsc
> @@ -446,8 +446,7 @@ [Components.common]
>    MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
>    EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf {
>      <LibraryClasses>
> -      ## TODO
> -      RealTimeClockLib|EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf
> +      RealTimeClockLib|Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
>    }
>    MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
>    MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
> @@ -627,6 +626,11 @@ [Components.common]
>  
>    Platform/Socionext/DeveloperBox/OsInstallerMenuDxe/OsInstallerMenuDxe.inf
>  
> +  #
> +  # I2C
> +  #
> +  Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf
> +
>  !if $(DO_X86EMU) == TRUE
>    #
>    # x86 emulator
> diff --git a/Platform/Socionext/DeveloperBox/DeveloperBox.fdf b/Platform/Socionext/DeveloperBox/DeveloperBox.fdf
> index 19dbcf17c1e1..368bf801e036 100644
> --- a/Platform/Socionext/DeveloperBox/DeveloperBox.fdf
> +++ b/Platform/Socionext/DeveloperBox/DeveloperBox.fdf
> @@ -236,6 +236,11 @@ [FV.FvMain]
>  
>    INF Platform/Socionext/DeveloperBox/OsInstallerMenuDxe/OsInstallerMenuDxe.inf
>  
> +  #
> +  # I2C
> +  #
> +  INF Silicon/Socionext/SynQuacer/Drivers/SynQuacerI2cDxe/SynQuacerI2cDxe.inf
> +
>  !if $(DO_X86EMU) == TRUE
>    #
>    # x86 emulator
> diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c
> index 1d300b15e25b..b39cbc5f5291 100644
> --- a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c
> +++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c
> @@ -62,27 +62,61 @@ STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mNetsecDesc[] = {
>    }
>  };
>  
> +STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mI2c0Desc[] = {
> +  {
> +    ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
> +    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,   // Len
> +    ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
> +    0,                                                // GenFlag
> +    0,                                                // SpecificFlag
> +    32,                                               // AddrSpaceGranularity
> +    SYNQUACER_I2C0_BASE,                              // AddrRangeMin
> +    SYNQUACER_I2C0_BASE + SYNQUACER_I2C0_SIZE - 1,    // AddrRangeMax
> +    0,                                                // AddrTranslationOffset
> +    SYNQUACER_I2C0_SIZE,                              // AddrLen
> +  }, {
> +    ACPI_END_TAG_DESCRIPTOR                           // Desc
> +  }
> +};
> +
> +STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mI2c1Desc[] = {
> +  {
> +    ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
> +    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,   // Len
> +    ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
> +    0,                                                // GenFlag
> +    0,                                                // SpecificFlag
> +    32,                                               // AddrSpaceGranularity
> +    SYNQUACER_I2C1_BASE,                              // AddrRangeMin
> +    SYNQUACER_I2C1_BASE + SYNQUACER_I2C1_SIZE - 1,    // AddrRangeMax
> +    0,                                                // AddrTranslationOffset
> +    SYNQUACER_I2C1_SIZE,                              // AddrLen
> +  }, {
> +    ACPI_END_TAG_DESCRIPTOR                           // Desc
> +  }
> +};
> +
>  STATIC
>  EFI_STATUS
> -RegisterNetsec (
> -  VOID
> +RegisterDevice (
> +  IN  EFI_GUID                            *TypeGuid,
> +  IN  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc,
> +  OUT EFI_HANDLE                          *Handle
>    )
>  {
>    NON_DISCOVERABLE_DEVICE             *Device;
>    EFI_STATUS                          Status;
> -  EFI_HANDLE                          Handle;
>  
>    Device = (NON_DISCOVERABLE_DEVICE *)AllocateZeroPool (sizeof (*Device));
>    if (Device == NULL) {
>      return EFI_OUT_OF_RESOURCES;
>    }
>  
> -  Device->Type = &gNetsecNonDiscoverableDeviceGuid;
> +  Device->Type = TypeGuid;
>    Device->DmaType = NonDiscoverableDeviceDmaTypeNonCoherent;
> -  Device->Resources = mNetsecDesc;
> +  Device->Resources = Desc;
>  
> -  Handle = NULL;
> -  Status = gBS->InstallMultipleProtocolInterfaces (&Handle,
> +  Status = gBS->InstallMultipleProtocolInterfaces (Handle,
>                    &gEdkiiNonDiscoverableDeviceProtocolGuid, Device,
>                    NULL);
>    if (EFI_ERROR (Status)) {
> @@ -106,6 +140,7 @@ PlatformDxeEntryPoint (
>    EFI_STATUS                      Status;
>    VOID                            *Dtb;
>    UINTN                           DtbSize;
> +  EFI_HANDLE                      Handle;
>  
>    Dtb = NULL;
>    Status = DtPlatformLoadDtb (&Dtb, &DtbSize);
> @@ -118,5 +153,30 @@ PlatformDxeEntryPoint (
>        Status));
>    }
>  
> -  return RegisterNetsec ();
> +  Handle = NULL;
> +  Status = RegisterDevice (&gNetsecNonDiscoverableDeviceGuid, mNetsecDesc,
> +             &Handle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Handle = NULL;
> +  Status = RegisterDevice (&gSynQuacerNonDiscoverableRuntimeI2cMasterGuid,
> +             mI2c0Desc, &Handle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Install the PCF8563 I2C Master protocol on this handle so the RTC driver
> +  // can identify it as the I2C master it can invoke directly, rather than
> +  // through the I2C driver stack (which cannot be used at runtime)
> +  //
> +  Status = gBS->InstallProtocolInterface (&Handle,
> +                  &gPcf8563RealTimeClockLibI2cMasterProtolGuid,
> +                  EFI_NATIVE_INTERFACE, NULL);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Handle = NULL;
> +  Status = RegisterDevice (&gSynQuacerNonDiscoverableI2cMasterGuid, mI2c1Desc,
> +             &Handle);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return EFI_SUCCESS;
>  }
> diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf
> index 25e6248f1c61..478e0c7d33e9 100644
> --- a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf
> +++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf
> @@ -29,6 +29,7 @@ [Packages]
>    EmbeddedPkg/EmbeddedPkg.dec
>    MdeModulePkg/MdeModulePkg.dec
>    MdePkg/MdePkg.dec
> +  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
>    Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.dec
>    Silicon/Socionext/SynQuacer/SynQuacer.dec
>  
> @@ -43,9 +44,12 @@ [LibraryClasses]
>  [Guids]
>    gFdtTableGuid
>    gNetsecNonDiscoverableDeviceGuid
> +  gSynQuacerNonDiscoverableI2cMasterGuid
> +  gSynQuacerNonDiscoverableRuntimeI2cMasterGuid
>  
>  [Protocols]
> -  gEdkiiNonDiscoverableDeviceProtocolGuid     ## PRODUCES
> +  gEdkiiNonDiscoverableDeviceProtocolGuid         ## PRODUCES
> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid     ## PRODUCES
>  
>  [FixedPcd]
>    gSynQuacerTokenSpaceGuid.PcdNetsecEepromBase
> diff --git a/Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h b/Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h
> index 1ccd3122cdda..49795f97602c 100644
> --- a/Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h
> +++ b/Silicon/Socionext/SynQuacer/Include/Platform/MemoryMap.h
> @@ -42,6 +42,14 @@
>  #define SYNQUACER_GPIO_BASE             0x51000000
>  #define SYNQUACER_GPIO_SIZE             SIZE_4KB
>  
> +// I2C0 block
> +#define SYNQUACER_I2C0_BASE             0x51200000
> +#define SYNQUACER_I2C0_SIZE             SIZE_4KB
> +
> +// I2C1 block
> +#define SYNQUACER_I2C1_BASE             0x51210000
> +#define SYNQUACER_I2C1_SIZE             SIZE_4KB
> +
>  // eMMC(SDH30)
>  #define SYNQUACER_EMMC_BASE             0x52300000
>  #define SYNQUACER_EMMC_BASE_SZ          SIZE_4KB
> diff --git a/Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c b/Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c
> index be9e28d2ff49..c8c940f27917 100644
> --- a/Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c
> +++ b/Silicon/Socionext/SynQuacer/Library/SynQuacerMemoryInitPeiLib/SynQuacerMemoryInitPeiLib.c
> @@ -82,6 +82,10 @@ STATIC CONST ARM_MEMORY_REGION_DESCRIPTOR mVirtualMemoryTable[] = {
>    ARM_DEVICE_REGION (FixedPcdGet32 (PcdNetsecEepromBase),
>                       SYNQUACER_EEPROM_BASE_SZ),
>  
> +  // SynQuacer I2C
> +  ARM_DEVICE_REGION (SYNQUACER_I2C0_BASE, SYNQUACER_I2C0_SIZE),
> +  ARM_DEVICE_REGION (SYNQUACER_I2C1_BASE, SYNQUACER_I2C1_SIZE),
> +
>    // SynQuacer NETSEC
>    ARM_DEVICE_REGION (SYNQUACER_NETSEC_BASE, SYNQUACER_NETSEC_BASE_SZ),
>  
> -- 
> 2.11.0
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP
  2017-11-03 10:16 ` [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP Ard Biesheuvel
  2017-11-06 11:09   ` Udit Kumar
  2017-11-08 16:43   ` Leif Lindholm
@ 2017-11-08 16:47   ` Leif Lindholm
  2017-11-08 17:45     ` Ard Biesheuvel
  2 siblings, 1 reply; 13+ messages in thread
From: Leif Lindholm @ 2017-11-08 16:47 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: edk2-devel, daniel.thompson

On Fri, Nov 03, 2017 at 10:16:52AM +0000, Ard Biesheuvel wrote:
> Add a RealTimeClockLib implementation for the NXP PCF8563 as used on
> the Socionext Developer Box board. Note that the standard I2C protocol
> stack does not support runtime use, so this driver invokes the I2C master
> protocol directly. This requires support from the platform side as well,
> and so this driver will only attach to a I2C master that has the
> gPcf8563RealTimeClockLibI2cMasterProtolGuid protocol installed on its
> handle. It is up to the platform to ensure that the driver producing
> the I2C master protocol in question is runtime capable, and is not
> shared with the I2C protocol stack (i.e., it should not have the I2C
> Bus Configuration Management protocol installed as well).
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>

> ---
>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c   | 385 ++++++++++++++++++++
>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec |  29 ++
>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf |  52 +++
>  3 files changed, 466 insertions(+)


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP
  2017-11-08 16:43   ` Leif Lindholm
@ 2017-11-08 17:44     ` Ard Biesheuvel
  0 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2017-11-08 17:44 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel@lists.01.org, Daniel Thompson

On 8 November 2017 at 16:43, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> On Fri, Nov 03, 2017 at 10:16:52AM +0000, Ard Biesheuvel wrote:
>> Add a RealTimeClockLib implementation for the NXP PCF8563 as used on
>> the Socionext Developer Box board. Note that the standard I2C protocol
>> stack does not support runtime use, so this driver invokes the I2C master
>> protocol directly. This requires support from the platform side as well,
>> and so this driver will only attach to a I2C master that has the
>> gPcf8563RealTimeClockLibI2cMasterProtolGuid protocol installed on its
>> handle. It is up to the platform to ensure that the driver producing
>> the I2C master protocol in question is runtime capable, and is not
>> shared with the I2C protocol stack (i.e., it should not have the I2C
>> Bus Configuration Management protocol installed as well).
>>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c   | 385 ++++++++++++++++++++
>>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec |  29 ++
>>  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf |  52 +++
>>  3 files changed, 466 insertions(+)
>>
>> diff --git a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
>> new file mode 100644
>> index 000000000000..fea65a225d7f
>> --- /dev/null
>> +++ b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.c
>> @@ -0,0 +1,385 @@
>> +/** @file
>> +
>> +  Copyright (c) 2017, Linaro, Ltd. 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.
>> +
>> +**/
>> +
>> +#include <PiDxe.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/IoLib.h>
>> +#include <Library/RealTimeClockLib.h>
>> +#include <Library/UefiBootServicesTableLib.h>
>> +#include <Library/UefiLib.h>
>> +#include <Library/UefiRuntimeLib.h>
>> +#include <Protocol/I2cMaster.h>
>> +
>> +#define SLAVE_ADDRESS             (FixedPcdGet8 (PcdI2cSlaveAddress))
>> +#define PCF8563_DATA_REG_OFFSET   0x2
>> +
>> +#define PCF8563_SECONDS_MASK      0x7f
>> +#define PCF8563_MINUTES_MASK      0x7f
>> +#define PCF8563_HOURS_MASK        0x3f
>> +#define PCF8563_DAYS_MASK         0x3f
>> +#define PCF8563_WEEKDAYS_MASK     0x07
>> +#define PCF8563_MONTHS_MASK       0x1f
>> +#define PCF8563_CENTURY_MASK      0x80
>> +
>> +#define EPOCH_BASE                2000
>> +
>> +STATIC EFI_HANDLE                 mI2cMasterHandle;
>> +STATIC VOID                       *mDriverEventRegistration;
>> +STATIC EFI_I2C_MASTER_PROTOCOL    *mI2cMaster;
>> +STATIC EFI_EVENT                  mRtcVirtualAddrChangeEvent;
>> +
>> +typedef struct {
>> +  UINTN                           OperationCount;
>> +  EFI_I2C_OPERATION               SetAddressOp;
>> +  EFI_I2C_OPERATION               GetSetDateTimeOp;
>> +} RTC_I2C_REQUEST;
>> +
>> +#pragma pack(1)
>> +typedef struct {
>> +  UINT8     VL_seconds;
>> +  UINT8     Minutes;
>> +  UINT8     Hours;
>> +  UINT8     Days;
>> +  UINT8     Weekdays;
>> +  UINT8     Century_months;
>> +  UINT8     Years;
>> +} RTC_DATETIME;
>> +#pragma pack()
>> +
>> +/**
>> +  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.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +LibGetTime (
>> +  OUT EFI_TIME                *Time,
>> +  OUT EFI_TIME_CAPABILITIES   *Capabilities
>> +  )
>> +{
>> +  RTC_I2C_REQUEST             Op;
>> +  RTC_DATETIME                DateTime;
>> +  EFI_STATUS                  Status;
>> +  UINT8                       Reg;
>> +
>> +  if (Time == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  if (mI2cMaster == NULL) {
>> +    return EFI_DEVICE_ERROR;
>> +  }
>> +
>> +  Reg = PCF8563_DATA_REG_OFFSET;
>> +
>> +  Op.OperationCount = 2;
>> +
>> +  Op.SetAddressOp.Flags = 0;
>> +  Op.SetAddressOp.LengthInBytes = 1;
>> +  Op.SetAddressOp.Buffer = &Reg;
>> +
>> +  Op.GetSetDateTimeOp.Flags = I2C_FLAG_READ;
>> +  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
>> +  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
>> +
>> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
>> +                         (VOID *)&Op, NULL, NULL);
>> +  if (EFI_ERROR (Status)) {
>> +    return EFI_DEVICE_ERROR;
>> +  }
>> +
>> +  Time->Second  = BcdToDecimal8 (DateTime.VL_seconds & PCF8563_SECONDS_MASK);
>> +  Time->Minute  = BcdToDecimal8 (DateTime.Minutes & PCF8563_MINUTES_MASK);
>> +  Time->Hour    = BcdToDecimal8 (DateTime.Hours & PCF8563_HOURS_MASK);
>> +  Time->Day     = BcdToDecimal8 (DateTime.Days & PCF8563_DAYS_MASK);
>> +  Time->Month   = BcdToDecimal8 (DateTime.Century_months & PCF8563_MONTHS_MASK);
>> +  Time->Year    = BcdToDecimal8 (DateTime.Years) + EPOCH_BASE;
>> +
>> +  if (DateTime.Century_months & PCF8563_CENTURY_MASK) {
>> +    Time->Year += 100;
>
> Guess we'd better retire all these platforms before the year 2100
> then... (Or, given EPOCH_BASE, is it 2070? (Or given EPOCH_BASE being
> set to 2000, is it 2200?))
>
> Could you add a small comment next to the EPOCH_BASE definition
> explaining the constrainst?
>

Well, ultimately it doesn't really matter, given that this IP treats
all years divisible by 4 as leap years, so regardless of which base we
choose, it is going to jump to 29/2/2100 no matter what.

So the EPOCH_BASE could even be 2016: UEFI fully owns the RTC so it
can do whatever it wants. 2000 just seemed the least arbitrary.

>> +  }
>> +
>> +  Time->Daylight  = EFI_TIME_ADJUST_DAYLIGHT;
>> +  Time->TimeZone  = 0; /* UTC */
>> +
>> +  if (Capabilities != NULL) {
>> +    Capabilities->Resolution = 1;
>> +    Capabilities->Accuracy = 0;
>> +    Capabilities->SetsToZero = TRUE;
>> +  }
>> +  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
>> +  )
>> +{
>> +  RTC_I2C_REQUEST             Op;
>> +  RTC_DATETIME                DateTime;
>> +  EFI_STATUS                  Status;
>> +  UINT8                       Reg;
>> +
>> +  if (mI2cMaster == NULL) {
>> +    return EFI_DEVICE_ERROR;
>> +  }
>> +
>> +  DateTime.VL_seconds     = DecimalToBcd8 (Time->Second);
>> +  DateTime.Minutes        = DecimalToBcd8 (Time->Minute);
>> +  DateTime.Hours          = DecimalToBcd8 (Time->Hour);
>> +  DateTime.Days           = DecimalToBcd8 (Time->Day);
>> +  DateTime.Century_months = DecimalToBcd8 (Time->Month);
>> +  DateTime.Years          = DecimalToBcd8 (Time->Year % 100);
>> +  if (Time->Year >= EPOCH_BASE + 100) {
>> +    DateTime.Century_months |= PCF8563_CENTURY_MASK;
>
> Are you going to slap me if I ask for this to return error if
> Time->Year >= EPOCH_BASE + 200?
>

Actually, I think it would be better to treat the century bit as a
toggle, depending on whether (year % 200) >= 100


>> +  }
>> +
>> +  Reg = PCF8563_DATA_REG_OFFSET;
>> +
>> +  Op.OperationCount = 2;
>> +
>> +  Op.SetAddressOp.Flags = 0;
>> +  Op.SetAddressOp.LengthInBytes = 1;
>> +  Op.SetAddressOp.Buffer = &Reg;
>> +
>> +  Op.GetSetDateTimeOp.Flags = 0;
>> +  Op.GetSetDateTimeOp.LengthInBytes = sizeof (RTC_DATETIME);
>> +  Op.GetSetDateTimeOp.Buffer = (VOID *)&DateTime;
>> +
>> +  Status = mI2cMaster->StartRequest (mI2cMaster, SLAVE_ADDRESS,
>> +                         (VOID *)&Op, NULL, NULL);
>> +  if (EFI_ERROR (Status)) {
>> +    return EFI_DEVICE_ERROR;
>> +  }
>> +  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
>> +  )
>> +{
>> +  return EFI_UNSUPPORTED;
>
> For now, unsupported by current platforms, or unsupportable by this
> RTC device?
>

Well, getting and setting the wakeup time should be fairly trivial to
implement, but I can't really test it on the hardware we have (the INT
line is not connected), so I didn't bother. I'll add a comment to that
effect.

>> +}
>> +
>> +
>> +/**
>> +  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
>> +  )
>> +{
>> +  return EFI_UNSUPPORTED;
>
> Same question.
>

Same answer. Trivial to implement, impossible to test fully atm
(especially because I fried my board today)

>> +}
>> +
>> +STATIC
>> +VOID
>> +DriverRegistrationEvent (
>> +  IN  EFI_EVENT       Event,
>> +  IN  VOID            *Context
>> +  )
>> +{
>> +  EFI_HANDLE                Handle[2];
>> +  UINTN                     BufferSize;
>> +  EFI_STATUS                Status;
>> +  EFI_I2C_MASTER_PROTOCOL   *I2cMaster;
>> +  UINTN                     BusFrequency;
>> +
>> +  //
>> +  // Try to connect the newly registered driver to our handle.
>> +  //
>> +  do {
>> +    BufferSize = sizeof (EFI_HANDLE);
>> +    Status = gBS->LocateHandle (ByRegisterNotify,
>> +                                &gEfiDriverBindingProtocolGuid,
>> +                                mDriverEventRegistration,
>> +                                &BufferSize,
>> +                                Handle);
>> +    if (EFI_ERROR (Status)) {
>> +      if (Status != EFI_NOT_FOUND) {
>> +        DEBUG ((DEBUG_WARN, "%a: gBS->LocateHandle () returned %r\n",
>> +          __FUNCTION__, Status));
>> +      }
>> +      break;
>> +    }
>> +
>> +    //
>> +    // Check if we can connect our handle to this driver.
>> +    //
>> +    Handle[1] = NULL;
>> +    Status = gBS->ConnectController (mI2cMasterHandle, Handle, NULL, FALSE);
>> +    if (EFI_ERROR (Status)) {
>> +      continue;
>> +    }
>> +
>> +    DEBUG ((DEBUG_INFO, "%a: found I2C master!\n", __FUNCTION__));
>> +
>> +    gBS->CloseEvent (Event);
>> +
>> +    Status = gBS->OpenProtocol (mI2cMasterHandle, &gEfiI2cMasterProtocolGuid,
>> +                    (VOID **)&I2cMaster, gImageHandle, NULL,
>> +                    EFI_OPEN_PROTOCOL_EXCLUSIVE);
>> +    ASSERT_EFI_ERROR (Status);
>> +
>> +    Status = I2cMaster->Reset (I2cMaster);
>> +    if (EFI_ERROR (Status)) {
>> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->Reset () failed - %r\n",
>> +        __FUNCTION__, Status));
>> +      break;
>> +    }
>> +
>> +    BusFrequency = FixedPcdGet16 (PcdI2cBusFrequency);
>> +    Status = I2cMaster->SetBusFrequency (I2cMaster, &BusFrequency);
>> +    if (EFI_ERROR (Status)) {
>> +      DEBUG ((DEBUG_ERROR, "%a: I2CMaster->SetBusFrequency () failed - %r\n",
>> +        __FUNCTION__, Status));
>> +      break;
>> +    }
>> +
>> +    mI2cMaster = I2cMaster;
>> +    break;
>> +  } while (TRUE);
>> +}
>> +
>> +/**
>> +  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
>> +  )
>> +{
>> +  EfiConvertPointer (0x0, (VOID **)&mI2cMaster);
>> +}
>> +
>> +/**
>> +  Library entry point
>> +
>> +  @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;
>> +  UINTN               BufferSize;
>> +
>> +  //
>> +  // Find the handle that marks the controller
>> +  // that will provide the I2C master protocol.
>> +  //
>> +  BufferSize = sizeof (EFI_HANDLE);
>> +  Status = gBS->LocateHandle (ByProtocol,
>> +                  &gPcf8563RealTimeClockLibI2cMasterProtolGuid, NULL,
>> +                  &BufferSize, &mI2cMasterHandle);
>> +  ASSERT_EFI_ERROR (Status);
>> +
>> +  //
>> +  // Register a protocol registration notification callback on the driver
>> +  // binding protocol so we can attempt to connect our I2C master to it
>> +  // as soon as it appears.
>> +  //
>> +  EfiCreateProtocolNotifyEvent (
>> +    &gEfiDriverBindingProtocolGuid,
>> +    TPL_CALLBACK,
>> +    DriverRegistrationEvent,
>> +    NULL,
>> +    &mDriverEventRegistration);
>> +
>> +  //
>> +  // Register for the virtual address change event
>> +  //
>> +  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
>> +                  LibRtcVirtualNotifyEvent, NULL,
>> +                  &gEfiEventVirtualAddressChangeGuid,
>> +                  &mRtcVirtualAddrChangeEvent);
>> +  ASSERT_EFI_ERROR (Status);
>> +
>> +  return EFI_SUCCESS;
>> +}
>> diff --git a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
>> new file mode 100644
>> index 000000000000..bc8fc60c0602
>> --- /dev/null
>> +++ b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
>> @@ -0,0 +1,29 @@
>> +#/** @file
>> +#
>> +#  Copyright (c) 2017, Linaro, Ltd. 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]
>> +  DEC_SPECIFICATION              = 0x0001001A
>> +  PACKAGE_NAME                   = Pcf8563RealTimeClockLib
>> +  PACKAGE_GUID                   = 44d63668-c86b-446a-b303-f3a5176702aa
>> +  PACKAGE_VERSION                = 0.1
>> +
>> +[Guids]
>> +  gPcf8563RealTimeClockLibTokenSpaceGuid = { 0xaaf5b169, 0x93a0, 0x4d60, { 0xba, 0xe4, 0x06, 0x07, 0x92, 0x8e, 0x63, 0xdd }}
>> +
>> +[Protocols]
>> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid = { 0xa6af18ae, 0x3bd5, 0x4af9, { 0xbb, 0x6a, 0xdb, 0x85, 0x07, 0x62, 0x81, 0x38 }}
>> +
>> +[PcdsFixedAtBuild]
>> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress|0x51|UINT8|0x00000001
>> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency|400|UINT16|0x00000002
>
> Could you add a comment clarifying unit?
>

Yep, and actually this is wrong. It should be in Hz not kHz

>> diff --git a/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
>> new file mode 100644
>> index 000000000000..e1e001162144
>> --- /dev/null
>> +++ b/Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.inf
>> @@ -0,0 +1,52 @@
>> +#/** @file
>> +#
>> +#  Copyright (c) 2017, Linaro, Ltd. 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                    = 0x0001001A
>> +  BASE_NAME                      = Pcf8563RealTimeClockLib
>> +  FILE_GUID                      = 1e3d33f3-a671-4116-bd81-6b435296c1e0
>> +  MODULE_TYPE                    = DXE_DRIVER
>> +  VERSION_STRING                 = 1.0
>> +  LIBRARY_CLASS                  = RealTimeClockLib
>> +
>> +[Sources.common]
>> +  Pcf8563RealTimeClockLib.c
>> +
>> +[Packages]
>> +  MdePkg/MdePkg.dec
>> +  EmbeddedPkg/EmbeddedPkg.dec
>> +  Silicon/NXP/Library/Pcf8563RealTimeClockLib/Pcf8563RealTimeClockLib.dec
>> +
>> +[LibraryClasses]
>> +  BaseMemoryLib
>> +  DebugLib
>> +  IoLib
>> +  UefiBootServicesTableLib
>> +  UefiLib
>> +  UefiRuntimeLib
>> +
>> +[Guids]
>> +  gEfiEventVirtualAddressChangeGuid
>> +
>> +[Protocols]
>> +  gEfiDriverBindingProtocolGuid                   ## CONSUMES
>> +  gEfiI2cMasterProtocolGuid                       ## CONSUMES
>> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid     ## CONSUMES
>> +
>> +[FixedPcd]
>> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cSlaveAddress
>> +  gPcf8563RealTimeClockLibTokenSpaceGuid.PcdI2cBusFrequency
>> +
>> +[Depex]
>> +  gPcf8563RealTimeClockLibI2cMasterProtolGuid
>> --
>> 2.11.0
>>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP
  2017-11-08 16:47   ` Leif Lindholm
@ 2017-11-08 17:45     ` Ard Biesheuvel
  2017-11-08 20:19       ` Leif Lindholm
  0 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2017-11-08 17:45 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel@lists.01.org, Daniel Thompson

On 8 November 2017 at 16:47, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> On Fri, Nov 03, 2017 at 10:16:52AM +0000, Ard Biesheuvel wrote:
>> Add a RealTimeClockLib implementation for the NXP PCF8563 as used on
>> the Socionext Developer Box board. Note that the standard I2C protocol
>> stack does not support runtime use, so this driver invokes the I2C master
>> protocol directly. This requires support from the platform side as well,
>> and so this driver will only attach to a I2C master that has the
>> gPcf8563RealTimeClockLibI2cMasterProtolGuid protocol installed on its
>> handle. It is up to the platform to ensure that the driver producing
>> the I2C master protocol in question is runtime capable, and is not
>> shared with the I2C protocol stack (i.e., it should not have the I2C
>> Bus Configuration Management protocol installed as well).
>>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>
> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
>

Ehm, is this in response to the correct patch, given that you already
asked for some changes?


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP
  2017-11-08 17:45     ` Ard Biesheuvel
@ 2017-11-08 20:19       ` Leif Lindholm
  0 siblings, 0 replies; 13+ messages in thread
From: Leif Lindholm @ 2017-11-08 20:19 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: edk2-devel@lists.01.org, Daniel Thompson

On Wed, Nov 08, 2017 at 05:45:11PM +0000, Ard Biesheuvel wrote:
> On 8 November 2017 at 16:47, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> > On Fri, Nov 03, 2017 at 10:16:52AM +0000, Ard Biesheuvel wrote:
> >> Add a RealTimeClockLib implementation for the NXP PCF8563 as used on
> >> the Socionext Developer Box board. Note that the standard I2C protocol
> >> stack does not support runtime use, so this driver invokes the I2C master
> >> protocol directly. This requires support from the platform side as well,
> >> and so this driver will only attach to a I2C master that has the
> >> gPcf8563RealTimeClockLibI2cMasterProtolGuid protocol installed on its
> >> handle. It is up to the platform to ensure that the driver producing
> >> the I2C master protocol in question is runtime capable, and is not
> >> shared with the I2C protocol stack (i.e., it should not have the I2C
> >> Bus Configuration Management protocol installed as well).
> >>
> >> Contributed-under: TianoCore Contribution Agreement 1.1
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >
> > Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
> 
> Ehm, is this in response to the correct patch, given that you already
> asked for some changes?

No, that's me getting confused by the patches appearing out of order
in my inbox... Apologies.

/
    Leif


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-11-08 20:15 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-11-03 10:16 [RFC PATCH edk2-platforms 0/3] add I2C RTC support to DeveloperBox Ard Biesheuvel
2017-11-03 10:16 ` [RFC PATCH edk2-platforms 1/3] Silicon/NXP: add RTC support library for PCF8563 I2C IP Ard Biesheuvel
2017-11-06 11:09   ` Udit Kumar
2017-11-06 11:11     ` Ard Biesheuvel
2017-11-07  4:37       ` Udit Kumar
2017-11-08 16:43   ` Leif Lindholm
2017-11-08 17:44     ` Ard Biesheuvel
2017-11-08 16:47   ` Leif Lindholm
2017-11-08 17:45     ` Ard Biesheuvel
2017-11-08 20:19       ` Leif Lindholm
2017-11-03 10:16 ` [RFC PATCH edk2-platforms 2/3] Silicon/Socionext: implement I2C master protocol for SynQuacer I2C Ard Biesheuvel
2017-11-03 10:16 ` [RFC PATCH edk2-platforms 3/3] Platform/DeveloperBox: wire up RTC support Ard Biesheuvel
2017-11-08 16:47   ` Leif Lindholm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox