]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPkg: Add ARM Architectural Timer support
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 27 Sep 2011 16:35:16 +0000 (16:35 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 27 Sep 2011 16:35:16 +0000 (16:35 +0000)
ARM Architectural Timer support is defined by the ARM Generic Timer Specification.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12455 6f19259b-4bc3-4df7-8a09-765794883524

15 files changed:
ArmPkg/ArmPkg.dec
ArmPkg/Drivers/TimerDxe/TimerDxe.c [new file with mode: 0644]
ArmPkg/Drivers/TimerDxe/TimerDxe.inf [new file with mode: 0644]
ArmPkg/Include/Chipset/ArmV7.h
ArmPkg/Include/Chipset/ArmV7ArchTimer.h [new file with mode: 0644]
ArmPkg/Include/Library/ArmLib.h
ArmPkg/Include/Library/ArmV7ArchTimerLib.h [new file with mode: 0644]
ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c [new file with mode: 0644]
ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf [new file with mode: 0644]
ArmPkg/Library/ArmLib/ArmV7/ArmV7ArchTimer.c [new file with mode: 0644]
ArmPkg/Library/ArmLib/ArmV7/ArmV7ArchTimerSupport.S [new file with mode: 0644]
ArmPkg/Library/ArmLib/ArmV7/ArmV7ArchTimerSupport.asm [new file with mode: 0644]
ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf
ArmPkg/Library/ArmLib/ArmV7/ArmV7LibPrePi.inf
ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf

index 710e2151988f8d6db485a1f986b7e189b74ec6bc..c9bf606666ae297e7ca0a8edc647ed4861ddbee2 100644 (file)
   # The Linux ATAGs are expected to be under 0x4000 (16KB) from the beginning of the System Memory\r
   gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset|0x4000|UINT32|0x00000020\r
 \r
+  #\r
+  # ARM Architectural Timer\r
+  #\r
+  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|0|UINT32|0x00000034\r
+  # ARM Architectural Timer Interrupt(GIC PPI) number\r
+  gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|29|UINT32|0x00000035  \r
+  gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|30|UINT32|0x00000036\r
diff --git a/ArmPkg/Drivers/TimerDxe/TimerDxe.c b/ArmPkg/Drivers/TimerDxe/TimerDxe.c
new file mode 100644 (file)
index 0000000..3cde15c
--- /dev/null
@@ -0,0 +1,379 @@
+/** @file
+  Timer Architecture Protocol driver of the ARM flavor
+
+  Copyright (c) 2011 ARM Ltd. All rights reserved.<BR>
+  
+  This program and the accompanying materials                          
+  are licensed and made available under the terms and conditions of the BSD License         
+  which accompanies this distribution.  The full text of the license may be found at        
+  http://opensource.org/licenses/bsd-license.php                                            
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/ArmV7ArchTimerLib.h>
+
+#include <Protocol/Timer.h>
+#include <Protocol/HardwareInterrupt.h>
+
+// The notification function to call on every timer interrupt.
+EFI_TIMER_NOTIFY      mTimerNotifyFunction     = (EFI_TIMER_NOTIFY)NULL;
+EFI_EVENT             EfiExitBootServicesEvent = (EFI_EVENT)NULL;
+
+// The current period of the timer interrupt
+UINT64 mTimerPeriod = 0;
+
+// Cached copy of the Hardware Interrupt protocol instance
+EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
+
+/**
+  This function registers the handler NotifyFunction so it is called every time 
+  the timer interrupt fires.  It also passes the amount of time since the last 
+  handler call to the NotifyFunction.  If NotifyFunction is NULL, then the 
+  handler is unregistered.  If the handler is registered, then EFI_SUCCESS is 
+  returned.  If the CPU does not support registering a timer interrupt handler, 
+  then EFI_UNSUPPORTED is returned.  If an attempt is made to register a handler 
+  when a handler is already registered, then EFI_ALREADY_STARTED is returned.  
+  If an attempt is made to unregister a handler when a handler is not registered, 
+  then EFI_INVALID_PARAMETER is returned.  If an error occurs attempting to 
+  register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR 
+  is returned.
+
+  @param  This             The EFI_TIMER_ARCH_PROTOCOL instance.
+  @param  NotifyFunction   The function to call when a timer interrupt fires. This
+                           function executes at TPL_HIGH_LEVEL. The DXE Core will
+                           register a handler for the timer interrupt, so it can know
+                           how much time has passed. This information is used to
+                           signal timer based events. NULL will unregister the handler.
+  @retval EFI_SUCCESS           The timer handler was registered.
+  @retval EFI_UNSUPPORTED       The platform does not support timer interrupts.
+  @retval EFI_ALREADY_STARTED   NotifyFunction is not NULL, and a handler is already
+                                registered.
+  @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
+                                previously registered.
+  @retval EFI_DEVICE_ERROR      The timer handler could not be registered.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+  IN EFI_TIMER_ARCH_PROTOCOL  *This,
+  IN EFI_TIMER_NOTIFY         NotifyFunction
+  )
+{
+  if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  mTimerNotifyFunction = NotifyFunction;
+
+  return EFI_SUCCESS;
+}
+
+/**
+    Disable the timer
+**/
+VOID
+EFIAPI
+ExitBootServicesEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  ArmArchTimerDisableTimer ();
+}
+
+/**
+
+  This function adjusts the period of timer interrupts to the value specified 
+  by TimerPeriod.  If the timer period is updated, then the selected timer 
+  period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned.  If 
+  the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.  
+  If an error occurs while attempting to update the timer period, then the 
+  timer hardware will be put back in its state prior to this call, and 
+  EFI_DEVICE_ERROR is returned.  If TimerPeriod is 0, then the timer interrupt 
+  is disabled.  This is not the same as disabling the CPU's interrupts.  
+  Instead, it must either turn off the timer hardware, or it must adjust the 
+  interrupt controller so that a CPU interrupt is not generated when the timer 
+  interrupt fires. 
+
+  @param  This             The EFI_TIMER_ARCH_PROTOCOL instance.
+  @param  TimerPeriod      The rate to program the timer interrupt in 100 nS units. If
+                           the timer hardware is not programmable, then EFI_UNSUPPORTED is
+                           returned. If the timer is programmable, then the timer period
+                           will be rounded up to the nearest timer period that is supported
+                           by the timer hardware. If TimerPeriod is set to 0, then the
+                           timer interrupts will be disabled.
+
+
+  @retval EFI_SUCCESS           The timer period was changed.
+  @retval EFI_UNSUPPORTED       The platform cannot change the period of the timer interrupt.
+  @retval EFI_DEVICE_ERROR      The timer period could not be changed due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+  IN EFI_TIMER_ARCH_PROTOCOL  *This,
+  IN UINT64                   TimerPeriod
+  )
+{
+  UINT64      TimerTicks;
+  
+  // always disable the timer
+  ArmArchTimerDisableTimer ();
+
+  if (TimerPeriod != 0) {
+    // Convert TimerPeriod to micro sec units
+    TimerTicks = DivU64x32 (TimerPeriod, 10);
+
+    TimerTicks = MultU64x32 (TimerPeriod, (PcdGet32(PcdArmArchTimerFreqInHz)/1000000));
+
+    ArmArchTimerSetTimerVal((UINTN)TimerTicks);
+
+    // Enable the timer
+    ArmArchTimerEnableTimer ();
+  }
+
+  // Save the new timer period
+  mTimerPeriod = TimerPeriod;
+  return EFI_SUCCESS;
+}
+
+/**
+  This function retrieves the period of timer interrupts in 100 ns units, 
+  returns that value in TimerPeriod, and returns EFI_SUCCESS.  If TimerPeriod 
+  is NULL, then EFI_INVALID_PARAMETER is returned.  If a TimerPeriod of 0 is 
+  returned, then the timer is currently disabled.
+
+  @param  This             The EFI_TIMER_ARCH_PROTOCOL instance.
+  @param  TimerPeriod      A pointer to the timer period to retrieve in 100 ns units. If
+                           0 is returned, then the timer is currently disabled.
+
+
+  @retval EFI_SUCCESS           The timer period was returned in TimerPeriod.
+  @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+  IN EFI_TIMER_ARCH_PROTOCOL   *This,
+  OUT UINT64                   *TimerPeriod
+  )
+{
+  if (TimerPeriod == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *TimerPeriod = mTimerPeriod;
+  return EFI_SUCCESS;
+}
+
+/**
+  This function generates a soft timer interrupt. If the platform does not support soft 
+  timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned. 
+  If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler() 
+  service, then a soft timer interrupt will be generated. If the timer interrupt is 
+  enabled when this service is called, then the registered handler will be invoked. The 
+  registered handler should not be able to distinguish a hardware-generated timer 
+  interrupt from a software-generated timer interrupt.
+
+  @param  This             The EFI_TIMER_ARCH_PROTOCOL instance.
+
+  @retval EFI_SUCCESS           The soft timer interrupt was generated.
+  @retval EFI_UNSUPPORTED       The platform does not support the generation of soft timer interrupts.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+  IN EFI_TIMER_ARCH_PROTOCOL  *This
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Interface structure for the Timer Architectural Protocol.
+
+  @par Protocol Description:
+  This protocol provides the services to initialize a periodic timer
+  interrupt, and to register a handler that is called each time the timer
+  interrupt fires.  It may also provide a service to adjust the rate of the
+  periodic timer interrupt.  When a timer interrupt occurs, the handler is
+  passed the amount of time that has passed since the previous timer
+  interrupt.
+
+  @param RegisterHandler
+  Registers a handler that will be called each time the
+  timer interrupt fires.  TimerPeriod defines the minimum
+  time between timer interrupts, so TimerPeriod will also
+  be the minimum time between calls to the registered
+  handler.
+
+  @param SetTimerPeriod
+  Sets the period of the timer interrupt in 100 nS units.
+  This function is optional, and may return EFI_UNSUPPORTED.
+  If this function is supported, then the timer period will
+  be rounded up to the nearest supported timer period.
+
+
+  @param GetTimerPeriod
+  Retrieves the period of the timer interrupt in 100 nS units.
+
+  @param GenerateSoftInterrupt
+  Generates a soft timer interrupt that simulates the firing of
+  the timer interrupt. This service can be used to invoke the   registered handler if the timer interrupt has been masked for
+  a period of time.
+
+**/
+EFI_TIMER_ARCH_PROTOCOL   gTimer = {
+  TimerDriverRegisterHandler,
+  TimerDriverSetTimerPeriod,
+  TimerDriverGetTimerPeriod,
+  TimerDriverGenerateSoftInterrupt
+};
+
+/**
+
+  C Interrupt Handler called in the interrupt context when Source interrupt is active.
+
+
+  @param Source         Source of the interrupt. Hardware routing off a specific platform defines
+                        what source means.
+
+  @param SystemContext  Pointer to system register context. Mostly used by debuggers and will
+                        update the system context after the return from the interrupt if
+                        modified. Don't change these values unless you know what you are doing
+
+**/
+VOID
+EFIAPI
+TimerInterruptHandler (
+  IN  HARDWARE_INTERRUPT_SOURCE   Source,
+  IN  EFI_SYSTEM_CONTEXT          SystemContext
+  )
+{
+  EFI_TPL      OriginalTPL;
+
+  //
+  // DXE core uses this callback for the EFI timer tick. The DXE core uses locks
+  // that raise to TPL_HIGH and then restore back to current level. Thus we need
+  // to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
+  //
+  OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+  // Check if the timer interrupt is active
+  if ((ArmArchTimerGetTimerCtrlReg () ) & ARM_ARCH_TIMER_ISTATUS) {
+
+    // Signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers
+    gInterrupt->EndOfInterrupt (gInterrupt, Source);
+
+    if (mTimerNotifyFunction) {
+      mTimerNotifyFunction (mTimerPeriod);
+    }
+
+    // Reload the Timer
+    TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod));
+  }
+
+  // Enable timer interrupts
+  gInterrupt->EnableInterruptSource (gInterrupt, Source);
+
+  gBS->RestoreTPL (OriginalTPL);
+}
+
+
+/**
+  Initialize the state information for the Timer Architectural Protocol and
+  the Timer Debug support protocol that allows the debugger to break into a
+  running program.
+
+  @param  ImageHandle   of the loaded driver
+  @param  SystemTable   Pointer to the System Table
+
+  @retval EFI_SUCCESS           Protocol registered
+  @retval EFI_OUT_OF_RESOURCES  Cannot allocate protocol data structure
+  @retval EFI_DEVICE_ERROR      Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+TimerInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_HANDLE  Handle = NULL;
+  EFI_STATUS  Status;
+  UINTN TimerCtrlReg;
+
+  if (ArmIsArchTimerImplemented () == 0) {
+    DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, hence cann't use this Driver \n"));
+    ASSERT (0);
+  }
+
+  // Find the interrupt controller protocol.  ASSERT if not found.
+  Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
+  ASSERT_EFI_ERROR (Status);
+
+  // Disable the timer
+  Status = TimerDriverSetTimerPeriod (&gTimer, 0);
+  ASSERT_EFI_ERROR (Status);
+
+  // Install secure and Non-secure interrupt handlers
+  // Note: Because it is not possible to determine the security state of the
+  // CPU dynamically, we just install interrupt handler for both sec and non-sec
+  // timer PPI
+  Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum), TimerInterruptHandler);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerIntrNum), TimerInterruptHandler);
+  ASSERT_EFI_ERROR (Status);
+
+  // Unmask timer interrupts
+  TimerCtrlReg = ArmArchTimerGetTimerCtrlReg ();
+  TimerCtrlReg &= ~ARM_ARCH_TIMER_IMASK;
+  ArmArchTimerSetTimerCtrlReg (TimerCtrlReg);
+
+  // Set up default timer
+  Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod)); // TIMER_DEFAULT_PERIOD
+  ASSERT_EFI_ERROR (Status);
+
+  // Install the Timer Architectural Protocol onto a new handle
+  Status = gBS->InstallMultipleProtocolInterfaces(
+                  &Handle,
+                  &gEfiTimerArchProtocolGuid,      &gTimer,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR(Status);
+
+  // enable Secure timer interrupts
+  Status = gInterrupt->EnableInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum));
+
+  // enable NonSecure timer interrupts
+  Status = gInterrupt->EnableInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerIntrNum));
+
+  // Register for an ExitBootServicesEvent
+  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/ArmPkg/Drivers/TimerDxe/TimerDxe.inf b/ArmPkg/Drivers/TimerDxe/TimerDxe.inf
new file mode 100644 (file)
index 0000000..2f807a8
--- /dev/null
@@ -0,0 +1,59 @@
+#/** @file
+#  
+#    Component discription file for Timer DXE module
+#  
+#  Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#  
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ArmTimerDxe
+  FILE_GUID                      = 49ea041e-6752-42ca-b0b1-7344fe2546b7 
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = TimerInitialize
+
+[Sources.common]
+  TimerDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  ArmLib
+  BaseLib
+  UefiRuntimeServicesTableLib
+  UefiLib
+  UefiBootServicesTableLib
+  BaseMemoryLib
+  DebugLib
+  UefiDriverEntryPoint
+  IoLib  
+
+[Guids]
+
+[Protocols]
+  gEfiTimerArchProtocolGuid  
+  gHardwareInterruptProtocolGuid
+
+[Pcd.common]
+  gEmbeddedTokenSpaceGuid.PcdTimerPeriod
+  gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum  
+  gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
+  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz  
+
+[Depex]
+  gHardwareInterruptProtocolGuid
+  
\ No newline at end of file
index 909686ce361abda8f42cf2a53fb341691b2c0a47..bb306a5f48c515009faaefb7babbd47027d723e3 100644 (file)
@@ -17,6 +17,7 @@
 #define __ARM_V7_H__\r
 \r
 #include <Chipset/ArmV7Mmu.h>\r
+#include <Chipset/ArmV7ArchTimer.h>\r
 \r
 // Domain Access Control Register\r
 #define DOMAIN_ACCESS_CONTROL_MASK(a)     (3UL << (2 * (a)))\r
@@ -80,6 +81,12 @@ ArmWriteTpidrurw (
   UINTN Value\r
   );\r
 \r
+UINTN\r
+EFIAPI\r
+ArmIsArchTimerImplemented (\r
+  VOID\r
+  );\r
+\r
 UINTN\r
 EFIAPI\r
 ArmReadIdPfr1 (\r
diff --git a/ArmPkg/Include/Chipset/ArmV7ArchTimer.h b/ArmPkg/Include/Chipset/ArmV7ArchTimer.h
new file mode 100644 (file)
index 0000000..734c885
--- /dev/null
@@ -0,0 +1,138 @@
+/** @file\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
+*\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
+#ifndef __ARMV7_ARCH_TIMER_H_\r
+#define __ARMV7_ARCH_TIMER_H_\r
+\r
+UINTN\r
+EFIAPI\r
+ArmReadCntFrq (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+ArmWriteCntFrq (\r
+  UINTN   FreqInHz\r
+  );\r
+\r
+UINT64\r
+EFIAPI\r
+ArmReadCntPct (\r
+  VOID\r
+  );\r
+\r
+UINTN\r
+EFIAPI\r
+ArmReadCntkCtl (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+ArmWriteCntkCtl (\r
+  UINTN   Val\r
+  );\r
+\r
+UINTN\r
+EFIAPI\r
+ArmReadCntpTval (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+ArmWriteCntpTval (\r
+  UINTN   Val\r
+  );\r
+\r
+UINTN\r
+EFIAPI\r
+ArmReadCntpCtl (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+ArmWriteCntpCtl (\r
+  UINTN   Val\r
+  );\r
+\r
+UINTN\r
+EFIAPI\r
+ArmReadCntvTval (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+ArmWriteCntvTval (\r
+  UINTN   Val\r
+  );\r
+\r
+UINTN\r
+EFIAPI\r
+ArmReadCntvCtl (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+ArmWriteCntvCtl (\r
+  UINTN   Val\r
+  );\r
+\r
+UINT64\r
+EFIAPI\r
+ArmReadCntvCt (\r
+  VOID\r
+  );\r
+\r
+UINT64\r
+EFIAPI\r
+ArmReadCntpCval (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+ArmWriteCntpCval (\r
+  UINT64   Val\r
+  );\r
+\r
+UINT64\r
+EFIAPI\r
+ArmReadCntvCval (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+ArmWriteCntvCval (\r
+  UINT64   Val\r
+  );\r
+\r
+UINT64\r
+EFIAPI\r
+ArmReadCntvOff (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+ArmWriteCntvOff (\r
+  UINT64   Val\r
+  );\r
+\r
+#endif\r
index e88633e1e93194c721d3a8e7dd5eee80fbddf4ed..3ce687244fe69a95b7a1b11d2303676cea9fdef4 100644 (file)
@@ -167,7 +167,7 @@ Cp15CacheInfo (
 
 BOOLEAN
 EFIAPI
-ArmIsMPCore (
+ArmIsMpCore (
   VOID
   );
 
diff --git a/ArmPkg/Include/Library/ArmV7ArchTimerLib.h b/ArmPkg/Include/Library/ArmV7ArchTimerLib.h
new file mode 100644 (file)
index 0000000..d2f4a46
--- /dev/null
@@ -0,0 +1,115 @@
+/** @file
+
+  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __ARM_V7_ARCH_TIMER_LIB_H__
+#define __ARM_V7_ARCH_TIMER_LIB_H__
+
+#define ARM_ARCH_TIMER_ENABLE           (1 << 0)
+#define ARM_ARCH_TIMER_IMASK            (1 << 1)
+#define ARM_ARCH_TIMER_ISTATUS          (1 << 2)
+
+typedef enum {
+  CntFrq = 0,
+  CntPct,
+  CntkCtl,
+  CntpTval,
+  CntpCtl,
+  CntvTval,
+  CntvCtl,
+  CntvCt,
+  CntpCval,
+  CntvCval,
+  CntvOff,
+  CnthCtl,
+  CnthpTval,
+  CnthpCtl,
+  CnthpCval,
+  RegMaximum
+}ARM_ARCH_TIMER_REGS;
+
+VOID
+EFIAPI
+ArmArchTimerReadReg (
+  IN   ARM_ARCH_TIMER_REGS   Reg,
+  OUT  VOID                  *DstBuf
+  );
+
+VOID
+EFIAPI
+ArmArchTimerWriteReg (
+  IN   ARM_ARCH_TIMER_REGS   Reg,
+  IN   VOID                  *SrcBuf
+  );
+
+VOID
+EFIAPI
+ArmArchTimerEnableTimer (
+  VOID
+  );
+
+VOID
+EFIAPI
+ArmArchTimerDisableTimer (
+  VOID
+  );
+
+VOID
+EFIAPI
+ArmArchTimerSetTimerFreq (
+  IN   UINTN  FreqInHz
+  );
+
+UINTN
+EFIAPI
+ArmArchTimerGetTimerFreq (
+  VOID
+  );
+
+VOID
+EFIAPI
+ArmArchTimerSetTimerVal (
+  IN   UINTN   Val
+  );
+
+UINTN
+EFIAPI
+ArmArchTimerGetTimerVal (
+  VOID
+  );
+
+UINT64
+EFIAPI
+ArmArchTimerGetSystemCount (
+  VOID
+  );
+
+UINTN
+EFIAPI
+ArmArchTimerGetTimerCtrlReg (
+  VOID
+  );
+
+VOID
+EFIAPI
+ArmArchTimerSetTimerCtrlReg (
+  UINTN Val
+  );
+
+VOID
+EFIAPI
+ArmArchTimerSetCompareVal (
+  IN   UINT64   Val
+  );
+
+#endif // __ARM_V7_ARCH_TIMER_LIB_H__
diff --git a/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c b/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c
new file mode 100644 (file)
index 0000000..d6f3f1b
--- /dev/null
@@ -0,0 +1,191 @@
+/** @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
+\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
+\r
+#include <Base.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
+\r
+#define TICKS_PER_MICRO_SEC     (PcdGet32 (PcdArmArchTimerFreqInHz)/1000000U)\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+ArmArchTimerLibConstructor (\r
+  VOID\r
+  )\r
+{\r
+  // Check if the ARM Generic Timer Extension is implemented\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
+\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
+  } else {\r
+    DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, Hence cann't use this library \n"));\r
+    ASSERT (0);\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\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
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+MicroSecondDelay (\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
+\r
+  // Read System Counter value\r
+  SystemCounterVal = ArmArchTimerGetSystemCount ();\r
+\r
+  TimerTicks64 += SystemCounterVal;\r
+\r
+  // Wait until delay count is expired.\r
+  while (SystemCounterVal < TimerTicks64) {\r
+    SystemCounterVal = ArmArchTimerGetSystemCount ();\r
+  }\r
+\r
+  return MicroSeconds;\r
+}\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
+  When the timer frequency is 1MHz, each tick corresponds to 1 microsecond.\r
+  Therefore, the nanosecond delay will be rounded up to the nearest 1 microsecond.\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
+  UINTN  MicroSeconds;\r
+\r
+  // Round up to 1us Tick Number\r
+  MicroSeconds = NanoSeconds / 1000;\r
+  MicroSeconds += ((NanoSeconds % 1000) == 0) ? 0 : 1;\r
+\r
+  MicroSecondDelay (MicroSeconds);\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
+  // Just return the value of system count\r
+  return ArmArchTimerGetSystemCount ();\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 down to 0x0\r
+    *EndValue = 0xFFFFFFFFFFFFFFFF;;\r
+  }\r
+\r
+  return (UINT64)ArmArchTimerGetTimerFreq ();\r
+}\r
diff --git a/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf b/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
new file mode 100644 (file)
index 0000000..87548b4
--- /dev/null
@@ -0,0 +1,46 @@
+#/** @file\r
+#  \r
+#  Copyright (c) 2011, ARM Limited. All rights reserved.<BR>\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
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = ArmArchTimerLib\r
+  FILE_GUID                      = 82da1b44-d2d6-4a7d-bbf0-a0cb67964034\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = TimerLib \r
+  CONSTRUCTOR                    = ArmArchTimerLibConstructor\r
+\r
+[Sources.common]\r
+  ArmArchTimerLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
+  ArmPkg/ArmPkg.dec\r
+  \r
+\r
+[LibraryClasses]\r
+  DebugLib\r
+  IoLib\r
+  ArmLib\r
+  BaseLib    \r
+  \r
+[Protocols]\r
+  \r
+[Guids]\r
\r
+[Pcd]\r
+  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz\r
+\r
+[Depex]\r
+  gEfiCpuArchProtocolGuid\r
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7ArchTimer.c b/ArmPkg/Library/ArmLib/ArmV7/ArmV7ArchTimer.c
new file mode 100644 (file)
index 0000000..1cba12d
--- /dev/null
@@ -0,0 +1,275 @@
+/** @file
+*
+*  Copyright (c) 2011, ARM Limited. All rights reserved.
+*  
+*  This program and the accompanying materials                          
+*  are licensed and made available under the terms and conditions of the BSD License         
+*  which accompanies this distribution.  The full text of the license may be found at        
+*  http://opensource.org/licenses/bsd-license.php                                            
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+*
+**/
+
+#include <Uefi.h> 
+#include <Chipset/ArmV7.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include "ArmV7Lib.h"
+#include "ArmLibPrivate.h"
+#include <Library/ArmV7ArchTimerLib.h>
+
+VOID
+EFIAPI
+ArmArchTimerReadReg (
+    IN   ARM_ARCH_TIMER_REGS   Reg,
+    OUT  VOID                  *DstBuf
+    )
+{
+  // Check if the Generic/Architecture timer is implemented
+  if (ArmIsArchTimerImplemented ()) {
+
+    switch (Reg) {
+
+    case CntFrq:
+      *((UINTN *)DstBuf) = ArmReadCntFrq ();
+      break;
+
+    case CntPct:
+      *((UINT64 *)DstBuf) = ArmReadCntPct ();
+      break;
+
+    case CntkCtl:
+      *((UINTN *)DstBuf) = ArmReadCntkCtl();
+      break;
+
+    case CntpTval:
+      *((UINTN *)DstBuf) = ArmReadCntpTval ();
+      break;
+
+    case CntpCtl:
+      *((UINTN *)DstBuf) = ArmReadCntpCtl ();
+      break;
+
+    case CntvTval:
+      *((UINTN *)DstBuf) = ArmReadCntvTval ();
+      break;
+
+    case CntvCtl:
+      *((UINTN *)DstBuf) = ArmReadCntvCtl ();
+      break;
+
+    case CntvCt:
+      *((UINT64 *)DstBuf) = ArmReadCntvCt ();
+      break;
+
+    case CntpCval:
+      *((UINT64 *)DstBuf) = ArmReadCntpCval ();
+      break;
+
+    case CntvCval:
+      *((UINT64 *)DstBuf) = ArmReadCntvCval ();
+      break;
+
+    case CntvOff:
+      *((UINT64 *)DstBuf) = ArmReadCntvOff ();
+      break;
+
+    case CnthCtl:
+    case CnthpTval:
+    case CnthpCtl:
+    case CnthpCval:
+    DEBUG ((EFI_D_ERROR, "The register is related to Hyperviser Mode. Can't perform requested operation\n "));
+      break;
+
+    default:
+      DEBUG ((EFI_D_ERROR, "Unknown ARM Generic Timer register %x. \n ", Reg));
+    }
+  } else {
+    DEBUG ((EFI_D_ERROR, "Attempt to read ARM Generic Timer registers. But ARM Generic Timer extension is not implemented \n "));
+    ASSERT (0);
+  }
+}
+
+VOID
+EFIAPI
+ArmArchTimerWriteReg (
+    IN   ARM_ARCH_TIMER_REGS   Reg,
+    IN   VOID                  *SrcBuf
+    )
+{
+  // Check if the Generic/Architecture timer is implemented
+  if (ArmIsArchTimerImplemented ()) {
+
+    switch (Reg) {
+
+    case CntFrq:
+      ArmWriteCntFrq (*((UINTN *)SrcBuf));
+      break;
+
+    case CntPct:
+      DEBUG ((EFI_D_ERROR, "Can't write to Read Only Register: CNTPCT \n"));
+      break;
+
+    case CntkCtl:
+      ArmWriteCntkCtl (*((UINTN *)SrcBuf));
+      break;
+
+    case CntpTval:
+      ArmWriteCntpTval (*((UINTN *)SrcBuf));
+      break;
+
+    case CntpCtl:
+      ArmWriteCntpCtl (*((UINTN *)SrcBuf));
+      break;
+
+    case CntvTval:
+      ArmWriteCntvTval (*((UINTN *)SrcBuf));
+      break;
+
+    case CntvCtl:
+      ArmWriteCntvCtl (*((UINTN *)SrcBuf));
+      break;
+
+    case CntvCt:
+      DEBUG ((EFI_D_ERROR, "Can't write to Read Only Register: CNTVCT \n"));
+      break;
+
+    case CntpCval:
+      ArmWriteCntpCval (*((UINT64 *)SrcBuf) );
+      break;
+
+    case CntvCval:
+      ArmWriteCntvCval (*((UINT64 *)SrcBuf) );
+      break;
+
+    case CntvOff:
+      ArmWriteCntvOff (*((UINT64 *)SrcBuf));
+      break;
+
+    case CnthCtl:
+    case CnthpTval:
+    case CnthpCtl:
+    case CnthpCval:
+      DEBUG ((EFI_D_ERROR, "The register is related to Hypervisor Mode. Can't perform requested operation\n "));
+      break;
+
+    default:
+      DEBUG ((EFI_D_ERROR, "Unknown ARM Generic Timer register %x. \n ", Reg));
+    }
+  } else {
+    DEBUG ((EFI_D_ERROR, "Attempt to write to ARM Generic Timer registers. But ARM Generic Timer extension is not implemented \n "));
+    ASSERT (0);
+  }
+}
+
+VOID
+EFIAPI
+ArmArchTimerEnableTimer (
+    VOID
+    )
+{
+  UINTN TimerCtrlReg;
+
+  ArmArchTimerReadReg (CntpCtl, (VOID *)&TimerCtrlReg);
+  TimerCtrlReg |= ARM_ARCH_TIMER_ENABLE;
+  ArmArchTimerWriteReg (CntpCtl, (VOID *)&TimerCtrlReg);
+}
+
+VOID
+EFIAPI
+ArmArchTimerDisableTimer (
+    VOID
+    )
+{
+  UINTN TimerCtrlReg;
+
+  ArmArchTimerReadReg (CntpCtl, (VOID *)&TimerCtrlReg);
+  TimerCtrlReg &= ~ARM_ARCH_TIMER_ENABLE;
+  ArmArchTimerWriteReg (CntpCtl, (VOID *)&TimerCtrlReg);
+}
+
+VOID
+EFIAPI
+ArmArchTimerSetTimerFreq (
+    IN   UINTN  FreqInHz
+    )
+{
+  ArmArchTimerWriteReg (CntFrq, (VOID *)&FreqInHz);
+}
+
+UINTN
+EFIAPI
+ArmArchTimerGetTimerFreq (
+    VOID
+    )
+{
+  UINTN ArchTimerFreq = 0;
+  ArmArchTimerReadReg (CntFrq, (VOID *)&ArchTimerFreq);
+  return ArchTimerFreq;
+}
+
+UINTN
+EFIAPI
+ArmArchTimerGetTimerVal (
+    VOID
+    )
+{
+  UINTN ArchTimerVal;
+  ArmArchTimerReadReg (CntpTval, (VOID *)&ArchTimerVal);
+  return ArchTimerVal;
+}
+
+
+VOID
+EFIAPI
+ArmArchTimerSetTimerVal (
+    IN   UINTN   Val
+    )
+{
+  ArmArchTimerWriteReg (CntpTval, (VOID *)&Val);
+}
+
+UINT64
+EFIAPI
+ArmArchTimerGetSystemCount (
+    VOID
+    )
+{
+  UINT64 SystemCount;
+  ArmArchTimerReadReg (CntPct, (VOID *)&SystemCount);
+  return SystemCount;
+}
+
+UINTN
+EFIAPI
+ArmArchTimerGetTimerCtrlReg (
+    VOID
+    )
+{
+  UINTN  Val;
+  ArmArchTimerReadReg (CntpCtl, (VOID *)&Val);
+  return Val;
+}
+
+VOID
+EFIAPI
+ArmArchTimerSetTimerCtrlReg (
+    UINTN Val
+    )
+{
+  ArmArchTimerWriteReg (CntpCtl, (VOID *)&Val);
+}
+
+VOID
+EFIAPI
+ArmArchTimerSetCompareVal (
+    IN   UINT64   Val
+    )
+{
+  ArmArchTimerWriteReg (CntpCval, (VOID *)&Val);
+}
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7ArchTimerSupport.S b/ArmPkg/Library/ArmLib/ArmV7/ArmV7ArchTimerSupport.S
new file mode 100644 (file)
index 0000000..531d8fd
--- /dev/null
@@ -0,0 +1,119 @@
+#------------------------------------------------------------------------------ \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
+#\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
+.text\r
+.align 2\r
+\r
+GCC_ASM_EXPORT (ArmReadCntFrq)\r
+GCC_ASM_EXPORT (ArmWriteCntFrq)\r
+GCC_ASM_EXPORT (ArmReadCntPct)\r
+GCC_ASM_EXPORT (ArmReadCntkCtl)\r
+GCC_ASM_EXPORT (ArmWriteCntkCtl)\r
+GCC_ASM_EXPORT (ArmReadCntpTval)\r
+GCC_ASM_EXPORT (ArmWriteCntpTval)\r
+GCC_ASM_EXPORT (ArmReadCntpCtl)\r
+GCC_ASM_EXPORT (ArmWriteCntpCtl)\r
+GCC_ASM_EXPORT (ArmReadCntvTval)\r
+GCC_ASM_EXPORT (ArmWriteCntvTval)\r
+GCC_ASM_EXPORT (ArmReadCntvCtl)\r
+GCC_ASM_EXPORT (ArmWriteCntvCtl)\r
+GCC_ASM_EXPORT (ArmReadCntvCt)\r
+GCC_ASM_EXPORT (ArmReadCntpCval)\r
+GCC_ASM_EXPORT (ArmWriteCntpCval)\r
+GCC_ASM_EXPORT (ArmReadCntvCval)\r
+GCC_ASM_EXPORT (ArmWriteCntvCval)\r
+GCC_ASM_EXPORT (ArmReadCntvOff)\r
+GCC_ASM_EXPORT (ArmWriteCntvOff)\r
+\r
+ASM_PFX(ArmReadCntFrq):\r
+  mrc    p15, 0, r0, c14, c0, 0    @ Read CNTFRQ\r
+  bx     lr\r
+\r
+ASM_PFX(ArmWriteCntFrq):\r
+  mcr    p15, 0, r0, c14, c0, 0    @ Write to CNTFRQ\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntPct):\r
+  mrrc   p15, 0, r0, r1, c14       @ Read CNTPT (Physical counter register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntkCtl):\r
+  mrc    p15, 0, r0, c14, c1, 0    @ Read CNTK_CTL (Timer PL1 Control Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmWriteCntkCtl):\r
+  mcr    p15, 0, r0, c14, c1, 0    @ Write to CNTK_CTL (Timer PL1 Control Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntpTval):\r
+  mrc    p15, 0, r0, c14, c2, 0    @ Read CNTP_TVAL (PL1 physical timer value register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmWriteCntpTval):\r
+  mcr    p15, 0, r0, c14, c2, 0    @ Write to CNTP_TVAL (PL1 physical timer value register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntpCtl):\r
+  mrc    p15, 0, r0, c14, c2, 1    @ Read CNTP_CTL (PL1 Physical Timer Control Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmWriteCntpCtl):\r
+  mcr    p15, 0, r0, c14, c2, 1    @ Write to  CNTP_CTL (PL1 Physical Timer Control Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntvTval):\r
+  mrc    p15, 0, r0, c14, c3, 0    @ Read CNTV_TVAL (Virtual Timer Value register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmWriteCntvTval):\r
+  mcr    p15, 0, r0, c14, c3, 0    @ Write to CNTV_TVAL (Virtual Timer Value register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntvCtl):\r
+  mrc    p15, 0, r0, c14, c3, 1    @ Read CNTV_CTL (Virtual Timer Control Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmWriteCntvCtl):\r
+  mcr    p15, 0, r0, c14, c3, 1    @ Write to CNTV_CTL (Virtual Timer Control Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntvCt):\r
+  mrrc   p15, 1, r0, r1, c14       @ Read CNTVCT  (Virtual Count Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntpCval):\r
+  mrrc   p15, 2, r0, r1, c14       @ Read CNTP_CTVAL (Physical Timer Compare Value Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmWriteCntpCval):\r
+  mcrr   p15, 2, r0, r1, c14       @ Write to CNTP_CTVAL (Physical Timer Compare Value Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntvCval):\r
+  mrrc   p15, 3, r0, r1, c14       @ Read CNTV_CTVAL (Virtual Timer Compare Value Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmWriteCntvCval):\r
+  mcrr   p15, 3, r0, r1, c14       @ write to  CNTV_CTVAL (Virtual Timer Compare Value Register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmReadCntvOff):\r
+  mrrc   p15, 4, r0, r1, c14       @ Read CNTVOFF (virtual Offset register)\r
+  bx     lr\r
+\r
+ASM_PFX(ArmWriteCntvOff):\r
+  mcrr   p15, 4, r0, r1, c14       @ Write to CNTVOFF (Virtual Offset register)\r
+  bx     lr\r
+\r
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED\r
diff --git a/ArmPkg/Library/ArmLib/ArmV7/ArmV7ArchTimerSupport.asm b/ArmPkg/Library/ArmLib/ArmV7/ArmV7ArchTimerSupport.asm
new file mode 100644 (file)
index 0000000..fc0be19
--- /dev/null
@@ -0,0 +1,119 @@
+//------------------------------------------------------------------------------ \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
+//\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
+    EXPORT  ArmReadCntFrq\r
+    EXPORT  ArmWriteCntFrq\r
+    EXPORT  ArmReadCntPct\r
+    EXPORT  ArmReadCntkCtl\r
+    EXPORT  ArmWriteCntkCtl\r
+    EXPORT  ArmReadCntpTval\r
+    EXPORT  ArmWriteCntpTval\r
+    EXPORT  ArmReadCntpCtl\r
+    EXPORT  ArmWriteCntpCtl\r
+    EXPORT  ArmReadCntvTval\r
+    EXPORT  ArmWriteCntvTval\r
+    EXPORT  ArmReadCntvCtl\r
+    EXPORT  ArmWriteCntvCtl\r
+    EXPORT  ArmReadCntvCt\r
+    EXPORT  ArmReadCntpCval\r
+    EXPORT  ArmWriteCntpCval\r
+    EXPORT  ArmReadCntvCval\r
+    EXPORT  ArmWriteCntvCval\r
+    EXPORT  ArmReadCntvOff\r
+    EXPORT  ArmWriteCntvOff\r
+\r
+    AREA    ArmV7ArchTimerSupport, CODE, READONLY\r
+    PRESERVE8\r
+\r
+ArmReadCntFrq\r
+  mrc    p15, 0, r0, c14, c0, 0    ; Read CNTFRQ\r
+  bx     lr\r
+\r
+ArmWriteCntFrq\r
+  mcr    p15, 0, r0, c14, c0, 0    ; Write to CNTFRQ\r
+  bx     lr\r
+\r
+ArmReadCntPct\r
+  mrrc   p15, 0, r0, r1, c14       ; Read CNTPT (Physical counter register)\r
+  bx     lr\r
+\r
+ArmReadCntkCtl\r
+  mrc    p15, 0, r0, c14, c1, 0    ; Read CNTK_CTL (Timer PL1 Control Register)\r
+  bx     lr\r
+\r
+ArmWriteCntkCtl\r
+  mcr    p15, 0, r0, c14, c1, 0    ; Write to CNTK_CTL (Timer PL1 Control Register)\r
+  bx     lr\r
+\r
+ArmReadCntpTval\r
+  mrc    p15, 0, r0, c14, c2, 0    ; Read CNTP_TVAL (PL1 physical timer value register)\r
+  bx     lr\r
+\r
+ArmWriteCntpTval\r
+  mcr    p15, 0, r0, c14, c2, 0    ; Write to CNTP_TVAL (PL1 physical timer value register)\r
+  bx     lr\r
+\r
+ArmReadCntpCtl\r
+  mrc    p15, 0, r0, c14, c2, 1    ; Read CNTP_CTL (PL1 Physical Timer Control Register)\r
+  bx     lr\r
+\r
+ArmWriteCntpCtl\r
+  mcr    p15, 0, r0, c14, c2, 1    ; Write to  CNTP_CTL (PL1 Physical Timer Control Register)\r
+  bx     lr\r
+\r
+ArmReadCntvTval\r
+  mrc    p15, 0, r0, c14, c3, 0    ; Read CNTV_TVAL (Virtual Timer Value register)\r
+  bx     lr\r
+\r
+ArmWriteCntvTval\r
+  mcr    p15, 0, r0, c14, c3, 0    ; Write to CNTV_TVAL (Virtual Timer Value register)\r
+  bx     lr\r
+\r
+ArmReadCntvCtl\r
+  mrc    p15, 0, r0, c14, c3, 1    ; Read CNTV_CTL (Virtual Timer Control Register)\r
+  bx     lr\r
+\r
+ArmWriteCntvCtl\r
+  mcr    p15, 0, r0, c14, c3, 1    ; Write to CNTV_CTL (Virtual Timer Control Register)\r
+  bx     lr\r
+\r
+ArmReadCntvCt\r
+  mrrc   p15, 1, r0, r1, c14       ; Read CNTVCT  (Virtual Count Register)\r
+  bx     lr\r
+\r
+ArmReadCntpCval\r
+  mrrc   p15, 2, r0, r1, c14       ; Read CNTP_CTVAL (Physical Timer Compare Value Register)\r
+  bx     lr\r
+\r
+ArmWriteCntpCval\r
+  mcrr   p15, 2, r0, r1, c14       ; Write to CNTP_CTVAL (Physical Timer Compare Value Register)\r
+  bx     lr\r
+\r
+ArmReadCntvCval\r
+  mrrc   p15, 3, r0, r1, c14       ; Read CNTV_CTVAL (Virtual Timer Compare Value Register)\r
+  bx     lr\r
+\r
+ArmWriteCntvCval\r
+  mcrr   p15, 3, r0, r1, c14       ; write to  CNTV_CTVAL (Virtual Timer Compare Value Register)\r
+  bx     lr\r
+\r
+ArmReadCntvOff\r
+  mrrc   p15, 4, r0, r1, c14       ; Read CNTVOFF (virtual Offset register)\r
+  bx     lr\r
+\r
+ArmWriteCntvOff\r
+  mcrr   p15, 4, r0, r1, c14       ; Write to CNTVOFF (Virtual Offset register)\r
+  bx     lr\r
+\r
+ END\r
index 2f0ade9b8e47be4ffe14a5f00ee2cf4d2f85a546..2bc01a9949ec4e6c05a645287d95d6315eb0150f 100644 (file)
   ArmV7Lib.c\r
   ArmV7Mmu.c\r
 \r
