From: klu2 Date: Tue, 13 Jan 2009 18:39:43 +0000 (+0000) Subject: Use ACPI timer for Duet platform. X-Git-Tag: edk2-stable201903~18984 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=9be2c306aa8e267eefbc6b9d4ef099308b7f091a Use ACPI timer for Duet platform. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7264 6f19259b-4bc3-4df7-8a09-765794883524 --- 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
All rights reserved. This program and the accompanying materials @@ -16,25 +21,93 @@ #include #include #include -#include +#include +#include +#include +#include -#include +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; }