]> git.proxmox.com Git - mirror_edk2.git/commitdiff
PcAtChipsetPkg: Add MMIO Support to RTC driver
authorSami Mujawar <sami.mujawar@arm.com>
Fri, 2 Oct 2020 21:13:55 +0000 (22:13 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 16 Oct 2020 17:21:04 +0000 (17:21 +0000)
Some virtual machine managers like Kvmtool emulate the MC146818
RTC controller in the MMIO space so that architectures that do
not support I/O Mapped I/O can use the RTC. This patch adds MMIO
support to the RTC controller driver.

The PCD PcdRtcUseMmio has been added to select I/O or MMIO support.
  If PcdRtcUseMmio is:
    TRUE  - Indicates the RTC port registers are in MMIO space.
    FALSE - Indicates the RTC port registers are in I/O space.
            Default is I/O space.

Additionally two new PCDs PcdRtcIndexRegister64 and
PcdRtcTargetRegister64 have been introduced to provide the base
address for the RTC registers in the MMIO space.

When MMIO support is selected (PcdRtcUseMmio == TRUE) the driver
converts the pointers to the RTC MMIO registers so that the
RTC registers are accessible post ExitBootServices.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
PcAtChipsetPkg/PcAtChipsetPkg.dec
PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf

index 88de5cceea593176c3a2425a5963b66b789f2b9e..ed2d95550b8d153995b30cdc290cf3bb905e211b 100644 (file)
@@ -6,6 +6,7 @@
 #\r
 # Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>\r
 # Copyright (c) 2017, AMD Inc. All rights reserved.<BR>\r
+# Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR>\r
 #\r
 # SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
   # @Prompt Configure HPET to use MSI.\r
   gPcAtChipsetPkgTokenSpaceGuid.PcdHpetMsiEnable|TRUE|BOOLEAN|0x00001000\r
 \r
+  ## Indicates the RTC port registers are in MMIO space, or in I/O space.\r
+  #  Default is I/O space.<BR><BR>\r
+  #   TRUE  - RTC port registers are in MMIO space.<BR>\r
+  #   FALSE - RTC port registers are in I/O space.<BR>\r
+  # @Prompt RTC port registers use MMIO.\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio|FALSE|BOOLEAN|0x00000021\r
+\r
 [PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule]\r
   ## This PCD specifies the base address of the HPET timer.\r
   # @Prompt HPET base address.\r
   # @Expression 0x80000001 | gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear < gPcAtChipsetPkgTokenSpaceGuid.PcdMinimalValidYear + 100\r
   gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear|2097|UINT16|0x0000000E\r
 \r
+  ## Specifies RTC Index Register address in MMIO space.\r
+  # @Prompt RTC Index Register address\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64|0x0|UINT64|0x00000022\r
+\r
+  ## Specifies RTC Target Register address in MMIO space.\r
+  # @Prompt RTC Target Register address\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister64|0x0|UINT64|0x00000023\r
+\r
 [PcdsFixedAtBuild, PcdsPatchableInModule]\r
   ## Defines the ACPI register set base address.\r
   #  The invalid 0xFFFF is as its default value. It must be configured to the real value.\r
index 52af17941786ef81c3911512ee64551724e67209..64f36f6fbbd1b03967bd1a1290d108d5b0f294fa 100644 (file)
@@ -3,6 +3,7 @@
 \r
 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
 Copyright (c) 2017, AMD Inc. All rights reserved.<BR>\r
+Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR>\r
 \r
 SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
@@ -10,6 +11,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 \r
 #include "PcRtc.h"\r
 \r
+extern UINTN  mRtcIndexRegister;\r
+extern UINTN  mRtcTargetRegister;\r
+\r
 //\r
 // Days of month.\r
 //\r
@@ -53,39 +57,133 @@ IsWithinOneDay (
   IN EFI_TIME   *To\r
   );\r
 \r
+/**\r
+  Read RTC content through its registers using IO access.\r
+\r
+  @param  Address   Address offset of RTC. It is recommended to use\r
+                    macros such as RTC_ADDRESS_SECONDS.\r
+\r
+  @return The data of UINT8 type read from RTC.\r
+**/\r
+STATIC\r
+UINT8\r
+IoRtcRead (\r
+  IN  UINTN Address\r
+  )\r
+{\r
+  IoWrite8 (\r
+    PcdGet8 (PcdRtcIndexRegister),\r
+    (UINT8)(Address | (UINT8)(IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80))\r
+    );\r
+  return IoRead8 (PcdGet8 (PcdRtcTargetRegister));\r
+}\r
+\r
+/**\r
+  Write RTC through its registers  using IO access.\r
+\r
+  @param  Address   Address offset of RTC. It is recommended to use\r
+                    macros such as RTC_ADDRESS_SECONDS.\r
+  @param  Data      The content you want to write into RTC.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+IoRtcWrite (\r
+  IN  UINTN   Address,\r
+  IN  UINT8   Data\r
+  )\r
+{\r
+  IoWrite8 (\r
+    PcdGet8 (PcdRtcIndexRegister),\r
+    (UINT8)(Address | (UINT8)(IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80))\r
+    );\r
+  IoWrite8 (PcdGet8 (PcdRtcTargetRegister), Data);\r
+}\r
+\r
+/**\r
+  Read RTC content through its registers using MMIO access.\r
+\r
+  @param  Address   Address offset of RTC. It is recommended to use\r
+                    macros such as RTC_ADDRESS_SECONDS.\r
+\r
+  @return The data of UINT8 type read from RTC.\r
+**/\r
+STATIC\r
+UINT8\r
+MmioRtcRead (\r
+  IN  UINTN Address\r
+  )\r
+{\r
+  MmioWrite8 (\r
+    mRtcIndexRegister,\r
+    (UINT8)(Address | (UINT8)(MmioRead8 (mRtcIndexRegister) & 0x80))\r
+    );\r
+  return MmioRead8 (mRtcTargetRegister);\r
+}\r
+\r
+/**\r
+  Write RTC through its registers using MMIO access.\r
+\r
+  @param  Address   Address offset of RTC. It is recommended to use\r
+                    macros such as RTC_ADDRESS_SECONDS.\r
+  @param  Data      The content you want to write into RTC.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+MmioRtcWrite (\r
+  IN  UINTN   Address,\r
+  IN  UINT8   Data\r
+  )\r
+{\r
+  MmioWrite8 (\r
+    mRtcIndexRegister,\r
+    (UINT8)(Address | (UINT8)(MmioRead8 (mRtcIndexRegister) & 0x80))\r
+    );\r
+  MmioWrite8 (mRtcTargetRegister, Data);\r
+}\r
+\r
 /**\r
   Read RTC content through its registers.\r
 \r
-  @param  Address  Address offset of RTC. It is recommended to use macros such as\r
-                   RTC_ADDRESS_SECONDS.\r
+  @param  Address   Address offset of RTC. It is recommended to use\r
+                    macros such as RTC_ADDRESS_SECONDS.\r
 \r
   @return The data of UINT8 type read from RTC.\r
 **/\r
+STATIC\r
 UINT8\r
 RtcRead (\r
-  IN  UINT8 Address\r
+  IN  UINTN Address\r
   )\r
 {\r
-  IoWrite8 (PcdGet8 (PcdRtcIndexRegister), (UINT8) (Address | (UINT8) (IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80)));\r
-  return IoRead8 (PcdGet8 (PcdRtcTargetRegister));\r
+  if (FeaturePcdGet (PcdRtcUseMmio)) {\r
+    return MmioRtcRead (Address);\r
+  }\r
+\r
+  return IoRtcRead (Address);\r
 }\r
 \r
 /**\r
   Write RTC through its registers.\r
 \r
-  @param  Address  Address offset of RTC. It is recommended to use macros such as\r
-                   RTC_ADDRESS_SECONDS.\r
-  @param  Data     The content you want to write into RTC.\r
+  @param  Address   Address offset of RTC. It is recommended to use\r
+                    macros such as RTC_ADDRESS_SECONDS.\r
+  @param  Data      The content you want to write into RTC.\r
 \r
 **/\r
+STATIC\r
 VOID\r
 RtcWrite (\r
-  IN  UINT8   Address,\r
+  IN  UINTN   Address,\r
   IN  UINT8   Data\r
   )\r
 {\r
-  IoWrite8 (PcdGet8 (PcdRtcIndexRegister), (UINT8) (Address | (UINT8) (IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80)));\r
-  IoWrite8 (PcdGet8 (PcdRtcTargetRegister), Data);\r
+  if (FeaturePcdGet (PcdRtcUseMmio)) {\r
+    MmioRtcWrite (Address, Data);\r
+  } else {\r
+    IoRtcWrite (Address, Data);\r
+  }\r
 }\r
 \r
 /**\r
index ccda6331373bfe4069b0a59495b5e5cc731c8fc8..606b88adafb7ef5d81e32e212794a5ccae9d0443 100644 (file)
@@ -2,16 +2,23 @@
   Provides Set/Get time operations.\r
 \r
 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR>\r
 SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
+#include <Library/DxeServicesTableLib.h>\r
 #include "PcRtc.h"\r
 \r
 PC_RTC_MODULE_GLOBALS  mModuleGlobal;\r
 \r
 EFI_HANDLE             mHandle = NULL;\r
 \r
+STATIC EFI_EVENT       mVirtualAddrChangeEvent;\r
+\r
+UINTN                  mRtcIndexRegister;\r
+UINTN                  mRtcTargetRegister;\r
+\r
 /**\r
   Returns the current time and date information, and the time-keeping capabilities\r
   of the hardware platform.\r
@@ -105,6 +112,30 @@ PcRtcEfiSetWakeupTime (
   return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);\r
 }\r
 \r
+/**\r
+  Fixup internal data so that EFI can be called in virtual mode.\r
+  Call the passed in Child Notify event and convert any pointers in\r
+  lib to virtual mode.\r
+\r
+  @param[in]    Event   The Event that is being processed\r
+  @param[in]    Context Event Context\r
+**/\r
+VOID\r
+EFIAPI\r
+LibRtcVirtualNotifyEvent (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+{\r
+  // Only needed if you are going to support the OS calling RTC functions in\r
+  // virtual mode. You will need to call EfiConvertPointer (). To convert any\r
+  // stored physical addresses to virtual address. After the OS transitions to\r
+  // calling in virtual mode, all future runtime calls will be made in virtual\r
+  // mode.\r
+  EfiConvertPointer (0x0, (VOID**)&mRtcIndexRegister);\r
+  EfiConvertPointer (0x0, (VOID**)&mRtcTargetRegister);\r
+}\r
+\r
 /**\r
   The user Entry Point for PcRTC module.\r
 \r
@@ -131,6 +162,11 @@ InitializePcRtc (
   EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_CALLBACK);\r
   mModuleGlobal.CenturyRtcAddress = GetCenturyRtcAddress ();\r
 \r
+  if (FeaturePcdGet (PcdRtcUseMmio)) {\r
+    mRtcIndexRegister = (UINTN)PcdGet64 (PcdRtcIndexRegister64);\r
+    mRtcTargetRegister = (UINTN)PcdGet64 (PcdRtcTargetRegister64);\r
+  }\r
+\r
   Status = PcRtcInit (&mModuleGlobal);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -165,7 +201,23 @@ InitializePcRtc (
                   NULL,\r
                   NULL\r
                   );\r
-  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT_EFI_ERROR (Status);\r
+    return Status;\r
+  }\r
+\r
+  if (FeaturePcdGet (PcdRtcUseMmio)) {\r
+    // Register for the virtual address change event\r
+    Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    LibRtcVirtualNotifyEvent,\r
+                    NULL,\r
+                    &gEfiEventVirtualAddressChangeGuid,\r
+                    &mVirtualAddrChangeEvent\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
 \r
   return Status;\r
 }\r
index c73ee98105e510f9e4e23c1a6c1e5c505325d2c9..0d8eca28b65954b073a72fc4fe5ad6247320e79d 100644 (file)
@@ -6,6 +6,7 @@
 #\r
 # Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
 # Copyright (c) 2017, AMD Inc. All rights reserved.<BR>\r
+# Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR>\r
 #\r
 # SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
   ## SOMETIMES_CONSUMES ## SystemTable\r
   gEfiAcpiTableGuid\r
 \r
+  gEfiEventVirtualAddressChangeGuid\r
+\r
+[FeaturePcd]\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio                   ## CONSUMES\r
+\r
 [FixedPcd]\r
   gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterA     ## CONSUMES\r
   gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterB     ## CONSUMES\r
@@ -72,6 +78,8 @@
   gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear             ## CONSUMES\r
   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister             ## CONSUMES\r
   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister            ## CONSUMES\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64           ## CONSUMES\r
+  gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister64          ## CONSUMES\r
 \r
 [Depex]\r
   gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid\r