+  ArmV7ArchTimer.c\r
+  ArmV7ArchTimerSupport.S    | GCC\r
+  ArmV7ArchTimerSupport.asm    | RVCT\r
+\r
 [Packages]\r
   ArmPkg/ArmPkg.dec\r
   MdePkg/MdePkg.dec\r
index 6211549742ade3fe7f79e40d1f1fa12a781a7fd0..5fdb04497490fe72dddd4960b2ed77d544562978 100644 (file)
   \r
   ArmV7Lib.c\r
   ArmV7Mmu.c\r
+  \r
+  ArmV7ArchTimer.c\r
+  ArmV7ArchTimerSupport.S    | GCC\r
+  ArmV7ArchTimerSupport.asm  | RVCT\r
 \r
 [Packages]\r
   ArmPkg/ArmPkg.dec\r
index b7cb4504622e99c882cd6751b4baaa793935886c..9e6f17ec3eb74598036ac12f3bf67ff111b56d1d 100644 (file)
   ArmV7Support.asm  | RVCT\r
 \r
   ArmV7Lib.c\r
+  \r
+  ArmV7ArchTimer.c\r
+  ArmV7ArchTimerSupport.S    | GCC\r
+  ArmV7ArchTimerSupport.asm    | RVCT\r
 \r
 [Packages]\r
   ArmPkg/ArmPkg.dec\r