/** @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
// 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
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
}\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
\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
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
\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
)\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