mirror of https://github.com/acidanthera/audk.git
ArmPkg: Add ARM Architectural Timer support
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
This commit is contained in:
parent
0c0e7ef451
commit
da9675a241
|
@ -133,3 +133,10 @@
|
||||||
# The Linux ATAGs are expected to be under 0x4000 (16KB) from the beginning of the System Memory
|
# The Linux ATAGs are expected to be under 0x4000 (16KB) from the beginning of the System Memory
|
||||||
gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset|0x4000|UINT32|0x00000020
|
gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset|0x4000|UINT32|0x00000020
|
||||||
|
|
||||||
|
#
|
||||||
|
# ARM Architectural Timer
|
||||||
|
#
|
||||||
|
gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|0|UINT32|0x00000034
|
||||||
|
# ARM Architectural Timer Interrupt(GIC PPI) number
|
||||||
|
gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|29|UINT32|0x00000035
|
||||||
|
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|30|UINT32|0x00000036
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#define __ARM_V7_H__
|
#define __ARM_V7_H__
|
||||||
|
|
||||||
#include <Chipset/ArmV7Mmu.h>
|
#include <Chipset/ArmV7Mmu.h>
|
||||||
|
#include <Chipset/ArmV7ArchTimer.h>
|
||||||
|
|
||||||
// Domain Access Control Register
|
// Domain Access Control Register
|
||||||
#define DOMAIN_ACCESS_CONTROL_MASK(a) (3UL << (2 * (a)))
|
#define DOMAIN_ACCESS_CONTROL_MASK(a) (3UL << (2 * (a)))
|
||||||
|
@ -80,6 +81,12 @@ ArmWriteTpidrurw (
|
||||||
UINTN Value
|
UINTN Value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
UINTN
|
||||||
|
EFIAPI
|
||||||
|
ArmIsArchTimerImplemented (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
UINTN
|
UINTN
|
||||||
EFIAPI
|
EFIAPI
|
||||||
ArmReadIdPfr1 (
|
ArmReadIdPfr1 (
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
/** @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.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __ARMV7_ARCH_TIMER_H_
|
||||||
|
#define __ARMV7_ARCH_TIMER_H_
|
||||||
|
|
||||||
|
UINTN
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntFrq (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ArmWriteCntFrq (
|
||||||
|
UINTN FreqInHz
|
||||||
|
);
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntPct (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
UINTN
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntkCtl (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ArmWriteCntkCtl (
|
||||||
|
UINTN Val
|
||||||
|
);
|
||||||
|
|
||||||
|
UINTN
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntpTval (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ArmWriteCntpTval (
|
||||||
|
UINTN Val
|
||||||
|
);
|
||||||
|
|
||||||
|
UINTN
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntpCtl (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ArmWriteCntpCtl (
|
||||||
|
UINTN Val
|
||||||
|
);
|
||||||
|
|
||||||
|
UINTN
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntvTval (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ArmWriteCntvTval (
|
||||||
|
UINTN Val
|
||||||
|
);
|
||||||
|
|
||||||
|
UINTN
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntvCtl (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ArmWriteCntvCtl (
|
||||||
|
UINTN Val
|
||||||
|
);
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntvCt (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntpCval (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ArmWriteCntpCval (
|
||||||
|
UINT64 Val
|
||||||
|
);
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntvCval (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ArmWriteCntvCval (
|
||||||
|
UINT64 Val
|
||||||
|
);
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
EFIAPI
|
||||||
|
ArmReadCntvOff (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ArmWriteCntvOff (
|
||||||
|
UINT64 Val
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
|
@ -167,7 +167,7 @@ Cp15CacheInfo (
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
EFIAPI
|
EFIAPI
|
||||||
ArmIsMPCore (
|
ArmIsMpCore (
|
||||||
VOID
|
VOID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -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__
|
|
@ -0,0 +1,191 @@
|
||||||
|
/** @file
|
||||||
|
Generic ARM implementation of TimerLib.h
|
||||||
|
|
||||||
|
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 <Base.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/TimerLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/PcdLib.h>
|
||||||
|
#include <Library/ArmV7ArchTimerLib.h>
|
||||||
|
#include <Chipset/ArmV7.h>
|
||||||
|
|
||||||
|
#define TICKS_PER_MICRO_SEC (PcdGet32 (PcdArmArchTimerFreqInHz)/1000000U)
|
||||||
|
|
||||||
|
RETURN_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ArmArchTimerLibConstructor (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Check if the ARM Generic Timer Extension is implemented
|
||||||
|
if (ArmIsArchTimerImplemented ()) {
|
||||||
|
|
||||||
|
UINTN TimerFreq;
|
||||||
|
|
||||||
|
// Check if Architectural Timer frequency is valid number (should not be 0)
|
||||||
|
ASSERT (PcdGet32 (PcdArmArchTimerFreqInHz));
|
||||||
|
|
||||||
|
// Check if ticks/uS is not 0. The Architectural timer runs at constant
|
||||||
|
// frequency irrespective of CPU frequency. According to General Timer Ref
|
||||||
|
// manual lower bound of the frequency is in the range of 1-10MHz
|
||||||
|
ASSERT (TICKS_PER_MICRO_SEC);
|
||||||
|
|
||||||
|
// If the security extensions are not implemented set Timer Frequency
|
||||||
|
if ((ArmReadIdPfr1 () & 0xF0)) {
|
||||||
|
ArmArchTimerSetTimerFreq (PcdGet32 (PcdArmArchTimerFreqInHz));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Architectural Timer Frequency must be set in the Secure privileged(if secure extensions are supported) mode.
|
||||||
|
// If the reset value (0) is returned just ASSERT.
|
||||||
|
TimerFreq = ArmArchTimerGetTimerFreq ();
|
||||||
|
ASSERT (TimerFreq);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, Hence cann't use this library \n"));
|
||||||
|
ASSERT (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RETURN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Stalls the CPU for the number of microseconds specified by MicroSeconds.
|
||||||
|
|
||||||
|
@param MicroSeconds The minimum number of microseconds to delay.
|
||||||
|
|
||||||
|
@return The value of MicroSeconds inputted.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
EFIAPI
|
||||||
|
MicroSecondDelay (
|
||||||
|
IN UINTN MicroSeconds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT64 TimerTicks64;
|
||||||
|
UINT64 SystemCounterVal;
|
||||||
|
|
||||||
|
// Calculate counter ticks that can represent requsted delay
|
||||||
|
TimerTicks64 = MultU64x32 (MicroSeconds, TICKS_PER_MICRO_SEC);
|
||||||
|
|
||||||
|
// Read System Counter value
|
||||||
|
SystemCounterVal = ArmArchTimerGetSystemCount ();
|
||||||
|
|
||||||
|
TimerTicks64 += SystemCounterVal;
|
||||||
|
|
||||||
|
// Wait until delay count is expired.
|
||||||
|
while (SystemCounterVal < TimerTicks64) {
|
||||||
|
SystemCounterVal = ArmArchTimerGetSystemCount ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return MicroSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Stalls the CPU for at least the given number of nanoseconds.
|
||||||
|
|
||||||
|
Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
|
||||||
|
|
||||||
|
When the timer frequency is 1MHz, each tick corresponds to 1 microsecond.
|
||||||
|
Therefore, the nanosecond delay will be rounded up to the nearest 1 microsecond.
|
||||||
|
|
||||||
|
@param NanoSeconds The minimum number of nanoseconds to delay.
|
||||||
|
|
||||||
|
@return The value of NanoSeconds inputted.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
EFIAPI
|
||||||
|
NanoSecondDelay (
|
||||||
|
IN UINTN NanoSeconds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN MicroSeconds;
|
||||||
|
|
||||||
|
// Round up to 1us Tick Number
|
||||||
|
MicroSeconds = NanoSeconds / 1000;
|
||||||
|
MicroSeconds += ((NanoSeconds % 1000) == 0) ? 0 : 1;
|
||||||
|
|
||||||
|
MicroSecondDelay (MicroSeconds);
|
||||||
|
|
||||||
|
return NanoSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieves the current value of a 64-bit free running performance counter.
|
||||||
|
|
||||||
|
The counter can either count up by 1 or count down by 1. If the physical
|
||||||
|
performance counter counts by a larger increment, then the counter values
|
||||||
|
must be translated. The properties of the counter can be retrieved from
|
||||||
|
GetPerformanceCounterProperties().
|
||||||
|
|
||||||
|
@return The current value of the free running performance counter.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
EFIAPI
|
||||||
|
GetPerformanceCounter (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Just return the value of system count
|
||||||
|
return ArmArchTimerGetSystemCount ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieves the 64-bit frequency in Hz and the range of performance counter
|
||||||
|
values.
|
||||||
|
|
||||||
|
If StartValue is not NULL, then the value that the performance counter starts
|
||||||
|
with immediately after is it rolls over is returned in StartValue. If
|
||||||
|
EndValue is not NULL, then the value that the performance counter end with
|
||||||
|
immediately before it rolls over is returned in EndValue. The 64-bit
|
||||||
|
frequency of the performance counter in Hz is always returned. If StartValue
|
||||||
|
is less than EndValue, then the performance counter counts up. If StartValue
|
||||||
|
is greater than EndValue, then the performance counter counts down. For
|
||||||
|
example, a 64-bit free running counter that counts up would have a StartValue
|
||||||
|
of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
|
||||||
|
that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
|
||||||
|
|
||||||
|
@param StartValue The value the performance counter starts with when it
|
||||||
|
rolls over.
|
||||||
|
@param EndValue The value that the performance counter ends with before
|
||||||
|
it rolls over.
|
||||||
|
|
||||||
|
@return The frequency in Hz.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
EFIAPI
|
||||||
|
GetPerformanceCounterProperties (
|
||||||
|
OUT UINT64 *StartValue, OPTIONAL
|
||||||
|
OUT UINT64 *EndValue OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (StartValue != NULL) {
|
||||||
|
// Timer starts with the reload value
|
||||||
|
*StartValue = (UINT64)0ULL ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EndValue != NULL) {
|
||||||
|
// Timer counts down to 0x0
|
||||||
|
*EndValue = 0xFFFFFFFFFFFFFFFF;;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (UINT64)ArmArchTimerGetTimerFreq ();
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
#/** @file
|
||||||
|
#
|
||||||
|
# Copyright (c) 2011, ARM Limited. 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 = ArmArchTimerLib
|
||||||
|
FILE_GUID = 82da1b44-d2d6-4a7d-bbf0-a0cb67964034
|
||||||
|
MODULE_TYPE = BASE
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
LIBRARY_CLASS = TimerLib
|
||||||
|
CONSTRUCTOR = ArmArchTimerLibConstructor
|
||||||
|
|
||||||
|
[Sources.common]
|
||||||
|
ArmArchTimerLib.c
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
EmbeddedPkg/EmbeddedPkg.dec
|
||||||
|
ArmPkg/ArmPkg.dec
|
||||||
|
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
DebugLib
|
||||||
|
IoLib
|
||||||
|
ArmLib
|
||||||
|
BaseLib
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiCpuArchProtocolGuid
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntFrq)
|
||||||
|
GCC_ASM_EXPORT (ArmWriteCntFrq)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntPct)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntkCtl)
|
||||||
|
GCC_ASM_EXPORT (ArmWriteCntkCtl)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntpTval)
|
||||||
|
GCC_ASM_EXPORT (ArmWriteCntpTval)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntpCtl)
|
||||||
|
GCC_ASM_EXPORT (ArmWriteCntpCtl)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntvTval)
|
||||||
|
GCC_ASM_EXPORT (ArmWriteCntvTval)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntvCtl)
|
||||||
|
GCC_ASM_EXPORT (ArmWriteCntvCtl)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntvCt)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntpCval)
|
||||||
|
GCC_ASM_EXPORT (ArmWriteCntpCval)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntvCval)
|
||||||
|
GCC_ASM_EXPORT (ArmWriteCntvCval)
|
||||||
|
GCC_ASM_EXPORT (ArmReadCntvOff)
|
||||||
|
GCC_ASM_EXPORT (ArmWriteCntvOff)
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntFrq):
|
||||||
|
mrc p15, 0, r0, c14, c0, 0 @ Read CNTFRQ
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmWriteCntFrq):
|
||||||
|
mcr p15, 0, r0, c14, c0, 0 @ Write to CNTFRQ
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntPct):
|
||||||
|
mrrc p15, 0, r0, r1, c14 @ Read CNTPT (Physical counter register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntkCtl):
|
||||||
|
mrc p15, 0, r0, c14, c1, 0 @ Read CNTK_CTL (Timer PL1 Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmWriteCntkCtl):
|
||||||
|
mcr p15, 0, r0, c14, c1, 0 @ Write to CNTK_CTL (Timer PL1 Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntpTval):
|
||||||
|
mrc p15, 0, r0, c14, c2, 0 @ Read CNTP_TVAL (PL1 physical timer value register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmWriteCntpTval):
|
||||||
|
mcr p15, 0, r0, c14, c2, 0 @ Write to CNTP_TVAL (PL1 physical timer value register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntpCtl):
|
||||||
|
mrc p15, 0, r0, c14, c2, 1 @ Read CNTP_CTL (PL1 Physical Timer Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmWriteCntpCtl):
|
||||||
|
mcr p15, 0, r0, c14, c2, 1 @ Write to CNTP_CTL (PL1 Physical Timer Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntvTval):
|
||||||
|
mrc p15, 0, r0, c14, c3, 0 @ Read CNTV_TVAL (Virtual Timer Value register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmWriteCntvTval):
|
||||||
|
mcr p15, 0, r0, c14, c3, 0 @ Write to CNTV_TVAL (Virtual Timer Value register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntvCtl):
|
||||||
|
mrc p15, 0, r0, c14, c3, 1 @ Read CNTV_CTL (Virtual Timer Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmWriteCntvCtl):
|
||||||
|
mcr p15, 0, r0, c14, c3, 1 @ Write to CNTV_CTL (Virtual Timer Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntvCt):
|
||||||
|
mrrc p15, 1, r0, r1, c14 @ Read CNTVCT (Virtual Count Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntpCval):
|
||||||
|
mrrc p15, 2, r0, r1, c14 @ Read CNTP_CTVAL (Physical Timer Compare Value Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmWriteCntpCval):
|
||||||
|
mcrr p15, 2, r0, r1, c14 @ Write to CNTP_CTVAL (Physical Timer Compare Value Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntvCval):
|
||||||
|
mrrc p15, 3, r0, r1, c14 @ Read CNTV_CTVAL (Virtual Timer Compare Value Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmWriteCntvCval):
|
||||||
|
mcrr p15, 3, r0, r1, c14 @ write to CNTV_CTVAL (Virtual Timer Compare Value Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmReadCntvOff):
|
||||||
|
mrrc p15, 4, r0, r1, c14 @ Read CNTVOFF (virtual Offset register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_PFX(ArmWriteCntvOff):
|
||||||
|
mcrr p15, 4, r0, r1, c14 @ Write to CNTVOFF (Virtual Offset register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ASM_FUNCTION_REMOVE_IF_UNREFERENCED
|
|
@ -0,0 +1,119 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
EXPORT ArmReadCntFrq
|
||||||
|
EXPORT ArmWriteCntFrq
|
||||||
|
EXPORT ArmReadCntPct
|
||||||
|
EXPORT ArmReadCntkCtl
|
||||||
|
EXPORT ArmWriteCntkCtl
|
||||||
|
EXPORT ArmReadCntpTval
|
||||||
|
EXPORT ArmWriteCntpTval
|
||||||
|
EXPORT ArmReadCntpCtl
|
||||||
|
EXPORT ArmWriteCntpCtl
|
||||||
|
EXPORT ArmReadCntvTval
|
||||||
|
EXPORT ArmWriteCntvTval
|
||||||
|
EXPORT ArmReadCntvCtl
|
||||||
|
EXPORT ArmWriteCntvCtl
|
||||||
|
EXPORT ArmReadCntvCt
|
||||||
|
EXPORT ArmReadCntpCval
|
||||||
|
EXPORT ArmWriteCntpCval
|
||||||
|
EXPORT ArmReadCntvCval
|
||||||
|
EXPORT ArmWriteCntvCval
|
||||||
|
EXPORT ArmReadCntvOff
|
||||||
|
EXPORT ArmWriteCntvOff
|
||||||
|
|
||||||
|
AREA ArmV7ArchTimerSupport, CODE, READONLY
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
ArmReadCntFrq
|
||||||
|
mrc p15, 0, r0, c14, c0, 0 ; Read CNTFRQ
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmWriteCntFrq
|
||||||
|
mcr p15, 0, r0, c14, c0, 0 ; Write to CNTFRQ
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntPct
|
||||||
|
mrrc p15, 0, r0, r1, c14 ; Read CNTPT (Physical counter register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntkCtl
|
||||||
|
mrc p15, 0, r0, c14, c1, 0 ; Read CNTK_CTL (Timer PL1 Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmWriteCntkCtl
|
||||||
|
mcr p15, 0, r0, c14, c1, 0 ; Write to CNTK_CTL (Timer PL1 Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntpTval
|
||||||
|
mrc p15, 0, r0, c14, c2, 0 ; Read CNTP_TVAL (PL1 physical timer value register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmWriteCntpTval
|
||||||
|
mcr p15, 0, r0, c14, c2, 0 ; Write to CNTP_TVAL (PL1 physical timer value register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntpCtl
|
||||||
|
mrc p15, 0, r0, c14, c2, 1 ; Read CNTP_CTL (PL1 Physical Timer Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmWriteCntpCtl
|
||||||
|
mcr p15, 0, r0, c14, c2, 1 ; Write to CNTP_CTL (PL1 Physical Timer Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntvTval
|
||||||
|
mrc p15, 0, r0, c14, c3, 0 ; Read CNTV_TVAL (Virtual Timer Value register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmWriteCntvTval
|
||||||
|
mcr p15, 0, r0, c14, c3, 0 ; Write to CNTV_TVAL (Virtual Timer Value register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntvCtl
|
||||||
|
mrc p15, 0, r0, c14, c3, 1 ; Read CNTV_CTL (Virtual Timer Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmWriteCntvCtl
|
||||||
|
mcr p15, 0, r0, c14, c3, 1 ; Write to CNTV_CTL (Virtual Timer Control Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntvCt
|
||||||
|
mrrc p15, 1, r0, r1, c14 ; Read CNTVCT (Virtual Count Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntpCval
|
||||||
|
mrrc p15, 2, r0, r1, c14 ; Read CNTP_CTVAL (Physical Timer Compare Value Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmWriteCntpCval
|
||||||
|
mcrr p15, 2, r0, r1, c14 ; Write to CNTP_CTVAL (Physical Timer Compare Value Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntvCval
|
||||||
|
mrrc p15, 3, r0, r1, c14 ; Read CNTV_CTVAL (Virtual Timer Compare Value Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmWriteCntvCval
|
||||||
|
mcrr p15, 3, r0, r1, c14 ; write to CNTV_CTVAL (Virtual Timer Compare Value Register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmReadCntvOff
|
||||||
|
mrrc p15, 4, r0, r1, c14 ; Read CNTVOFF (virtual Offset register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
ArmWriteCntvOff
|
||||||
|
mcrr p15, 4, r0, r1, c14 ; Write to CNTVOFF (Virtual Offset register)
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
END
|
|
@ -35,6 +35,10 @@
|
||||||
ArmV7Lib.c
|
ArmV7Lib.c
|
||||||
ArmV7Mmu.c
|
ArmV7Mmu.c
|
||||||
|
|
||||||
|
ArmV7ArchTimer.c
|
||||||
|
ArmV7ArchTimerSupport.S | GCC
|
||||||
|
ArmV7ArchTimerSupport.asm | RVCT
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
ArmPkg/ArmPkg.dec
|
ArmPkg/ArmPkg.dec
|
||||||
MdePkg/MdePkg.dec
|
MdePkg/MdePkg.dec
|
||||||
|
|
|
@ -35,6 +35,10 @@
|
||||||
ArmV7Lib.c
|
ArmV7Lib.c
|
||||||
ArmV7Mmu.c
|
ArmV7Mmu.c
|
||||||
|
|
||||||
|
ArmV7ArchTimer.c
|
||||||
|
ArmV7ArchTimerSupport.S | GCC
|
||||||
|
ArmV7ArchTimerSupport.asm | RVCT
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
ArmPkg/ArmPkg.dec
|
ArmPkg/ArmPkg.dec
|
||||||
MdePkg/MdePkg.dec
|
MdePkg/MdePkg.dec
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
|
|
||||||
ArmV7Lib.c
|
ArmV7Lib.c
|
||||||
|
|
||||||
|
ArmV7ArchTimer.c
|
||||||
|
ArmV7ArchTimerSupport.S | GCC
|
||||||
|
ArmV7ArchTimerSupport.asm | RVCT
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
ArmPkg/ArmPkg.dec
|
ArmPkg/ArmPkg.dec
|
||||||
MdePkg/MdePkg.dec
|
MdePkg/MdePkg.dec
|
||||||
|
|
Loading…
Reference in New Issue