]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Use ACPI timer for Duet platform.
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 13 Jan 2009 18:39:43 +0000 (18:39 +0000)
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 13 Jan 2009 18:39:43 +0000 (18:39 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7264 6f19259b-4bc3-4df7-8a09-765794883524

DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf
DuetPkg/Library/DuetTimerLib/X86TimerLib.c

index 6d841645b0a8c24908cf969ba10eb6b81c71a268..d076fbd5c28ecb12c6fa77ef00a96134f2dbe675 100644 (file)
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
+  DuetPkg/DuetPkg.dec\r
 \r
 [LibraryClasses]\r
   BaseLib\r
   DebugLib\r
-  UefiBootServicesTableLib\r
-\r
-[Protocols]\r
-  gEfiMetronomeArchProtocolGuid         # ALWAYS_CONSUMED\r
+  HobLib\r
+  IoLib\r
+  \r
+[Guids]\r
+  gEfiAcpiDescriptionGuid\r
+  \r
+  
\ No newline at end of file
index 13df34fc34d4afa29eb1fd317f62f3857fca6fa8..185844eeb3d8b411544f99d0e292571543a3a4f6 100644 (file)
@@ -1,5 +1,10 @@
 /** @file\r
-  Timer Library functions built upon local APIC on IA32/x64.\r
+  Timer Library functions built upon ACPI on IA32/x64.\r
+  \r
+  ACPI power management timer is a 24-bit or 32-bit fixed rate free running count-up\r
+  timer that runs off a 3.579545 MHz clock. \r
+  When startup, Duet will check the FADT to determine whether the PM timer is a \r
+  32-bit or 25-bit timer.\r
 \r
   Copyright (c) 2006 - 2007, Intel Corporation<BR>\r
   All rights reserved. This program and the accompanying materials\r
 #include <Library/TimerLib.h>\r
 #include <Library/BaseLib.h>\r
 #include <Library/DebugLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Guid/AcpiDescription.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
 \r
-#include <Protocol/Metronome.h>\r
+EFI_ACPI_DESCRIPTION *gAcpiDesc          = NULL;\r
 \r
 /**\r
-EFI_METRONOME_ARCH_PROTOCOL *gDuetMetronome = NULL;\r
-\r
-EFI_METRONOME_ARCH_PROTOCOL*\r
-GetMetronomeArchProtocol (\r
-    VOID\r
-    )\r
+  Internal function to get Acpi information from HOB.\r
+  \r
+  @return Pointer to ACPI description structure.\r
+**/\r
+EFI_ACPI_DESCRIPTION*\r
+InternalGetApciDescrptionTable (\r
+  VOID\r
+  )\r
 {\r
-  if (gDuetMetronome == NULL) {\r
-     gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID**) &gDuetMetronome);\r
+  EFI_PEI_HOB_POINTERS  GuidHob;\r
+  \r
+  if (gAcpiDesc != NULL) {\r
+    return gAcpiDesc;\r
   }\r
   \r
-  return gDuetMetronome;\r
-}    \r
+  GuidHob.Raw = GetFirstGuidHob (&gEfiAcpiDescriptionGuid);\r
+  if (GuidHob.Raw != NULL) {\r
+    gAcpiDesc = GET_GUID_HOB_DATA (GuidHob.Guid);\r
+    DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.RegisterBitWidth = 0x%X\n", gAcpiDesc->PM_TMR_BLK.RegisterBitWidth));\r
+    DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.Address = 0x%X\n", gAcpiDesc->PM_TMR_BLK.Address));\r
+    return gAcpiDesc;\r
+  } else {\r
+    DEBUG ((EFI_D_ERROR, "Fail to get Acpi description table from hob\n"));\r
+    return NULL;\r
+  }\r
+}\r
+\r
+/**\r
+  Internal function to read the current tick counter of ACPI.\r
+\r
+  @return The tick counter read.\r
+\r
 **/\r
