]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c
UefiCpuPkg/CpuMpPei: Correct BIST PPI logic.
[mirror_edk2.git] / ArmPkg / Library / ArmArchTimerLib / ArmArchTimerLib.c
index 4361905e143f7963cd64e2a8d35abcb7688fa91b..b81293c5cfde0234a56abed42ece062d9dd6fab7 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Generic ARM implementation of TimerLib.h\r
 \r
-  Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
+  Copyright (c) 2011-2016, 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
@@ -42,7 +42,6 @@ TimerConstructor (
   // Check if the ARM Generic Timer Extension is implemented.\r
   //\r
   if (ArmIsArchTimerImplemented ()) {\r
-    UINTN TimerFreq;\r
 \r
     //\r
     // Check if Architectural Timer frequency is pre-determined by the platform\r
@@ -51,7 +50,7 @@ TimerConstructor (
     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 General Timer\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
@@ -70,14 +69,14 @@ TimerConstructor (
     }\r
 \r
     //\r
-    // Architectural Timer Frequency must be set in the Secure privileged\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
-    TimerFreq = ArmGenericTimerGetTimerFreq ();\r
-    ASSERT (TimerFreq != 0);\r
+    ASSERT (ArmGenericTimerGetTimerFreq () != 0);\r
+\r
   } else {\r
-    DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, hence this library can not be used.\n"));\r
+    DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, hence this library cannot be used.\n"));\r
     ASSERT (0);\r
   }\r
 \r
@@ -112,7 +111,7 @@ GetPlatformTimerFreq (
 \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
@@ -124,7 +123,7 @@ MicroSecondDelay (
   UINT64 TimerTicks64;\r
   UINT64 SystemCounterVal;\r
 \r
-  // Calculate counter ticks that can represent requested delay:\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
@@ -140,7 +139,7 @@ MicroSecondDelay (
 \r
   TimerTicks64 += SystemCounterVal;\r
 \r
-  // Wait until delay count is expired.\r
+  // Wait until delay count expires.\r
   while (SystemCounterVal < TimerTicks64) {\r
     SystemCounterVal = ArmGenericTimerGetSystemCount ();\r
   }\r
@@ -231,14 +230,63 @@ GetPerformanceCounterProperties (
   )\r
 {\r
   if (StartValue != NULL) {\r
-    // Timer starts with the reload value\r
+    // Timer starts at 0\r
     *StartValue = (UINT64)0ULL ;\r
   }\r
 \r
   if (EndValue != NULL) {\r
-    // Timer counts down to 0x0\r
+    // Timer counts up.\r
     *EndValue = 0xFFFFFFFFFFFFFFFFUL;\r
   }\r
 \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 = MultU64xN (\r
+                  DivU64x32Remainder (\r
+                    Ticks,\r
+                    TimerFreq,\r
+                    &Remainder),\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
+                   MultU64xN (\r
+                     (UINT64) Remainder,\r
+                     1000000000U),\r
+                   TimerFreq\r
+                   );\r
+\r
+  return NanoSeconds;\r
+}\r