]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPlatformPkg/PL031RealTimeClock: Fixed driver to support UEFI Runtime Services
authorOlivier Martin <olivier.martin@arm.com>
Tue, 8 Apr 2014 17:59:00 +0000 (17:59 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 8 Apr 2014 17:59:00 +0000 (17:59 +0000)
- Removed PCD base address from the macro definition. The base address needs to be fixup when the driver runs in UEFI Runtime mode
- Added the PL031 controller memory region to the Runtime UEFI Memory Mapped IO
- Caught the gEfiEventVirtualAddressChangeGuid event to fixup the PL031 Base address

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15435 6f19259b-4bc3-4df7-8a09-765794883524

ArmPlatformPkg/Include/Drivers/PL031RealTimeClock.h
ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.c
ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf

index 4c559c0c952bbe75f39cc9be3b2ddfb6816635ac..76fbd0eb8225f68f3867a42a36adfcf9f52c85c1 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 *\r
-*  Copyright (c) 2011, ARM Limited. All rights reserved.\r
+*  Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.\r
 *\r
 *  This program and the accompanying materials\r
 *  are licensed and made available under the terms and conditions of the BSD License\r
 #define __PL031_REAL_TIME_CLOCK_H__\r
 \r
 // PL031 Registers\r
-#define PL031_RTC_DR_DATA_REGISTER                      ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x000)\r
-#define PL031_RTC_MR_MATCH_REGISTER                     ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x004)\r
-#define PL031_RTC_LR_LOAD_REGISTER                      ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x008)\r
-#define PL031_RTC_CR_CONTROL_REGISTER                   ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x00C)\r
-#define PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER      ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x010)\r
-#define PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER           ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x014)\r
-#define PL031_RTC_MIS_MASKED_IRQ_STATUS_REGISTER        ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x018)\r
-#define PL031_RTC_ICR_IRQ_CLEAR_REGISTER                ((UINT32)PcdGet32(PcdPL031RtcBase) + 0x01C)\r
-#define PL031_RTC_PERIPH_ID0                            ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFE0)\r
-#define PL031_RTC_PERIPH_ID1                            ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFE4)\r
-#define PL031_RTC_PERIPH_ID2                            ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFE8)\r
-#define PL031_RTC_PERIPH_ID3                            ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFEC)\r
-#define PL031_RTC_PCELL_ID0                             ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFF0)\r
-#define PL031_RTC_PCELL_ID1                             ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFF4)\r
-#define PL031_RTC_PCELL_ID2                             ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFF8)\r
-#define PL031_RTC_PCELL_ID3                             ((UINT32)PcdGet32(PcdPL031RtcBase) + 0xFFC)\r
+#define PL031_RTC_DR_DATA_REGISTER                      0x000\r
+#define PL031_RTC_MR_MATCH_REGISTER                     0x004\r
+#define PL031_RTC_LR_LOAD_REGISTER                      0x008\r
+#define PL031_RTC_CR_CONTROL_REGISTER                   0x00C\r
+#define PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER      0x010\r
+#define PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER           0x014\r
+#define PL031_RTC_MIS_MASKED_IRQ_STATUS_REGISTER        0x018\r
+#define PL031_RTC_ICR_IRQ_CLEAR_REGISTER                0x01C\r
+#define PL031_RTC_PERIPH_ID0                            0xFE0\r
+#define PL031_RTC_PERIPH_ID1                            0xFE4\r
+#define PL031_RTC_PERIPH_ID2                            0xFE8\r
+#define PL031_RTC_PERIPH_ID3                            0xFEC\r
+#define PL031_RTC_PCELL_ID0                             0xFF0\r
+#define PL031_RTC_PCELL_ID1                             0xFF4\r
+#define PL031_RTC_PCELL_ID2                             0xFF8\r
+#define PL031_RTC_PCELL_ID3                             0xFFC\r
 \r
 // PL031 Values\r
 #define PL031_RTC_ENABLED                               0x00000001\r
index 980f809b2c6ccbc5832030144906dc1bedbb6bc6..b43d8dc4ba2fd69dda62aff22e230fbf96849d95 100644 (file)
@@ -4,7 +4,7 @@
   Currently this driver does not support runtime virtual calling.\r
 \r
   Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
-  Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>\r
+  Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/PcdLib.h>\r
 #include <Library/ArmPlatformSysConfigLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+\r
 #include <Protocol/RealTimeClock.h>\r
+\r
 #include <Guid/GlobalVariable.h>\r
+#include <Guid/EventGroup.h>\r
+\r
 #include <Drivers/PL031RealTimeClock.h>\r
 \r
 #include <ArmPlatform.h>\r
@@ -37,6 +43,8 @@
 STATIC CONST CHAR16  mTimeZoneVariableName[] = L"PL031RtcTimeZone";\r
 STATIC CONST CHAR16  mDaylightVariableName[] = L"PL031RtcDaylight";\r
 STATIC BOOLEAN       mPL031Initialized = FALSE;\r
+STATIC EFI_EVENT     mRtcVirtualAddrChangeEvent;\r
+STATIC UINTN         mPL031RtcBase;\r
 \r
 EFI_STATUS\r
 IdentifyPL031 (\r
@@ -46,19 +54,19 @@ IdentifyPL031 (
   EFI_STATUS    Status;\r
 \r
   // Check if this is a PrimeCell Peripheral\r
-  if (  (MmioRead8 (PL031_RTC_PCELL_ID0) != 0x0D)\r
-      || (MmioRead8 (PL031_RTC_PCELL_ID1) != 0xF0)\r
-      || (MmioRead8 (PL031_RTC_PCELL_ID2) != 0x05)\r
-      || (MmioRead8 (PL031_RTC_PCELL_ID3) != 0xB1)) {\r
+  if (  (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID0) != 0x0D)\r
+      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID1) != 0xF0)\r
+      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID2) != 0x05)\r
+      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID3) != 0xB1)) {\r
     Status = EFI_NOT_FOUND;\r
     goto EXIT;\r
   }\r
 \r
   // Check if this PrimeCell Peripheral is the PL031 Real Time Clock\r
