hwtimer.c revision 256281
11573Srgrimes/****************************************************************************** 21573Srgrimes * 31573Srgrimes * Name: hwtimer.c - ACPI Power Management Timer Interface 41573Srgrimes * 51573Srgrimes *****************************************************************************/ 61573Srgrimes 71573Srgrimes/* 8227753Stheraven * Copyright (C) 2000 - 2013, Intel Corp. 9227753Stheraven * All rights reserved. 10227753Stheraven * 11227753Stheraven * Redistribution and use in source and binary forms, with or without 12227753Stheraven * modification, are permitted provided that the following conditions 131573Srgrimes * are met: 141573Srgrimes * 1. Redistributions of source code must retain the above copyright 151573Srgrimes * notice, this list of conditions, and the following disclaimer, 161573Srgrimes * without modification. 171573Srgrimes * 2. Redistributions in binary form must reproduce at minimum a disclaimer 181573Srgrimes * substantially similar to the "NO WARRANTY" disclaimer below 191573Srgrimes * ("Disclaimer") and any redistribution must be conditioned upon 201573Srgrimes * including a substantially similar Disclaimer requirement for further 211573Srgrimes * binary redistribution. 221573Srgrimes * 3. Neither the names of the above-listed copyright holders nor the names 231573Srgrimes * of any contributors may be used to endorse or promote products derived 241573Srgrimes * from this software without specific prior written permission. 251573Srgrimes * 261573Srgrimes * Alternatively, this software may be distributed under the terms of the 271573Srgrimes * GNU General Public License ("GPL") version 2 as published by the Free 281573Srgrimes * Software Foundation. 291573Srgrimes * 301573Srgrimes * NO WARRANTY 311573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 321573Srgrimes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 331573Srgrimes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 341573Srgrimes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 351573Srgrimes * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 361573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 371573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 381573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 391573Srgrimes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 401573Srgrimes * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4192986Sobrien * POSSIBILITY OF SUCH DAMAGES. 4292986Sobrien */ 431573Srgrimes 441573Srgrimes#include <contrib/dev/acpica/include/acpi.h> 45132820Stjr#include <contrib/dev/acpica/include/accommon.h> 46121845Stjr 47129153Stjr#define _COMPONENT ACPI_HARDWARE 481573Srgrimes ACPI_MODULE_NAME ("hwtimer") 49227753Stheraven 501573Srgrimes 5161218Sache#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 52136609Stjr/****************************************************************************** 53136609Stjr * 541573Srgrimes * FUNCTION: AcpiGetTimerResolution 551573Srgrimes * 5657035Sobrien * PARAMETERS: Resolution - Where the resolution is returned 5757035Sobrien * 5857035Sobrien * RETURN: Status and timer resolution 5957035Sobrien * 6057035Sobrien * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits). 6157035Sobrien * 6257035Sobrien ******************************************************************************/ 6357035Sobrien 6457035SobrienACPI_STATUS 6557035SobrienAcpiGetTimerResolution ( 6657035Sobrien UINT32 *Resolution) 6757035Sobrien{ 6857035Sobrien ACPI_FUNCTION_TRACE (AcpiGetTimerResolution); 6957035Sobrien 7057035Sobrien 7157035Sobrien if (!Resolution) 7257035Sobrien { 7357035Sobrien return_ACPI_STATUS (AE_BAD_PARAMETER); 7457035Sobrien } 7557035Sobrien 7657035Sobrien if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) 7757035Sobrien { 7857035Sobrien *Resolution = 24; 7957035Sobrien } 8057035Sobrien else 8157035Sobrien { 8257035Sobrien *Resolution = 32; 8357035Sobrien } 8457035Sobrien 8557035Sobrien return_ACPI_STATUS (AE_OK); 8657035Sobrien} 8757035Sobrien 8857035SobrienACPI_EXPORT_SYMBOL (AcpiGetTimerResolution) 8957035Sobrien 9057035Sobrien 9157035Sobrien/****************************************************************************** 9257035Sobrien * 9357035Sobrien * FUNCTION: AcpiGetTimer 9457035Sobrien * 9557035Sobrien * PARAMETERS: Ticks - Where the timer value is returned 9657035Sobrien * 9757035Sobrien * RETURN: Status and current timer value (ticks) 9857035Sobrien * 9957035Sobrien * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). 10057035Sobrien * 10157035Sobrien ******************************************************************************/ 10257035Sobrien 10357035SobrienACPI_STATUS 10457035SobrienAcpiGetTimer ( 10557035Sobrien UINT32 *Ticks) 10657035Sobrien{ 10757035Sobrien ACPI_STATUS Status; 10857035Sobrien 10957035Sobrien 11057035Sobrien ACPI_FUNCTION_TRACE (AcpiGetTimer); 11157035Sobrien 11257035Sobrien 11357035Sobrien if (!Ticks) 11457035Sobrien { 11557035Sobrien return_ACPI_STATUS (AE_BAD_PARAMETER); 11657035Sobrien } 11757035Sobrien 11857035Sobrien /* ACPI 5.0A: PM Timer is optional */ 11957035Sobrien 12057035Sobrien if (!AcpiGbl_FADT.XPmTimerBlock.Address) 12157035Sobrien { 12257035Sobrien return_ACPI_STATUS (AE_SUPPORT); 12357035Sobrien } 12457035Sobrien 12557035Sobrien Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock); 12657035Sobrien return_ACPI_STATUS (Status); 12757035Sobrien} 12857035Sobrien 12957035SobrienACPI_EXPORT_SYMBOL (AcpiGetTimer) 13057035Sobrien 13157035Sobrien 13257035Sobrien/****************************************************************************** 13357035Sobrien * 13457035Sobrien * FUNCTION: AcpiGetTimerDuration 13557035Sobrien * 13657035Sobrien * PARAMETERS: StartTicks - Starting timestamp 13757035Sobrien * EndTicks - End timestamp 13857035Sobrien * TimeElapsed - Where the elapsed time is returned 13957035Sobrien * 14057035Sobrien * RETURN: Status and TimeElapsed 14157035Sobrien * 14257035Sobrien * DESCRIPTION: Computes the time elapsed (in microseconds) between two 14357035Sobrien * PM Timer time stamps, taking into account the possibility of 14457035Sobrien * rollovers, the timer resolution, and timer frequency. 14557035Sobrien * 14657035Sobrien * The PM Timer's clock ticks at roughly 3.6 times per 14757035Sobrien * _microsecond_, and its clock continues through Cx state 14857035Sobrien * transitions (unlike many CPU timestamp counters) -- making it 14957035Sobrien * a versatile and accurate timer. 15057035Sobrien * 15157035Sobrien * Note that this function accommodates only a single timer 15257035Sobrien * rollover. Thus for 24-bit timers, this function should only 15357035Sobrien * be used for calculating durations less than ~4.6 seconds 15457035Sobrien * (~20 minutes for 32-bit timers) -- calculations below: 15557035Sobrien * 15657035Sobrien * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec 15757035Sobrien * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes 15857035Sobrien * 15957035Sobrien ******************************************************************************/ 16057035Sobrien 16157035SobrienACPI_STATUS 16257035SobrienAcpiGetTimerDuration ( 16357035Sobrien UINT32 StartTicks, 16457035Sobrien UINT32 EndTicks, 16557035Sobrien UINT32 *TimeElapsed) 16657035Sobrien{ 16757035Sobrien ACPI_STATUS Status; 16857035Sobrien UINT32 DeltaTicks; 16957035Sobrien UINT64 Quotient; 17057035Sobrien 17157035Sobrien 17257035Sobrien ACPI_FUNCTION_TRACE (AcpiGetTimerDuration); 17357035Sobrien 17457035Sobrien 17557035Sobrien if (!TimeElapsed) 17657035Sobrien { 17757035Sobrien return_ACPI_STATUS (AE_BAD_PARAMETER); 17857035Sobrien } 17957035Sobrien 18057035Sobrien /* ACPI 5.0A: PM Timer is optional */ 18157035Sobrien 18257035Sobrien if (!AcpiGbl_FADT.XPmTimerBlock.Address) 18357035Sobrien { 1841573Srgrimes return_ACPI_STATUS (AE_SUPPORT); 1851573Srgrimes } 1861573Srgrimes 1871573Srgrimes /* 1881573Srgrimes * Compute Tick Delta: 1891573Srgrimes * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. 1901573Srgrimes */ 1911573Srgrimes if (StartTicks < EndTicks) 1921573Srgrimes { 1931573Srgrimes DeltaTicks = EndTicks - StartTicks; 1941573Srgrimes } 1951573Srgrimes else if (StartTicks > EndTicks) 1961573Srgrimes { 1971573Srgrimes if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) 1981573Srgrimes { 1991573Srgrimes /* 24-bit Timer */ 2001573Srgrimes 2011573Srgrimes DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF); 2021573Srgrimes } 2031573Srgrimes else 2041573Srgrimes { 2051573Srgrimes /* 32-bit Timer */ 2061573Srgrimes 2071573Srgrimes DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks; 2081573Srgrimes } 2091573Srgrimes } 2101573Srgrimes else /* StartTicks == EndTicks */ 2111573Srgrimes { 2121573Srgrimes *TimeElapsed = 0; 2131573Srgrimes return_ACPI_STATUS (AE_OK); 2141573Srgrimes } 2151573Srgrimes 2161573Srgrimes /* 2171573Srgrimes * Compute Duration (Requires a 64-bit multiply and divide): 2181573Srgrimes * 2191573Srgrimes * TimeElapsed (microseconds) = 2201573Srgrimes * (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY; 2211573Srgrimes */ 2221573Srgrimes Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * ACPI_USEC_PER_SEC, 2231573Srgrimes ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL); 2241573Srgrimes 2251573Srgrimes *TimeElapsed = (UINT32) Quotient; 2261573Srgrimes return_ACPI_STATUS (Status); 2271573Srgrimes} 2281573Srgrimes 2291573SrgrimesACPI_EXPORT_SYMBOL (AcpiGetTimerDuration) 2301573Srgrimes 2311573Srgrimes#endif /* !ACPI_REDUCED_HARDWARE */ 2321573Srgrimes