+STATIC\r
+UINT32\r
+InternalAcpiGetTimerTick (\r
+  VOID\r
+  )\r
+{\r
+  return IoRead32 ((UINTN)gAcpiDesc->PM_TMR_BLK.Address);\r
+}\r
+\r
+/**\r
+  Stalls the CPU for at least the given number of ticks.\r
+\r
+  Stalls the CPU for at least the given number of ticks. It's invoked by\r
+  MicroSecondDelay() and NanoSecondDelay().\r
+\r
+  @param  Delay     A period of time to delay in ticks.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+InternalAcpiDelay (\r
+  IN      UINT32                    Delay\r
+  )\r
+{\r
+  UINT32                            Ticks;\r
+  UINT32                            Times;\r
+\r
+  Times    = Delay >> (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2);\r
+  Delay   &= (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2)) - 1;\r
+  do {\r
+    //\r
+    // The target timer count is calculated here\r
+    //\r
+    Ticks    = InternalAcpiGetTimerTick () + Delay;\r
+    Delay    = 1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2);\r
+    //\r
+    // Wait until time out\r
+    // Delay >= 2^23 (if ACPI provide 24-bit timer) or Delay >= 2^31 (if ACPI\r
+    // provide 32-bit timer) could not be handled by this function\r
+    // Timer wrap-arounds are handled correctly by this function\r
+    //\r
+    while (((Ticks - InternalAcpiGetTimerTick ()) & (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 1))) == 0) {\r
+      CpuPause ();\r
+    }\r
+  } while (Times-- > 0);\r
+}\r
 \r
 /**\r
   Stalls the CPU for at least the given number of microseconds.\r
@@ -52,36 +125,20 @@ MicroSecondDelay (
   IN      UINTN                     MicroSeconds\r
   )\r
 {\r
-  gBS->Stall (MicroSeconds);\r
-/**\r
-  EFI_METRONOME_ARCH_PROTOCOL       *mMetronome;\r
-  UINT32                            Counter;\r
-  UINTN                             Remainder;  \r
-  \r
-  if ((mMetronome = GetMetronomeArchProtocol()) == NULL) {\r
+\r
+  if (InternalGetApciDescrptionTable() == NULL) {\r
     return MicroSeconds;\r
   }\r
-  \r
-  //\r
-  // Calculate the number of ticks by dividing the number of microseconds by\r
-  // the TickPeriod.\r
-  // Calculation is based on 100ns unit.\r
-  //\r
-  Counter = (UINT32) DivU64x32Remainder (\r
-                       MicroSeconds * 10,\r
-                       mMetronome->TickPeriod,\r
-                       &Remainder\r
-                       );\r
-  //\r
-  // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick\r
-  // periods, thus attempting to ensure Microseconds of stall time.\r
-  //\r
-  if (Remainder != 0) {\r
-    Counter++;\r
-  }\r
-\r
-  mMetronome->WaitForTick (mMetronome, Counter);\r
-**/\r
\r
+  InternalAcpiDelay (\r
+    (UINT32)DivU64x32 (\r
+              MultU64x32 (\r
+                MicroSeconds,\r
+                3579545\r
+                ),\r
+              1000000u\r
+              )\r
+    );\r
   return MicroSeconds;\r
 }\r
 \r
@@ -101,11 +158,20 @@ NanoSecondDelay (
   IN      UINTN                     NanoSeconds\r
   )\r
 {\r
-  //\r
-  // Duet platform need *not* this interface.\r
-  //\r
-  //ASSERT (FALSE);\r
-  return 0;\r
+  if (InternalGetApciDescrptionTable() == NULL) {\r
+    return NanoSeconds;\r
+  }\r
+  \r
+  InternalAcpiDelay (\r
+    (UINT32)DivU64x32 (\r
+              MultU64x32 (\r
+                NanoSeconds,\r
+                3579545\r
+                ),\r
+              1000000000u\r
+              )\r
+    );\r
+  return NanoSeconds;\r
 }\r
 \r
 /**\r
@@ -126,11 +192,11 @@ GetPerformanceCounter (
   VOID\r
   )\r
 {\r
-  //\r
-  // Duet platform need *not* this interface.\r
-  //\r
-  //ASSERT (FALSE);\r
-  return 0;\r
+  if (InternalGetApciDescrptionTable() == NULL) {\r
+    return 0;\r
+  }\r
+  \r
+  return (UINT64)InternalAcpiGetTimerTick ();\r
 }\r
 \r
 /**\r
@@ -163,9 +229,17 @@ GetPerformanceCounterProperties (
   OUT      UINT64                    *EndValue     OPTIONAL\r
   )\r
 {\r
-  //\r
-  // Duet platform need *not* this interface.\r
-  //\r
-  //ASSERT (FALSE);\r
-  return 0;\r
+  if (InternalGetApciDescrptionTable() == NULL) {\r
+    return 0;\r
+  }\r
+  \r
+  if (StartValue != NULL) {\r
+    *StartValue = 0;\r
+  }\r
+\r
+  if (EndValue != NULL) {\r
+    *EndValue = (1 << gAcpiDesc->PM_TMR_BLK.RegisterBitWidth) - 1;\r
+  }\r
+\r
+  return 3579545;\r
 }\r