hwtimer.c revision 278970
152419Sjulian/****************************************************************************** 252419Sjulian * 352419Sjulian * Name: hwtimer.c - ACPI Power Management Timer Interface 452419Sjulian * 552419Sjulian *****************************************************************************/ 652419Sjulian 752419Sjulian/* 852419Sjulian * Copyright (C) 2000 - 2015, Intel Corp. 952419Sjulian * All rights reserved. 1052419Sjulian * 1152419Sjulian * Redistribution and use in source and binary forms, with or without 1252419Sjulian * modification, are permitted provided that the following conditions 1352419Sjulian * are met: 1452419Sjulian * 1. Redistributions of source code must retain the above copyright 1552419Sjulian * notice, this list of conditions, and the following disclaimer, 1652419Sjulian * without modification. 1752419Sjulian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1852419Sjulian * substantially similar to the "NO WARRANTY" disclaimer below 1952419Sjulian * ("Disclaimer") and any redistribution must be conditioned upon 2052419Sjulian * including a substantially similar Disclaimer requirement for further 2152419Sjulian * binary redistribution. 2252419Sjulian * 3. Neither the names of the above-listed copyright holders nor the names 2352419Sjulian * of any contributors may be used to endorse or promote products derived 2452419Sjulian * from this software without specific prior written permission. 2552419Sjulian * 2652419Sjulian * Alternatively, this software may be distributed under the terms of the 2752419Sjulian * GNU General Public License ("GPL") version 2 as published by the Free 2852419Sjulian * Software Foundation. 2952419Sjulian * 3052419Sjulian * NO WARRANTY 3152419Sjulian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3252419Sjulian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3352419Sjulian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3452419Sjulian * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3552419Sjulian * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3652419Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3752419Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3852419Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3952419Sjulian * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4052419Sjulian * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4152419Sjulian * POSSIBILITY OF SUCH DAMAGES. 4252419Sjulian */ 4352419Sjulian 4452419Sjulian#define EXPORT_ACPI_INTERFACES 4552419Sjulian 4652419Sjulian#include <contrib/dev/acpica/include/acpi.h> 4752419Sjulian#include <contrib/dev/acpica/include/accommon.h> 4852419Sjulian 4952419Sjulian#define _COMPONENT ACPI_HARDWARE 5052562Sjulian ACPI_MODULE_NAME ("hwtimer") 5152419Sjulian 5252419Sjulian 5352419Sjulian#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 5452419Sjulian/****************************************************************************** 5552419Sjulian * 5652419Sjulian * FUNCTION: AcpiGetTimerResolution 5752419Sjulian * 5852419Sjulian * PARAMETERS: Resolution - Where the resolution is returned 5952419Sjulian * 6052419Sjulian * RETURN: Status and timer resolution 6152419Sjulian * 6252419Sjulian * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits). 6352419Sjulian * 6452419Sjulian ******************************************************************************/ 6552419Sjulian 6652419SjulianACPI_STATUS 6752419SjulianAcpiGetTimerResolution ( 6852419Sjulian UINT32 *Resolution) 6952441Sjulian{ 7052419Sjulian ACPI_FUNCTION_TRACE (AcpiGetTimerResolution); 7152419Sjulian 7252419Sjulian 7352419Sjulian if (!Resolution) 7452419Sjulian { 7552419Sjulian return_ACPI_STATUS (AE_BAD_PARAMETER); 7652419Sjulian } 7752419Sjulian 7852419Sjulian if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) 7952419Sjulian { 8052419Sjulian *Resolution = 24; 8152419Sjulian } 8252419Sjulian else 8352419Sjulian { 8452562Sjulian *Resolution = 32; 8552722Sjulian } 8652722Sjulian 8752419Sjulian return_ACPI_STATUS (AE_OK); 8852419Sjulian} 8952419Sjulian 9052419SjulianACPI_EXPORT_SYMBOL (AcpiGetTimerResolution) 9152419Sjulian 9252419Sjulian 9352419Sjulian/****************************************************************************** 9452419Sjulian * 9552419Sjulian * FUNCTION: AcpiGetTimer 9652419Sjulian * 9753042Sjulian * PARAMETERS: Ticks - Where the timer value is returned 9852419Sjulian * 9952419Sjulian * RETURN: Status and current timer value (ticks) 10052419Sjulian * 10152419Sjulian * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). 10252419Sjulian * 10352419Sjulian ******************************************************************************/ 10452419Sjulian 10552419SjulianACPI_STATUS 10652419SjulianAcpiGetTimer ( 10752562Sjulian UINT32 *Ticks) 10852419Sjulian{ 10952419Sjulian ACPI_STATUS Status; 11052419Sjulian 11152419Sjulian 11252419Sjulian ACPI_FUNCTION_TRACE (AcpiGetTimer); 11352419Sjulian 11452419Sjulian 11552419Sjulian if (!Ticks) 11652419Sjulian { 11752419Sjulian return_ACPI_STATUS (AE_BAD_PARAMETER); 11852562Sjulian } 11952419Sjulian 12052419Sjulian /* ACPI 5.0A: PM Timer is optional */ 12152419Sjulian 12252419Sjulian if (!AcpiGbl_FADT.XPmTimerBlock.Address) 12352419Sjulian { 12452562Sjulian return_ACPI_STATUS (AE_SUPPORT); 12552419Sjulian } 12652419Sjulian 12752419Sjulian Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock); 12852419Sjulian return_ACPI_STATUS (Status); 12952419Sjulian} 13052419Sjulian 13152419SjulianACPI_EXPORT_SYMBOL (AcpiGetTimer) 13252419Sjulian 13352419Sjulian 13452419Sjulian/****************************************************************************** 13552419Sjulian * 13652419Sjulian * FUNCTION: AcpiGetTimerDuration 13752419Sjulian * 13852419Sjulian * PARAMETERS: StartTicks - Starting timestamp 13952419Sjulian * EndTicks - End timestamp 14052419Sjulian * TimeElapsed - Where the elapsed time is returned 14152419Sjulian * 14252419Sjulian * RETURN: Status and TimeElapsed 14352419Sjulian * 14452419Sjulian * DESCRIPTION: Computes the time elapsed (in microseconds) between two 14552419Sjulian * PM Timer time stamps, taking into account the possibility of 14652419Sjulian * rollovers, the timer resolution, and timer frequency. 14752419Sjulian * 14852419Sjulian * The PM Timer's clock ticks at roughly 3.6 times per 14952419Sjulian * _microsecond_, and its clock continues through Cx state 15052562Sjulian * transitions (unlike many CPU timestamp counters) -- making it 15152562Sjulian * a versatile and accurate timer. 15252419Sjulian * 15352419Sjulian * Note that this function accommodates only a single timer 15452419Sjulian * rollover. Thus for 24-bit timers, this function should only 15552419Sjulian * be used for calculating durations less than ~4.6 seconds 15652419Sjulian * (~20 minutes for 32-bit timers) -- calculations below: 15752419Sjulian * 15852419Sjulian * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec 15952419Sjulian * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes 16052419Sjulian * 16152419Sjulian ******************************************************************************/ 16252419Sjulian 16352419SjulianACPI_STATUS 16452562SjulianAcpiGetTimerDuration ( 16552562Sjulian UINT32 StartTicks, 16652419Sjulian UINT32 EndTicks, 16752419Sjulian UINT32 *TimeElapsed) 16852419Sjulian{ 16952419Sjulian ACPI_STATUS Status; 17052419Sjulian UINT32 DeltaTicks; 17152419Sjulian UINT64 Quotient; 17252419Sjulian 17352419Sjulian 17452419Sjulian ACPI_FUNCTION_TRACE (AcpiGetTimerDuration); 17552419Sjulian 17652419Sjulian 17752419Sjulian if (!TimeElapsed) 17852419Sjulian { 17952419Sjulian return_ACPI_STATUS (AE_BAD_PARAMETER); 18052419Sjulian } 18152419Sjulian 18252419Sjulian /* ACPI 5.0A: PM Timer is optional */ 18352419Sjulian 18452419Sjulian if (!AcpiGbl_FADT.XPmTimerBlock.Address) 18552419Sjulian { 18652419Sjulian return_ACPI_STATUS (AE_SUPPORT); 18752419Sjulian } 18852419Sjulian 18952419Sjulian /* 19052419Sjulian * Compute Tick Delta: 19152419Sjulian * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. 19252419Sjulian */ 19352419Sjulian if (StartTicks < EndTicks) 19452419Sjulian { 19552419Sjulian DeltaTicks = EndTicks - StartTicks; 19652419Sjulian } 19752419Sjulian else if (StartTicks > EndTicks) 19852419Sjulian { 19952419Sjulian if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) 20052419Sjulian { 20152419Sjulian /* 24-bit Timer */ 20252419Sjulian 20352419Sjulian DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF); 20452419Sjulian } 20552419Sjulian else 20652419Sjulian { 20752419Sjulian /* 32-bit Timer */ 20852419Sjulian 20952419Sjulian DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks; 21052419Sjulian } 21152419Sjulian } 21252419Sjulian else /* StartTicks == EndTicks */ 21352419Sjulian { 21452419Sjulian *TimeElapsed = 0; 21552419Sjulian return_ACPI_STATUS (AE_OK); 21652419Sjulian } 21752419Sjulian 21852419Sjulian /* 21952419Sjulian * Compute Duration (Requires a 64-bit multiply and divide): 22052419Sjulian * 22152419Sjulian * TimeElapsed (microseconds) = 22252419Sjulian * (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY; 22352419Sjulian */ 22452419Sjulian Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * ACPI_USEC_PER_SEC, 225 ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL); 226 227 *TimeElapsed = (UINT32) Quotient; 228 return_ACPI_STATUS (Status); 229} 230 231ACPI_EXPORT_SYMBOL (AcpiGetTimerDuration) 232 233#endif /* !ACPI_REDUCED_HARDWARE */ 234