ArmPkg: ArmArchTimerLib: conditionally rebase to actual timer frequency

Allow a platform to set PcdArmArchTimerFreqInHz to zero, and consider it a
request to use the actual timer frequency.

No global variable is introduced, so that the library can be used in PEIMs
that execute from flash.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <Olivier.martin@arm.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16691 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Laszlo Ersek 2015-02-02 12:01:48 +00:00 committed by lersek
parent b36bc5af58
commit 16b7aff06b
1 changed files with 38 additions and 20 deletions

View File

@ -37,28 +37,29 @@ TimerConstructor (
UINTN TimerFreq;
//
// Check if Architectural Timer frequency is valid (should not be 0).
// Check if Architectural Timer frequency is pre-determined by the platform
// (ie. nonzero).
//
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 (PcdGet32 (PcdArmArchTimerFreqInHz) != 0) {
//
// 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);
#ifdef MDE_CPU_ARM
//
// Only set the frequency for ARMv7. We expect the secure firmware to
// have already done it.
// If the security extension is not implemented, set Timer Frequency
// here.
//
if ((ArmReadIdPfr1 () & ARM_PFR1_SEC) == 0x0) {
ArmGenericTimerSetTimerFreq (PcdGet32 (PcdArmArchTimerFreqInHz));
}
//
// Only set the frequency for ARMv7. We expect the secure firmware to
// have already done it.
// If the security extension is not implemented, set Timer Frequency
// here.
//
if ((ArmReadIdPfr1 () & ARM_PFR1_SEC) == 0x0) {
ArmGenericTimerSetTimerFreq (PcdGet32 (PcdArmArchTimerFreqInHz));
}
#endif
}
//
// Architectural Timer Frequency must be set in the Secure privileged
@ -92,14 +93,31 @@ MicroSecondDelay (
{
UINT64 TimerTicks64;
UINT64 SystemCounterVal;
UINT64 (EFIAPI
*MultU64xN) (
IN UINT64 Multiplicand,
IN UINTN Multiplier
);
UINTN TimerFreq;
#ifdef MDE_CPU_ARM
MultU64xN = MultU64x32;
#else
MultU64xN = MultU64x64;
#endif
TimerFreq = PcdGet32 (PcdArmArchTimerFreqInHz);
if (TimerFreq == 0) {
TimerFreq = ArmGenericTimerGetTimerFreq ();
}
// Calculate counter ticks that can represent requested delay:
// = MicroSeconds x TICKS_PER_MICRO_SEC
// = MicroSeconds x Frequency.10^-6
TimerTicks64 = DivU64x32 (
MultU64x32 (
MultU64xN (
MicroSeconds,
PcdGet32 (PcdArmArchTimerFreqInHz)
TimerFreq
),
1000000U
);