]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c
ArmPkg: Apply uncrustify changes
[mirror_edk2.git] / ArmPkg / Library / ArmArchTimerLib / ArmArchTimerLib.c
index d6f3f1b709cd6dc724402a556e623b9784318c8d..d663a76a9b2cd56e3e7a1cb017df9336364a3e7c 100644 (file)
 /** @file\r
   Generic ARM implementation of TimerLib.h\r
 \r
-  Copyright (c) 2011, 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
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
+  Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>\r
 \r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
-\r
 #include <Base.h>\r
+#include <Library/ArmLib.h>\r
 #include <Library/BaseLib.h>\r
 #include <Library/TimerLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/PcdLib.h>\r
-#include <Library/ArmV7ArchTimerLib.h>\r
-#include <Chipset/ArmV7.h>\r
+#include <Library/ArmGenericTimerCounterLib.h>\r
+\r
+#define TICKS_PER_MICRO_SEC  (PcdGet32 (PcdArmArchTimerFreqInHz)/1000000U)\r
 \r
-#define TICKS_PER_MICRO_SEC     (PcdGet32 (PcdArmArchTimerFreqInHz)/1000000U)\r
+// Select appropriate multiply function for platform architecture.\r
+#ifdef MDE_CPU_ARM\r
+#define MULT_U64_X_N  MultU64x32\r
+#else\r
+#define MULT_U64_X_N  MultU64x64\r
+#endif\r
 \r
 RETURN_STATUS\r
 EFIAPI\r
-ArmArchTimerLibConstructor (\r
+TimerConstructor (\r
   VOID\r
   )\r
 {\r
-  // Check if the ARM Generic Timer Extension is implemented\r
+  //\r
+  // Check if the ARM Generic Timer Extension is implemented.\r
+  //\r
   if (ArmIsArchTimerImplemented ()) {\r
-\r
-    UINTN TimerFreq;\r
-\r
-    // Check if Architectural Timer frequency is valid number (should not be 0)\r
-    ASSERT (PcdGet32 (PcdArmArchTimerFreqInHz));\r
-\r
-    // Check if ticks/uS is not 0. The Architectural timer runs at constant\r
-    // frequency irrespective of CPU frequency. According to General Timer Ref\r
-    // manual lower bound of the frequency is in the range of 1-10MHz\r
-    ASSERT (TICKS_PER_MICRO_SEC);\r
-\r
-    // If the security extensions are not implemented set Timer Frequency\r
-    if ((ArmReadIdPfr1 () & 0xF0)) {\r
-      ArmArchTimerSetTimerFreq (PcdGet32 (PcdArmArchTimerFreqInHz));\r
+    //\r
+    // Check if Architectural Timer frequency is pre-determined by the platform\r
+    // (ie. nonzero).\r
+    //\r
+    if (PcdGet32 (PcdArmArchTimerFreqInHz) != 0) {\r
+      //\r
+      // Check if ticks/uS is not 0. The Architectural timer runs at constant\r
+      // frequency, irrespective of CPU frequency. According to Generic Timer\r
+      // Ref manual, lower bound of the frequency is in the range of 1-10MHz.\r
+      //\r
+      ASSERT (TICKS_PER_MICRO_SEC);\r
+\r
+ #ifdef MDE_CPU_ARM\r
+      //\r
+      // Only set the frequency for ARMv7. We expect the secure firmware to\r
+      // have already done it.\r
+      // If the security extension is not implemented, set Timer Frequency\r
+      // here.\r
+      //\r
+      if (ArmHasSecurityExtensions ()) {\r
+        ArmGenericTimerSetTimerFreq (PcdGet32 (PcdArmArchTimerFreqInHz));\r
+      }\r
+\r
+ #endif\r
     }\r
 \r
-    // Architectural Timer Frequency must be set in the Secure privileged(if secure extensions are supported) mode.\r
-    // If the reset value (0) is returned just ASSERT.\r
-    TimerFreq = ArmArchTimerGetTimerFreq ();\r
-    ASSERT (TimerFreq);\r
-\r
+    //\r
+    // Architectural Timer Frequency must be set in Secure privileged\r
+    // mode (if secure extension is supported).\r
+    // If the reset value (0) is returned, just ASSERT.\r
+    //\r
+    ASSERT (ArmGenericTimerGetTimerFreq () != 0);\r
   } else {\r
-    DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, Hence cann't use this library \n"));\r
+    DEBUG ((DEBUG_ERROR, "ARM Architectural Timer is not available in the CPU, hence this library cannot be used.\n"));\r
     ASSERT (0);\r
   }\r
 \r
   return RETURN_SUCCESS;\r
 }\r
 \r
+/**\r
+  A local utility function that returns the PCD value, if specified.\r
+  Otherwise it defaults to ArmGenericTimerGetTimerFreq.\r
+\r
+  @return The timer frequency.\r
+\r
+**/\r
+STATIC\r
+UINTN\r
+EFIAPI\r
+GetPlatformTimerFreq (\r
+  )\r
+{\r
+  UINTN  TimerFreq;\r
+\r
+  TimerFreq = PcdGet32 (PcdArmArchTimerFreqInHz);\r
+  if (TimerFreq == 0) {\r
+    TimerFreq = ArmGenericTimerGetTimerFreq ();\r
+  }\r
+\r
+  return TimerFreq;\r
+}\r
 \r
 /**\r
   Stalls the CPU for the number of microseconds specified by MicroSeconds.\r
 \r
   @param  MicroSeconds  The minimum number of microseconds to delay.\r
 \r
-  @return The value of MicroSeconds inputted.\r
+  @return The value of MicroSeconds input.\r
 \r
 **/\r
 UINTN\r
 EFIAPI\r
 MicroSecondDelay (\r
-  IN      UINTN                     MicroSeconds\r
+  IN      UINTN  MicroSeconds\r
   )\r
 {\r
-  UINT64 TimerTicks64;\r
-  UINT64 SystemCounterVal;\r
-\r
-  // Calculate counter ticks that can represent requsted delay\r
-  TimerTicks64 = MultU64x32 (MicroSeconds, TICKS_PER_MICRO_SEC);\r
+  UINT64  TimerTicks64;\r
+  UINT64  SystemCounterVal;\r
+\r
+  // Calculate counter ticks that represent requested delay:\r
+  //  = MicroSeconds x TICKS_PER_MICRO_SEC\r
+  //  = MicroSeconds x Frequency.10^-6\r
+  TimerTicks64 = DivU64x32 (\r
+                   MULT_U64_X_N (\r
+                     MicroSeconds,\r
+                     GetPlatformTimerFreq ()\r
+                     ),\r
+                   1000000U\r
+                   );\r
 \r
   // Read System Counter value\r
-  SystemCounterVal = ArmArchTimerGetSystemCount ();\r
+  SystemCounterVal = ArmGenericTimerGetSystemCount ();\r
 \r
   TimerTicks64 += SystemCounterVal;\r
 \r
-  // Wait until delay count is expired.\r
+  // Wait until delay count expires.\r
   while (SystemCounterVal < TimerTicks64) {\r
-    SystemCounterVal = ArmArchTimerGetSystemCount ();\r
+    SystemCounterVal = ArmGenericTimerGetSystemCount ();\r
   }\r
 \r
   return MicroSeconds;\r
 }\r
 \r
