diff options
author | klu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524> | 2009-01-13 18:39:43 +0000 |
---|---|---|
committer | klu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524> | 2009-01-13 18:39:43 +0000 |
commit | 9be2c306aa8e267eefbc6b9d4ef099308b7f091a (patch) | |
tree | 09be55fe160658d3b35aae12c117bec0699ff02f /DuetPkg/Library/DuetTimerLib | |
parent | 4e6a198ccca8d95b452b85e66da84fba1acd34a5 (diff) | |
download | edk2-platforms-9be2c306aa8e267eefbc6b9d4ef099308b7f091a.tar.xz |
Use ACPI timer for Duet platform.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7264 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'DuetPkg/Library/DuetTimerLib')
-rw-r--r-- | DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf | 12 | ||||
-rw-r--r-- | DuetPkg/Library/DuetTimerLib/X86TimerLib.c | 186 |
2 files changed, 138 insertions, 60 deletions
diff --git a/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf b/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf index 6d841645b0..d076fbd5c2 100644 --- a/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf +++ b/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf @@ -42,11 +42,15 @@ [Packages]
MdePkg/MdePkg.dec
+ DuetPkg/DuetPkg.dec
[LibraryClasses]
BaseLib
DebugLib
- UefiBootServicesTableLib
-
-[Protocols]
- gEfiMetronomeArchProtocolGuid # ALWAYS_CONSUMED
+ HobLib
+ IoLib
+
+[Guids]
+ gEfiAcpiDescriptionGuid
+
+
\ No newline at end of file diff --git a/DuetPkg/Library/DuetTimerLib/X86TimerLib.c b/DuetPkg/Library/DuetTimerLib/X86TimerLib.c index 13df34fc34..185844eeb3 100644 --- a/DuetPkg/Library/DuetTimerLib/X86TimerLib.c +++ b/DuetPkg/Library/DuetTimerLib/X86TimerLib.c @@ -1,5 +1,10 @@ /** @file
- Timer Library functions built upon local APIC on IA32/x64.
+ Timer Library functions built upon ACPI on IA32/x64.
+
+ ACPI power management timer is a 24-bit or 32-bit fixed rate free running count-up
+ timer that runs off a 3.579545 MHz clock.
+ When startup, Duet will check the FADT to determine whether the PM timer is a
+ 32-bit or 25-bit timer.
Copyright (c) 2006 - 2007, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
@@ -16,25 +21,93 @@ #include <Library/TimerLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
-#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Guid/AcpiDescription.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
-#include <Protocol/Metronome.h>
+EFI_ACPI_DESCRIPTION *gAcpiDesc = NULL;
/**
-EFI_METRONOME_ARCH_PROTOCOL *gDuetMetronome = NULL;
-
-EFI_METRONOME_ARCH_PROTOCOL*
-GetMetronomeArchProtocol (
- VOID
- )
+ Internal function to get Acpi information from HOB.
+
+ @return Pointer to ACPI description structure.
+**/
+EFI_ACPI_DESCRIPTION*
+InternalGetApciDescrptionTable (
+ VOID
+ )
{
- if (gDuetMetronome == NULL) {
- gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID**) &gDuetMetronome);
+ EFI_PEI_HOB_POINTERS GuidHob;
+
+ if (gAcpiDesc != NULL) {
+ return gAcpiDesc;
}
- return gDuetMetronome;
-}
+ GuidHob.Raw = GetFirstGuidHob (&gEfiAcpiDescriptionGuid);
+ if (GuidHob.Raw != NULL) {
+ gAcpiDesc = GET_GUID_HOB_DATA (GuidHob.Guid);
+ DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.RegisterBitWidth = 0x%X\n", gAcpiDesc->PM_TMR_BLK.RegisterBitWidth));
+ DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.Address = 0x%X\n", gAcpiDesc->PM_TMR_BLK.Address));
+ return gAcpiDesc;
+ } else {
+ DEBUG ((EFI_D_ERROR, "Fail to get Acpi description table from hob\n"));
+ return NULL;
+ }
+}
+
+/**
+ Internal function to read the current tick counter of ACPI.
+
+ @return The tick counter read.
+
**/
+STATIC
+UINT32
+InternalAcpiGetTimerTick (
+ VOID
+ )
+{
+ return IoRead32 ((UINTN)gAcpiDesc->PM_TMR_BLK.Address);
+}
+
+/**
+ Stalls the CPU for at least the given number of ticks.
+
+ Stalls the CPU for at least the given number of ticks. It's invoked by
+ MicroSecondDelay() and NanoSecondDelay().
+
+ @param Delay A period of time to delay in ticks.
+
+**/
+STATIC
+VOID
+InternalAcpiDelay (
+ IN UINT32 Delay
+ )
+{
+ UINT32 Ticks;
+ UINT32 Times;
+
+ Times = Delay >> (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2);
+ Delay &= (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2)) - 1;
+ do {
+ //
+ // The target timer count is calculated here
+ //
+ Ticks = InternalAcpiGetTimerTick () + Delay;
+ Delay = 1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2);
+ //
+ // Wait until time out
+ // Delay >= 2^23 (if ACPI provide 24-bit timer) or Delay >= 2^31 (if ACPI
+ // provide 32-bit timer) could not be handled by this function
+ // Timer wrap-arounds are handled correctly by this function
+ //
+ while (((Ticks - InternalAcpiGetTimerTick ()) & (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 1))) == 0) {
+ CpuPause ();
+ }
+ } while (Times-- > 0);
+}
/**
Stalls the CPU for at least the given number of microseconds.
@@ -52,36 +125,20 @@ MicroSecondDelay ( IN UINTN MicroSeconds
)
{
- gBS->Stall (MicroSeconds);
-/**
- EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
- UINT32 Counter;
- UINTN Remainder;
-
- if ((mMetronome = GetMetronomeArchProtocol()) == NULL) {
+
+ if (InternalGetApciDescrptionTable() == NULL) {
return MicroSeconds;
}
-
- //
- // Calculate the number of ticks by dividing the number of microseconds by
- // the TickPeriod.
- // Calculation is based on 100ns unit.
- //
- Counter = (UINT32) DivU64x32Remainder (
- MicroSeconds * 10,
- mMetronome->TickPeriod,
- &Remainder
- );
- //
- // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
- // periods, thus attempting to ensure Microseconds of stall time.
- //
- if (Remainder != 0) {
- Counter++;
- }
-
- mMetronome->WaitForTick (mMetronome, Counter);
-**/
+
+ InternalAcpiDelay (
+ (UINT32)DivU64x32 (
+ MultU64x32 (
+ MicroSeconds,
+ 3579545
+ ),
+ 1000000u
+ )
+ );
return MicroSeconds;
}
@@ -101,11 +158,20 @@ NanoSecondDelay ( IN UINTN NanoSeconds
)
{
- //
- // Duet platform need *not* this interface.
- //
- //ASSERT (FALSE);
- return 0;
+ if (InternalGetApciDescrptionTable() == NULL) {
+ return NanoSeconds;
+ }
+
+ InternalAcpiDelay (
+ (UINT32)DivU64x32 (
+ MultU64x32 (
+ NanoSeconds,
+ 3579545
+ ),
+ 1000000000u
+ )
+ );
+ return NanoSeconds;
}
/**
@@ -126,11 +192,11 @@ GetPerformanceCounter ( VOID
)
{
- //
- // Duet platform need *not* this interface.
- //
- //ASSERT (FALSE);
- return 0;
+ if (InternalGetApciDescrptionTable() == NULL) {
+ return 0;
+ }
+
+ return (UINT64)InternalAcpiGetTimerTick ();
}
/**
@@ -163,9 +229,17 @@ GetPerformanceCounterProperties ( OUT UINT64 *EndValue OPTIONAL
)
{
- //
- // Duet platform need *not* this interface.
- //
- //ASSERT (FALSE);
- return 0;
+ if (InternalGetApciDescrptionTable() == NULL) {
+ return 0;
+ }
+
+ if (StartValue != NULL) {
+ *StartValue = 0;
+ }
+
+ if (EndValue != NULL) {
+ *EndValue = (1 << gAcpiDesc->PM_TMR_BLK.RegisterBitWidth) - 1;
+ }
+
+ return 3579545;
}
|