The generic timer support libraries call the actual system register accessor function via a single pair of functions ArmArchTimerReadReg() and ArmArchTimerWriteReg(), which take an enum argument to identify the register, and return output values by pointer reference. Since these functions are never called with a non-immediate argument, we can simply replace each invocation with the underlying system register accessor instead. This is mostly functionally equivalent, with the exception of the bounds check for the enum (which is pointless given the fact that we never pass a variable), the check for the presence of the architected timer (which only makes sense for ARMv7, but is highly unlikely to vary between platforms that are similar enough to run the same firmware image), and a check for enum values that refer to the HYP view of the timer, which we never referred to anywhere in the code in the first place. So get rid of the middle man, and update the ArmGenericTimerPhyCounterLib and ArmGenericTimerVirtCounterLib implementations to call the system register accessors directly. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
136 lines
2.4 KiB
C
136 lines
2.4 KiB
C
/** @file
|
|
|
|
Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
|
|
Copyright (c) 2014, Linaro 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 <Library/ArmGenericTimerCounterLib.h>
|
|
#include <Library/ArmLib.h>
|
|
|
|
VOID
|
|
EFIAPI
|
|
ArmGenericTimerEnableTimer (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN TimerCtrlReg;
|
|
|
|
TimerCtrlReg = ArmReadCntvCtl ();
|
|
TimerCtrlReg |= ARM_ARCH_TIMER_ENABLE;
|
|
|
|
//
|
|
// When running under KVM, we need to unmask the interrupt on the timer side
|
|
// as KVM will mask it when servicing the interrupt at the hypervisor level
|
|
// and delivering the virtual timer interrupt to the guest. Otherwise, the
|
|
// interrupt will fire again, trapping into the hypervisor again, etc. etc.
|
|
// This is scheduled to be fixed on the KVM side, but there is no harm in
|
|
// leaving this in once KVM gets fixed.
|
|
//
|
|
TimerCtrlReg &= ~ARM_ARCH_TIMER_IMASK;
|
|
ArmWriteCntvCtl (TimerCtrlReg);
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
ArmGenericTimerDisableTimer (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN TimerCtrlReg;
|
|
|
|
TimerCtrlReg = ArmReadCntvCtl ();
|
|
TimerCtrlReg &= ~ARM_ARCH_TIMER_ENABLE;
|
|
ArmWriteCntvCtl (TimerCtrlReg);
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
ArmGenericTimerSetTimerFreq (
|
|
IN UINTN FreqInHz
|
|
)
|
|
{
|
|
ArmWriteCntFrq (FreqInHz);
|
|
}
|
|
|
|
UINTN
|
|
EFIAPI
|
|
ArmGenericTimerGetTimerFreq (
|
|
VOID
|
|
)
|
|
{
|
|
return ArmReadCntFrq ();
|
|
}
|
|
|
|
UINTN
|
|
EFIAPI
|
|
ArmGenericTimerGetTimerVal (
|
|
VOID
|
|
)
|
|
{
|
|
return ArmReadCntvTval ();
|
|
}
|
|
|
|
|
|
VOID
|
|
EFIAPI
|
|
ArmGenericTimerSetTimerVal (
|
|
IN UINTN Value
|
|
)
|
|
{
|
|
ArmWriteCntvTval (Value);
|
|
}
|
|
|
|
UINT64
|
|
EFIAPI
|
|
ArmGenericTimerGetSystemCount (
|
|
VOID
|
|
)
|
|
{
|
|
return ArmReadCntvCt ();
|
|
}
|
|
|
|
UINTN
|
|
EFIAPI
|
|
ArmGenericTimerGetTimerCtrlReg (
|
|
VOID
|
|
)
|
|
{
|
|
return ArmReadCntvCtl ();
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
ArmGenericTimerSetTimerCtrlReg (
|
|
UINTN Value
|
|
)
|
|
{
|
|
ArmWriteCntvCtl (Value);
|
|
}
|
|
|
|
UINT64
|
|
EFIAPI
|
|
ArmGenericTimerGetCompareVal (
|
|
VOID
|
|
)
|
|
{
|
|
return ArmReadCntvCval ();
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
ArmGenericTimerSetCompareVal (
|
|
IN UINT64 Value
|
|
)
|
|
{
|
|
ArmWriteCntvCval (Value);
|
|
}
|