hwtimer.c revision 229989
171867Smsmith 271867Smsmith/****************************************************************************** 371867Smsmith * 471867Smsmith * Name: hwtimer.c - ACPI Power Management Timer Interface 571867Smsmith * 671867Smsmith *****************************************************************************/ 771867Smsmith 8217365Sjkim/* 9229989Sjkim * Copyright (C) 2000 - 2012, Intel Corp. 1071867Smsmith * All rights reserved. 1171867Smsmith * 12217365Sjkim * Redistribution and use in source and binary forms, with or without 13217365Sjkim * modification, are permitted provided that the following conditions 14217365Sjkim * are met: 15217365Sjkim * 1. Redistributions of source code must retain the above copyright 16217365Sjkim * notice, this list of conditions, and the following disclaimer, 17217365Sjkim * without modification. 18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 20217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 21217365Sjkim * including a substantially similar Disclaimer requirement for further 22217365Sjkim * binary redistribution. 23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 24217365Sjkim * of any contributors may be used to endorse or promote products derived 25217365Sjkim * from this software without specific prior written permission. 2671867Smsmith * 27217365Sjkim * Alternatively, this software may be distributed under the terms of the 28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 29217365Sjkim * Software Foundation. 3071867Smsmith * 31217365Sjkim * NO WARRANTY 32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 43217365Sjkim */ 4471867Smsmith 45193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 46193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 4771867Smsmith 4877424Smsmith#define _COMPONENT ACPI_HARDWARE 4991116Smsmith ACPI_MODULE_NAME ("hwtimer") 5071867Smsmith 5171867Smsmith 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 118197104Sjkim Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock); 11971867Smsmith 12099679Siwasaki return_ACPI_STATUS (Status); 12171867Smsmith} 12271867Smsmith 123167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimer) 12471867Smsmith 125167802Sjkim 12671867Smsmith/****************************************************************************** 12771867Smsmith * 12871867Smsmith * FUNCTION: AcpiGetTimerDuration 12971867Smsmith * 130138287Smarks * PARAMETERS: StartTicks - Starting timestamp 131138287Smarks * EndTicks - End timestamp 132138287Smarks * TimeElapsed - Where the elapsed time is returned 13371867Smsmith * 134138287Smarks * RETURN: Status and TimeElapsed 13571867Smsmith * 13671867Smsmith * DESCRIPTION: Computes the time elapsed (in microseconds) between two 13771867Smsmith * PM Timer time stamps, taking into account the possibility of 13877424Smsmith * rollovers, the timer resolution, and timer frequency. 13977424Smsmith * 14077424Smsmith * The PM Timer's clock ticks at roughly 3.6 times per 14171867Smsmith * _microsecond_, and its clock continues through Cx state 14271867Smsmith * transitions (unlike many CPU timestamp counters) -- making it 14371867Smsmith * a versatile and accurate timer. 14471867Smsmith * 145114237Snjl * Note that this function accommodates only a single timer 14671867Smsmith * rollover. Thus for 24-bit timers, this function should only 14777424Smsmith * be used for calculating durations less than ~4.6 seconds 148138287Smarks * (~20 minutes for 32-bit timers) -- calculations below: 14971867Smsmith * 150114237Snjl * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec 151114237Snjl * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes 152114237Snjl * 15371867Smsmith ******************************************************************************/ 15471867Smsmith 15571867SmsmithACPI_STATUS 15671867SmsmithAcpiGetTimerDuration ( 15771867Smsmith UINT32 StartTicks, 15871867Smsmith UINT32 EndTicks, 15971867Smsmith UINT32 *TimeElapsed) 16071867Smsmith{ 16191116Smsmith ACPI_STATUS Status; 162138287Smarks UINT32 DeltaTicks; 163202771Sjkim UINT64 Quotient; 16471867Smsmith 16578986Smsmith 166167802Sjkim ACPI_FUNCTION_TRACE (AcpiGetTimerDuration); 16771867Smsmith 16880062Smsmith 16977424Smsmith if (!TimeElapsed) 17071867Smsmith { 17171867Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 17271867Smsmith } 17371867Smsmith 17477424Smsmith /* 17571867Smsmith * Compute Tick Delta: 176138287Smarks * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. 17771867Smsmith */ 17871867Smsmith if (StartTicks < EndTicks) 17971867Smsmith { 18071867Smsmith DeltaTicks = EndTicks - StartTicks; 18171867Smsmith } 18277424Smsmith else if (StartTicks > EndTicks) 18371867Smsmith { 184167802Sjkim if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) 18571867Smsmith { 18691116Smsmith /* 24-bit Timer */ 18791116Smsmith 18873561Smsmith DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF); 18971867Smsmith } 19077424Smsmith else 19171867Smsmith { 19291116Smsmith /* 32-bit Timer */ 19391116Smsmith 19471867Smsmith DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks; 19571867Smsmith } 19671867Smsmith } 197138287Smarks else /* StartTicks == EndTicks */ 19873561Smsmith { 19973561Smsmith *TimeElapsed = 0; 20073561Smsmith return_ACPI_STATUS (AE_OK); 20173561Smsmith } 20271867Smsmith 20377424Smsmith /* 204138287Smarks * Compute Duration (Requires a 64-bit multiply and divide): 20571867Smsmith * 20691116Smsmith * TimeElapsed = (DeltaTicks * 1000000) / PM_TIMER_FREQUENCY; 20771867Smsmith */ 208138287Smarks Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * 1000000, 209138287Smarks PM_TIMER_FREQUENCY, &Quotient, NULL); 21071867Smsmith 211138287Smarks *TimeElapsed = (UINT32) Quotient; 21291116Smsmith return_ACPI_STATUS (Status); 21371867Smsmith} 21471867Smsmith 215167802SjkimACPI_EXPORT_SYMBOL (AcpiGetTimerDuration) 21671867Smsmith 217