hwtimer.c revision 253690
171867Smsmith/****************************************************************************** 271867Smsmith * 371867Smsmith * Name: hwtimer.c - ACPI Power Management Timer Interface 471867Smsmith * 571867Smsmith *****************************************************************************/ 671867Smsmith 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 971867Smsmith * All rights reserved. 1071867Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2571867Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2971867Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4371867Smsmith 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 4671867Smsmith 4777424Smsmith#define _COMPONENT ACPI_HARDWARE 4891116Smsmith ACPI_MODULE_NAME ("hwtimer") 4971867Smsmith 5071867Smsmith 51231844Sjkim#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 5271867Smsmith/****************************************************************************** 5371867Smsmith * 5471867Smsmith * FUNCTION: AcpiGetTimerResolution 5571867Smsmith * 56138287Smarks * PARAMETERS: Resolution - Where the resolution is returned 5771867Smsmith * 58138287Smarks * RETURN: Status and timer resolution 5971867Smsmith * 60138287Smarks * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits). 6171867Smsmith * 6271867Smsmith ******************************************************************************/ 6371867Smsmith 6471867SmsmithACPI_STATUS 6571867SmsmithAcpiGetTimerResolution ( 6671867Smsmith UINT32 *Resolution) 6771867Smsmith{ 68167802Sjkim ACPI_FUNCTION_TRACE (AcpiGetTimerResolution); 6971867Smsmith 7077424Smsmith 7171867Smsmith if (!Resolution) 7271867Smsmith { 7371867Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 7471867Smsmith } 7571867Smsmith 76167802Sjkim if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) 7771867Smsmith { 7871867Smsmith *Resolution = 24; 7971867Smsmith } 8071867Smsmith else 8171867Smsmith { 8271867Smsmith *Resolution = 32; 8371867Smsmith } 8471867Smsmith 8571867Smsmith return_ACPI_STATUS (AE_OK); 8671867Smsmith} 8771867Smsmith 88167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimerResolution) 8971867Smsmith 90167802Sjkim 9171867Smsmith/****************************************************************************** 9271867Smsmith * 9371867Smsmith * FUNCTION: AcpiGetTimer 9471867Smsmith * 95138287Smarks * PARAMETERS: Ticks - Where the timer value is returned 9671867Smsmith * 97151937Sjkim * RETURN: Status and current timer value (ticks) 9871867Smsmith * 99138287Smarks * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). 10071867Smsmith * 10171867Smsmith ******************************************************************************/ 10271867Smsmith 10371867SmsmithACPI_STATUS 10471867SmsmithAcpiGetTimer ( 10571867Smsmith UINT32 *Ticks) 10671867Smsmith{ 10799679Siwasaki ACPI_STATUS Status; 10899679Siwasaki 10999679Siwasaki 110167802Sjkim ACPI_FUNCTION_TRACE (AcpiGetTimer); 11171867Smsmith 11283174Smsmith 11371867Smsmith if (!Ticks) 11471867Smsmith { 11571867Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 11671867Smsmith } 11771867Smsmith 118253690Sjkim /* ACPI 5.0A: PM Timer is optional */ 119253690Sjkim 120253690Sjkim if (!AcpiGbl_FADT.XPmTimerBlock.Address) 121253690Sjkim { 122253690Sjkim return_ACPI_STATUS (AE_SUPPORT); 123253690Sjkim } 124253690Sjkim 125197104Sjkim Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock); 12699679Siwasaki return_ACPI_STATUS (Status); 12771867Smsmith} 12871867Smsmith 129167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimer) 13071867Smsmith 131167802Sjkim 13271867Smsmith/****************************************************************************** 13371867Smsmith * 13471867Smsmith * FUNCTION: AcpiGetTimerDuration 13571867Smsmith * 136138287Smarks * PARAMETERS: StartTicks - Starting timestamp 137138287Smarks * EndTicks - End timestamp 138138287Smarks * TimeElapsed - Where the elapsed time is returned 13971867Smsmith * 140138287Smarks * RETURN: Status and TimeElapsed 14171867Smsmith * 14271867Smsmith * DESCRIPTION: Computes the time elapsed (in microseconds) between two 14371867Smsmith * PM Timer time stamps, taking into account the possibility of 14477424Smsmith * rollovers, the timer resolution, and timer frequency. 14577424Smsmith * 14677424Smsmith * The PM Timer's clock ticks at roughly 3.6 times per 14771867Smsmith * _microsecond_, and its clock continues through Cx state 14871867Smsmith * transitions (unlike many CPU timestamp counters) -- making it 14971867Smsmith * a versatile and accurate timer. 15071867Smsmith * 151114237Snjl * Note that this function accommodates only a single timer 152241973Sjkim * rollover. Thus for 24-bit timers, this function should only 15377424Smsmith * be used for calculating durations less than ~4.6 seconds 154138287Smarks * (~20 minutes for 32-bit timers) -- calculations below: 15571867Smsmith * 156114237Snjl * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec 157114237Snjl * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes 158114237Snjl * 15971867Smsmith ******************************************************************************/ 16071867Smsmith 16171867SmsmithACPI_STATUS 16271867SmsmithAcpiGetTimerDuration ( 16371867Smsmith UINT32 StartTicks, 16471867Smsmith UINT32 EndTicks, 16571867Smsmith UINT32 *TimeElapsed) 16671867Smsmith{ 16791116Smsmith ACPI_STATUS Status; 168138287Smarks UINT32 DeltaTicks; 169202771Sjkim UINT64 Quotient; 17071867Smsmith 17178986Smsmith 172167802Sjkim ACPI_FUNCTION_TRACE (AcpiGetTimerDuration); 17371867Smsmith 17480062Smsmith 17577424Smsmith if (!TimeElapsed) 17671867Smsmith { 17771867Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 17871867Smsmith } 17971867Smsmith 180253690Sjkim /* ACPI 5.0A: PM Timer is optional */ 181253690Sjkim 182253690Sjkim if (!AcpiGbl_FADT.XPmTimerBlock.Address) 183253690Sjkim { 184253690Sjkim return_ACPI_STATUS (AE_SUPPORT); 185253690Sjkim } 186253690Sjkim 18777424Smsmith /* 18871867Smsmith * Compute Tick Delta: 189138287Smarks * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. 19071867Smsmith */ 19171867Smsmith if (StartTicks < EndTicks) 19271867Smsmith { 19371867Smsmith DeltaTicks = EndTicks - StartTicks; 19471867Smsmith } 19577424Smsmith else if (StartTicks > EndTicks) 19671867Smsmith { 197167802Sjkim if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) 19871867Smsmith { 19991116Smsmith /* 24-bit Timer */ 20091116Smsmith 20173561Smsmith DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF); 20271867Smsmith } 20377424Smsmith else 20471867Smsmith { 20591116Smsmith /* 32-bit Timer */ 20691116Smsmith 20771867Smsmith DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks; 20871867Smsmith } 20971867Smsmith } 210138287Smarks else /* StartTicks == EndTicks */ 21173561Smsmith { 21273561Smsmith *TimeElapsed = 0; 21373561Smsmith return_ACPI_STATUS (AE_OK); 21473561Smsmith } 21571867Smsmith 21677424Smsmith /* 217138287Smarks * Compute Duration (Requires a 64-bit multiply and divide): 21871867Smsmith * 219245582Sjkim * TimeElapsed (microseconds) = 220245582Sjkim * (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY; 22171867Smsmith */ 222245582Sjkim Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * ACPI_USEC_PER_SEC, 223245582Sjkim ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL); 22471867Smsmith 225138287Smarks *TimeElapsed = (UINT32) Quotient; 22691116Smsmith return_ACPI_STATUS (Status); 22771867Smsmith} 22871867Smsmith 229167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimerDuration) 23071867Smsmith 231231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */ 232