-  if (  (MmioRead8 (PL031_RTC_PERIPH_ID0) != 0x31)\r
-      || (MmioRead8 (PL031_RTC_PERIPH_ID1) != 0x10)\r
-      || ((MmioRead8 (PL031_RTC_PERIPH_ID2) & 0xF) != 0x04)\r
-      || (MmioRead8 (PL031_RTC_PERIPH_ID3) != 0x00)) {\r
+  if (  (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID0) != 0x31)\r
+      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID1) != 0x10)\r
+      || ((MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID2) & 0xF) != 0x04)\r
+      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID3) != 0x00)) {\r
     Status = EFI_NOT_FOUND;\r
     goto EXIT;\r
   }\r
@@ -83,18 +91,18 @@ InitializePL031 (
   }\r
 \r
   // Ensure interrupts are masked. We do not want RTC interrupts in UEFI\r
-  if ((MmioRead32 (PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER) & PL031_SET_IRQ_MASK) != PL031_SET_IRQ_MASK) {\r
-    MmioOr32 (PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER, PL031_SET_IRQ_MASK);\r
+  if ((MmioRead32 (mPL031RtcBase + PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER) & PL031_SET_IRQ_MASK) != PL031_SET_IRQ_MASK) {\r
+    MmioOr32 (mPL031RtcBase + PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER, PL031_SET_IRQ_MASK);\r
   }\r
 \r
   // Clear any existing interrupts\r
-  if ((MmioRead32 (PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER) & PL031_IRQ_TRIGGERED) == PL031_IRQ_TRIGGERED) {\r
-    MmioOr32 (PL031_RTC_ICR_IRQ_CLEAR_REGISTER, PL031_CLEAR_IRQ);\r
+  if ((MmioRead32 (mPL031RtcBase + PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER) & PL031_IRQ_TRIGGERED) == PL031_IRQ_TRIGGERED) {\r
+    MmioOr32 (mPL031RtcBase + PL031_RTC_ICR_IRQ_CLEAR_REGISTER, PL031_CLEAR_IRQ);\r
   }\r
 \r
   // Start the clock counter\r
-  if ((MmioRead32 (PL031_RTC_CR_CONTROL_REGISTER) & PL031_RTC_ENABLED) != PL031_RTC_ENABLED) {\r
-    MmioOr32 (PL031_RTC_CR_CONTROL_REGISTER, PL031_RTC_ENABLED);\r
+  if ((MmioRead32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER) & PL031_RTC_ENABLED) != PL031_RTC_ENABLED) {\r
+    MmioOr32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER, PL031_RTC_ENABLED);\r
   }\r
 \r
   mPL031Initialized = TRUE;\r
@@ -267,7 +275,7 @@ LibGetTime (
   Status = ArmPlatformSysConfigGet (SYS_CFG_RTC, &EpochSeconds);\r
   if (Status == EFI_UNSUPPORTED) {\r
     // Battery backed up hardware RTC does not exist, revert to PL031\r
-    EpochSeconds = MmioRead32 (PL031_RTC_DR_DATA_REGISTER);\r
+    EpochSeconds = MmioRead32 (mPL031RtcBase + PL031_RTC_DR_DATA_REGISTER);\r
     Status = EFI_SUCCESS;\r
   } else if (EFI_ERROR (Status)) {\r
     // Battery backed up hardware RTC exists but could not be read due to error. Abort.\r
@@ -275,7 +283,7 @@ LibGetTime (
   } else {\r
     // Battery backed up hardware RTC exists and we read the time correctly from it.\r
     // Now sync the PL031 to the new time.\r
-    MmioWrite32 (PL031_RTC_LR_LOAD_REGISTER, EpochSeconds);\r
+    MmioWrite32 (mPL031RtcBase + PL031_RTC_LR_LOAD_REGISTER, EpochSeconds);\r
   }\r
 \r
   // Ensure Time is a valid pointer\r
@@ -484,7 +492,7 @@ LibSetTime (
 \r
 \r
   // Set the PL031\r
-  MmioWrite32 (PL031_RTC_LR_LOAD_REGISTER, EpochSeconds);\r
+  MmioWrite32 (mPL031RtcBase + PL031_RTC_LR_LOAD_REGISTER, EpochSeconds);\r
 \r
   // The accesses to Variable Services can be very slow, because we may be writing to Flash.\r
   // Do this after having set the RTC.\r
@@ -579,7 +587,30 @@ LibSetWakeupTime (
   return EFI_UNSUPPORTED;\r
 }\r
 \r
+/**\r
+  Fixup internal data so that EFI can be call 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
+  //\r
+  // Only needed if you are going to support the OS calling RTC functions in virtual mode.\r
+  // You will need to call EfiConvertPointer (). To convert any stored physical addresses\r
+  // to virtual address. After the OS transitions to calling in virtual mode, all future\r
+  // runtime calls will be made in virtual mode.\r
+  //\r
+  EfiConvertPointer (0x0, (VOID**)&mPL031RtcBase);\r
+  return;\r
+}\r
 \r
 /**\r
   This is the declaration of an EFI image entry point. This can be the entry point to an application\r
@@ -601,6 +632,24 @@ LibRtcInitialize (
   EFI_STATUS    Status;\r
   EFI_HANDLE    Handle;\r
 \r
+  // Initialize RTC Base Address\r
+  mPL031RtcBase = PcdGet32 (PcdPL031RtcBase);\r
+\r
+  // Declare the controller as EFI_MEMORY_RUNTIME\r
+  Status = gDS->AddMemorySpace (\r
+                  EfiGcdMemoryTypeMemoryMappedIo,\r
+                  mPL031RtcBase, SIZE_4KB,\r
+                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gDS->SetMemorySpaceAttributes (mPL031RtcBase, SIZE_4KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   // Setup the setters and getters\r
   gRT->GetTime       = LibGetTime;\r
   gRT->SetTime       = LibSetTime;\r
@@ -614,31 +663,20 @@ LibRtcInitialize (
                   &gEfiRealTimeClockArchProtocolGuid,  NULL,\r
                   NULL\r
                  );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Fixup internal data so that EFI can be call 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
   //\r
-  // Only needed if you are going to support the OS calling RTC functions in virtual mode.\r
-  // You will need to call EfiConvertPointer (). To convert any stored physical addresses\r
-  // to virtual address. After the OS transitions to calling in virtual mode, all future\r
-  // runtime calls will be made in virtual mode.\r
+  // Register for the virtual address change event\r
   //\r
-  return;\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  LibRtcVirtualNotifyEvent,\r
+                  NULL,\r
+                  &gEfiEventVirtualAddressChangeGuid,\r
+                  &mRtcVirtualAddrChangeEvent\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
 }\r
index add982ce8e4b442819ccbaddc3eeba00d51c5b4c..3a98fc757e3df8a3e5bd3f8dd86433a63822dfb5 100644 (file)
@@ -1,7 +1,7 @@
 #/** @file\r
 #\r
 # Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
-# Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>\r
+# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
   DebugLib\r
   PcdLib\r
   ArmPlatformSysConfigLib\r
+  DxeServicesTableLib\r
+  UefiRuntimeLib\r
+\r
+[Guids]\r
+  gEfiEventVirtualAddressChangeGuid\r
 \r
 [Pcd]\r
   gArmPlatformTokenSpaceGuid.PcdPL031RtcBase\r