-\r
 /**\r
   Stalls the CPU for at least the given number of nanoseconds.\r
 \r
@@ -112,13 +154,13 @@ MicroSecondDelay (
 UINTN\r
 EFIAPI\r
 NanoSecondDelay (\r
-  IN  UINTN NanoSeconds\r
+  IN  UINTN  NanoSeconds\r
   )\r
 {\r
   UINTN  MicroSeconds;\r
 \r
   // Round up to 1us Tick Number\r
-  MicroSeconds = NanoSeconds / 1000;\r
+  MicroSeconds  = NanoSeconds / 1000;\r
   MicroSeconds += ((NanoSeconds % 1000) == 0) ? 0 : 1;\r
 \r
   MicroSecondDelay (MicroSeconds);\r
@@ -144,7 +186,7 @@ GetPerformanceCounter (
   )\r
 {\r
   // Just return the value of system count\r
-  return ArmArchTimerGetSystemCount ();\r
+  return ArmGenericTimerGetSystemCount ();\r
 }\r
 \r
 /**\r
@@ -173,19 +215,70 @@ GetPerformanceCounter (
 UINT64\r
 EFIAPI\r
 GetPerformanceCounterProperties (\r
-  OUT      UINT64                    *StartValue,  OPTIONAL\r
-  OUT      UINT64                    *EndValue     OPTIONAL\r
+  OUT      UINT64  *StartValue   OPTIONAL,\r
+  OUT      UINT64  *EndValue     OPTIONAL\r
   )\r
 {\r
   if (StartValue != NULL) {\r
-    // Timer starts with the reload value\r
-    *StartValue = (UINT64)0ULL ;\r
+    // Timer starts at 0\r
+    *StartValue = (UINT64)0ULL;\r
   }\r
 \r
   if (EndValue != NULL) {\r
-    // Timer counts down to 0x0\r
-    *EndValue = 0xFFFFFFFFFFFFFFFF;;\r
+    // Timer counts up.\r
+    *EndValue = 0xFFFFFFFFFFFFFFFFUL;\r
   }\r
 \r
-  return (UINT64)ArmArchTimerGetTimerFreq ();\r
+  return (UINT64)ArmGenericTimerGetTimerFreq ();\r
+}\r
+\r
+/**\r
+  Converts elapsed ticks of performance counter to time in nanoseconds.\r
+\r
+  This function converts the elapsed ticks of running performance counter to\r
+  time value in unit of nanoseconds.\r
+\r
+  @param  Ticks     The number of elapsed ticks of running performance counter.\r
+\r
+  @return The elapsed time in nanoseconds.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetTimeInNanoSecond (\r
+  IN      UINT64  Ticks\r
+  )\r
+{\r
+  UINT64  NanoSeconds;\r
+  UINT32  Remainder;\r
+  UINT32  TimerFreq;\r
+\r
+  TimerFreq = GetPlatformTimerFreq ();\r
+  //\r
+  //          Ticks\r
+  // Time = --------- x 1,000,000,000\r
+  //        Frequency\r
+  //\r
+  NanoSeconds = MULT_U64_X_N (\r
+                  DivU64x32Remainder (\r
+                    Ticks,\r
+                    TimerFreq,\r
+                    &Remainder\r
+                    ),\r
+                  1000000000U\r
+                  );\r
+\r
+  //\r
+  // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000)\r
+  // will not overflow 64-bit.\r
+  //\r
+  NanoSeconds += DivU64x32 (\r
+                   MULT_U64_X_N (\r
+                     (UINT64)Remainder,\r
+                     1000000000U\r
+                     ),\r
+                   TimerFreq\r
+                   );\r
+\r
+  return NanoSeconds;\r
 }\r