--- /dev/null
+/** @file\r
+ TimerLib for ARM EB. Hardcoded to 100ns period\r
+\r
+ This library assume the following initialization, usually done in SEC. \r
+\r
+ // configure SP810 to use 1MHz clock and disable\r
+ MmioAndThenOr32 (EB_SP810_CTRL_BASE + SP810_SYS_CTRL_REG, ~SP810_SYS_CTRL_TIMER2_EN, SP810_SYS_CTRL_TIMER2_TIMCLK);\r
+ // Enable\r
+ MmioOr32 (EB_SP810_CTRL_BASE + SP810_SYS_CTRL_REG, SP810_SYS_CTRL_TIMER2_EN);\r
+\r
+ // configure timer 2 for one shot operation, 32 bits, no prescaler, and interrupt disabled\r
+ MmioOr32 (EB_SP804_TIMER2_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ONESHOT | SP804_TIMER_CTRL_32BIT | SP804_PRESCALE_DIV_1);\r
+\r
+ // preload the timer count register\r
+ MmioWrite32 (EB_SP804_TIMER2_BASE + SP804_TIMER_LOAD_REG, 1);\r
+\r
+ // enable the timer\r
+ MmioOr32 (EB_SP804_TIMER2_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ENABLE);\r
+\r
+\r
+ Copyright (c) 2008 - 2010, Apple Inc. 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
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\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
+\r
+**/\r
+\r
+#include <Base.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IoLib.h>\r
+\r
+#include <ArmEb/ArmEb.h>\r
+\r
+\r
+/**\r
+ Stalls the CPU for at least the given number of microseconds.\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
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+MicroSecondDelay (\r
+ IN UINTN MicroSeconds\r
+ )\r
+{\r
+ UINT64 NanoSeconds;\r
+ \r
+ NanoSeconds = MultU64x32 (MicroSeconds, 1000);\r
+\r
+ while (NanoSeconds > (UINTN)-1) { \r
+ NanoSecondDelay((UINTN)-1);\r
+ NanoSeconds -= (UINTN)-1;\r
+ }\r
+\r
+ NanoSecondDelay (NanoSeconds);\r
+\r
+ return MicroSeconds;\r
+}\r
+\r
+/**\r
+ Stalls the CPU for at least the given number of nanoseconds.\r
+\r
+ Stalls the CPU for the number of nanoseconds specified by NanoSeconds.\r
+\r
+ @param NanoSeconds The minimum number of nanoseconds to delay.\r
+\r
+ @return The value of NanoSeconds inputted.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+NanoSecondDelay (\r
+ IN UINTN NanoSeconds\r
+ )\r
+{\r
+ UINT32 TickNumber;\r
+\r
+ if (NanoSeconds == 0) {\r
+ return NanoSeconds;\r
+ }\r
+\r
+ // Round up to 100ns Tick Number\r
+ TickNumber = (UINT32)NanoSeconds / 100;\r
+ TickNumber += ((UINT32)NanoSeconds % 100) == 0 ? 0 : 1;\r
+\r
+ // load the timer count register\r
+ MmioWrite32 (EB_SP804_TIMER2_BASE + SP804_TIMER_LOAD_REG, TickNumber);\r
+\r
+ while (MmioRead32 (EB_SP804_TIMER2_BASE + SP804_TIMER_CURRENT_REG) > 0) {\r
+ ;\r
+ } \r
+ \r
+ return NanoSeconds;\r
+}\r
+\r
+/**\r
+ Retrieves the current value of a 64-bit free running performance counter.\r
+\r
+ The counter can either count up by 1 or count down by 1. If the physical\r
+ performance counter counts by a larger increment, then the counter values\r
+ must be translated. The properties of the counter can be retrieved from\r
+ GetPerformanceCounterProperties().\r
+\r
+ @return The current value of the free running performance counter.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetPerformanceCounter (\r
+ VOID\r
+ )\r
+{ \r
+ // Free running 64-bit/32-bit counter is needed here.\r
+ // Don't think we need this to boot, just to do performance profile\r
+ ASSERT (FALSE);\r
+ return (UINT64)0ULL;\r
+}\r
+\r
+\r
+/**\r
+ Retrieves the 64-bit frequency in Hz and the range of performance counter\r
+ values.\r
+\r
+ If StartValue is not NULL, then the value that the performance counter starts\r
+ with immediately after is it rolls over is returned in StartValue. If\r
+ EndValue is not NULL, then the value that the performance counter end with\r
+ immediately before it rolls over is returned in EndValue. The 64-bit\r
+ frequency of the performance counter in Hz is always returned. If StartValue\r
+ is less than EndValue, then the performance counter counts up. If StartValue\r
+ is greater than EndValue, then the performance counter counts down. For\r
+ example, a 64-bit free running counter that counts up would have a StartValue\r
+ of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter\r
+ that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.\r
+\r
+ @param StartValue The value the performance counter starts with when it\r
+ rolls over.\r
+ @param EndValue The value that the performance counter ends with before\r
+ it rolls over.\r
+\r
+ @return The frequency in Hz.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetPerformanceCounterProperties (\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
+ }\r
+ \r
+ if (EndValue != NULL) {\r
+ // Timer counts up to 0xFFFFFFFF\r
+ *EndValue = 0xFFFFFFFF;\r
+ }\r
+ \r
+ return 100;\r
+}\r
+\r
+\r